单字节异或密码(python)



这是我目前正在学习的一个现代密码学类。

挑战是cryptopals挑战3:单字节异或密码,我正试图使用python 3来帮助完成这项任务。

我知道我应该对字符串进行异或运算并转换为英语。十六进制字符串为"1b3373331363f78151b7f2b7834313333d78397783772d363c78373e783a393b3736",可转换为十进制形式的"80674845337190240905117429187545859274380033785421566549206796642836053682239286"。

我已经对多个十六进制字节组合(2个十六进制数字)进行了异或运算,但我不知道如何将其转换为英语。在这一点上,这只是暴力和有教养的猜测吗?

我知道ETAOIN SHRDLU,但这并没有真正的帮助。

感谢您的时间和帮助。


添加:此外,我尝试了挑战#4,但这段代码似乎不起作用。但它确实适用于挑战#3,所以我很困惑。

挑战#3挑战#4

您可以使用binascii.hexlifybinascii.unhexlify将字节字符串转换为十六进制,反之亦然:

>>> import binascii
>>> binascii.hexlify(b'HELLO')  # to Hex
b'48454c4c4f'
>>> binascii.unhexlify('48454c4c4f')  # from Hex
b'HELLO'

使用str.isprintable,您可以筛选出不可打印的候选者:

>>> 'abcd'.isprintable()
True
>>> 'x00'.isprintable()
False
>>> 'x7f'.isprintable()
False

import binascii
encoded = binascii.unhexlify('1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736')
for xor_key in range(256):
decoded = ''.join(chr(b ^ xor_key) for b in encoded)
if decoded.isprintable():
print(xor_key, decoded)

基于@falsetru的答案,但只显示具有最多空格字符的解码字符串:

>>> encoded = '1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736'
>>> import binascii
>>> nums = binascii.unhexlify(encoded)
>>> strings = (''.join(chr(num ^ key) for num in nums) for key in range(256))
>>> max(strings, key=lambda s: s.count(' '))
"Cooking MC's like a pound of bacon"

您可以使用ETAOIN SHRDLU("英语中最常用的12个字母的大致频率顺序")来计算权重,而不是计算空格,但这里没有必要。

顺便说一句,我认为如果你和挑战联系在一起会很好。


编辑:或者,您可以尝试找到密钥(或一些最有前途的密钥),然后只使用该密钥(或这些少数密钥)进行解码。例如,假设计算空格将决定获胜者:

>>> encoded = '1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736'
>>> import binascii
>>> nums = binascii.unhexlify(encoded)
>>> key = max(nums, key=nums.count) ^ ord(' ')
>>> ''.join(chr(num ^ key) for num in nums)
"Cooking MC's like a pound of bacon"

这甚至可以很容易地手工完成(尽管挑战告诉你不要这样做)。

通过观察,您可以在编码字符串中找到"3737",因此它可以是"e"、"e"、"o"、"o"、"r"、"r",对于一个英语单词来说可能是?使用逆向工程,XOR结果显示"R"、"R"、"X"、"X"、"E"、"E"为潜在密钥。在尝试这些潜在的密钥后,您将获得"X"是密钥;-)

最新更新