反向已知异或加密算法
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 种可能的 K
和 K2
组合。
具体来说,如果 A = (E - (KEY ^ KEY2)) ^ KEY
,则 KEY2 = (E - (A ^ KEY)) ^ KEY
。对于给定的 (A,E)
对使用此公式,您可以轻松地遍历 KEY
的所有 256 个值并获得 KEY2
的相应值。对每对 plaintext/ciphertext 个字符重复此过程,并计算所有 (KEY,KEY2)
对结果集的交集。在明文和密文中有足够数量的字符,应该会给你一个唯一的结果。
我知道您将此问题标记为 c#,但在 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);
我有异或加解密算法,它的工作原理,就像这段代码
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 种可能的 K
和 K2
组合。
具体来说,如果 A = (E - (KEY ^ KEY2)) ^ KEY
,则 KEY2 = (E - (A ^ KEY)) ^ KEY
。对于给定的 (A,E)
对使用此公式,您可以轻松地遍历 KEY
的所有 256 个值并获得 KEY2
的相应值。对每对 plaintext/ciphertext 个字符重复此过程,并计算所有 (KEY,KEY2)
对结果集的交集。在明文和密文中有足够数量的字符,应该会给你一个唯一的结果。
我知道您将此问题标记为 c#,但在 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);