这是我正在参加的现代密码学课程。
挑战是密码挑战3:单字节XOR密码,我正在尝试使用python 3来帮助完成此任务。
我知道我应该对字符串进行异或并转换为英语。十六进制字符串是" 1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"转换为" 806748453371902409051174291875458592743800337585421566549206796642836053682239286"十进制形式。
我对多个十六进制字节组合(2个十六进制数字)进行XOR'这个,但我不知道如何将其转换为英语。这只是蛮力和有根据的猜测吗?
我知道ETAOIN SHRDLU,但这并没有真正有用。
感谢您的时间和帮助。
增加: 另外,我尝试了挑战#4,但这段代码似乎不起作用。但它确实适用于挑战#3,所以我很困惑。
答案 0 :(得分:4)
建立@fattru的答案,但只显示空格字符最多的解码字符串:
>>> 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个字母的频率的大致顺序")而不是计算空格,但它可以使用the challenge。这里没有必要。
顺便说一下,如果你链接到{{3}},我认为它会很好。
编辑:或者,您可以尝试找到密钥(或一些最有前途的密钥),然后只使用该密钥(或那些几个密钥)进行解码。例如,假设计算空格将决定胜利者:
>>> 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"
这甚至可以很容易地手工完成(虽然挑战告诉你不要这样做)。
答案 1 :(得分:3)
您可以使用binascii.hexlify
,binascii.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)
答案 2 :(得分:0)
通过观察,您可以在编码字符串中找到“ 3737”,因此对于英语单词来说,它可以是“ e”,“ E”,“ o”,“ O”,“ r”,“ R”吗? 使用逆向工程,XOR结果显示“ R”,“ r”,“ X”,“ x”,“ E”,“ e”作为电位键。 在尝试了这些电位键之后,您将获得“ X”为键;-)