反向已知异或加密算法

Reverse known XOR encryption algorithm

我有异或加解密算法,它的工作原理,就像这段代码

    int Encryption(int A)
    {
        E = (A ^ KEY) + (KEY ^ KEY2);
        return E;
    }
    int Decryption(int E)
    {
        A = (E - (KEY ^ KEY2)) ^ KEY;
        return A; 
    }

我的问题是,如果我知道加密值和解密值,如何获取 KEY 和 KEY2 例子: 对于加密值 0x53,它应该具有解密值 0x47 对于加密值 0x5E,它应该具有解密值 0x4C 对于加密值 0x61,它应该具有解密值 0x49

备注 我试图为我丢失的笔记找回我的 KEY 和 KEY2

谢谢

Note: I will assume the encryption and decryption arithmetic are all done modulo 256.

由于您使用两个 8 位密钥加密和解密单个字节,因此此密码的密钥 space 比消息 space 大 256 倍。这意味着每个 (A,E) 对有 256 种可能的 KK2 组合。

具体来说,如果 A = (E - (KEY ^ KEY2)) ^ KEY,则 KEY2 = (E - (A ^ KEY)) ^ KEY。对于给定的 (A,E) 对使用此公式,您可以轻松地遍历 KEY 的所有 256 个值并获得 KEY2 的相应值。对每对 plaintext/ciphertext 个字符重复此过程,并计算所有 (KEY,KEY2) 对结果集的交集。在明文和密文中有足够数量的字符,应该会给你一个唯一的结果。

我知道您将此问题标记为 ,但在 Python 中做此类事情更容易。下面的代码可能不是很有效,但这并不重要,因为我们在这里只处理玩具密码。

def retrieve_keys(plain,cipher):
    # Initialize set with all 65536 possible key pairs
    key_pairs = set([(x,y) for x in range(256) for y in range(256)])
    # Intersect this set with the set of 256 possible key pairs for
    # each plaintext/ciphertext pair
    for i in range(len(plain)):
        a, e = ord(plain[i]), ord(cipher[i])
        s = set([])
        # if a = (e - (key ^ key2)) ^ key, then key2 = (e - (a ^ key)) ^ key
        for key in range(256):
            s.add((key, ((e - (a ^ key)) % 256) ^ key))
        key_pairs = key_pairs.intersection(s)
    # Print out the remaining set of possible key pairs
    for kp in key_pairs:
        print "KEY=%d, KEY2=%d" % kp

# Example (should output "KEY=117, KEY2=80" and "KEY=245, KEY2=80"):
plaintext  = "Hello world, this is a test"
ciphertext = "b5>>?z'?,>6~z&BA+zA+z9z&5+&"
retrieve_keys(plaintext,ciphertext)

编辑: Eric Lippert 建议使用以下 C# 代码:

foreach (var kp in 
  Enumerable.Range(0, plain.Length).Aggregate(
    ( from x in Enumerable.Range(0, 256) 
      from y in Enumerable.Range(0, 256) 
      select new { x, y }).ToList(), 
    (pairs, i) => pairs.Intersect(
      from x in Enumerable.Range(0, 256) 
      select new { x, y = 
        ((cipher[i] - (plain[i] ^ x)) % 256) ^ x }).ToList()))
  Console.WriteLine(kp);