x86 程序集:很难找到一个可以加密和解密十六进制值的好而短的算法

x86 assembly: Having hard time finding a good and short algorithm which can encrypt and decrypt hex values

我正在尝试在 x86 程序集中实现一种算法,该算法可以加密给定的十六进制值,然后在不到 20 到 30 行的时间内对其进行解密,但无济于事。

我还没有真正找到任何类型的算法来做这样的事情,在汇编中也是如此,希望你们中的任何人都有我可以使用的想法或算法。

我考虑过单独解密每个字母,但我知道我可能能够实施的唯一真正的加密是凯撒密码。但对于我要做的事情来说,这是很容易解密的方法。

我正在使用模拟器 8086。

谢谢!

所以你想要一个对称密码,其中需要相同的密钥来加密和解密? (即,在使用 Diffie-Helman 密钥交换或 public-密钥加密(如 RSA)或通过某些预先存在的秘密侧通道建立共享密钥后,您将使用的加密类型)。

显然,如果您自己设计它,您会 don't expect it to be actually secure, just hopefully non-trivial for an amateur to break by hand if you get it right and the application/protocol that uses it doesn't screw it up (e.g. leak the key, reuse keys insecurely, or generate weak keys). Real digital cryptography is hard; there's a reason the world spent years evaluating ciphers before standardizing on Rijndael as the winner to become AES in 2001,以及为什么它如此复杂并且以 128 位的块工作。将它用于 encrypt/decrypt 更长的消息需要选择各种技术中的一种来应用该分组密码,而不仅仅是分别对每个 128 位块重复完全相同的操作,例如密码块链接。 (然后攻击者可以判断明文是否有两个相同或不同的 128 位块。)


最简单的方法是用一些密钥对明文进行异或。再次这样做将解密,因为这就是异或的工作原理。

如果您对消息的每个字节或单词重复相同的短密钥,则相当于凯撒密码的数字;即使是业余爱好者也很容易破解。

如果您有一个与消息一样长的密钥,那么这是一个“one time pad”。 (除非您使用具有不同明文的相同密钥,否则您已经击败了安全性,因为攻击者可以将两个密文异或在一起以取消密钥,并获得两个明文的异或。选择明文攻击将完全击败它。 ) 但是,如果您从不重复使用真正随机的密钥,那么这是唯一 可证明 安全的密码学。当然它不是很有用,因为你需要发送者和接收者已经有足够的共享秘密数据。如果你派一个间谍带着一本密码本到野外很有用,对单独的计算机没有用 运行 无限期。

如果您从不重复使用密钥,那么带有巨型密钥的简单 XOR 是完美的,但如果您想重复使用密钥或使用短密钥,则比更复杂的加密要弱得多。


一个好的策略可能是使用 PRNG 将小密钥扩展为任意长度的字节流,您可以将消息与 进行异或。即密钥是随机数生成器的种子。 (并且是程序的单独输入,或者可以将一个特定的键硬编码到玩具程序中。)

这就是 Stream Ciphers RC4 / RC5 的工作方式,即它们是 CSPRNG:加密安全伪随机数生成器。

就像一次一密一样,如果攻击者知道正在发生这种情况,则可以通过重复使用相同的密钥来彻底击败它们。但很明显,如果您正在设计自己的密码,您不应该 任何 期望真正的安全性。尽管如此,与其他混合方式相比,将密钥硬编码到您的程序中对于这种策略来说会更糟。

对于这个玩具程序,您可以使用一个简单的 PRNG,它不是加密安全的,例如XORshift+。紧凑的 xorshift32+ 应该可以在 16 位 8086 上使用几个寄存器。我链接的主要站点只有 128 位和 256 位状态版本,但在 16 位 CPU.[=22= 上确实提到了 xorshift32+ ]

但是,任何旧的简单 PRNG might be ok for your use, maybe even as simple LCG as a multiply / add with a constant,模是 2^16 的隐式模,仅在 AX 中取 16 位结果。这只是一些说明。如果你关心真正的 8086 的性能,你会避免乘法(因为它很慢)。


要考虑的另一个主要策略 是旋转、XOR 和 ADD 的序列,就像现在已经过时的 DES。 https://en.wikipedia.org/wiki/Data_Encryption_Standard。 (也许移位,但旋转和异或很容易可逆,因为它们不会破坏信息。)

它的一个简化版本(例如,使用 32 位块,这样你就可以只用一对 adc ax,ax / adc dx,dx 指令循环一个)可能工作正常。

有一个微型加密算法 (wikipedia has a C version) which is based on Feistel rounds (shift two ways, add magic constants, xor together), and is intended to be cheap + simple to implement, although some weaknesses have been found in it. (Although it does have 128-bit keys and a 64-bit block-size.) Broken attempt at a 32-bit x86 asm implementation in this question.

在 8086 上移动 4 或 5 并不便宜(需要在 CL 中计数,除非你可以滥用 AAA 或用比 aam 16 更便宜的东西来拆分 4 位半字节,这将做硬件部门,甚至更慢)。如果您不关心完整的安全性,那么每块执行的次数远少于建议的 64 轮将有助于提高性能,但不一定有助于代码大小。

对于业余爱好者来说,使用相同的密钥加密不同的消息应该比使用流密码更容易破解这种设计的密码。对于经验丰富的密码学家。

您仍然可以使用 xorshift+ 之类的 PRNG 或更简单的方法在每一步中演化密钥,因此如果相同的 4 个字母碰巧对齐,它们不会每次都以相同的方式加密。或者,如果您不关心这一点并且需要代码大小说小,也许您会放弃。或者只是在每一步递增密钥,或者执行 cipher block chaining 将新块的明文与先前的密文进行异或。这只是 Wiki 文章的一部分,内容涉及对大量数据流使用分组密码算法的各种方法。

解密和加密在这个策略中不是同一个函数;你需要按相反的顺序做事。