https://cryptopals.com/sets/1/challenges/3中所述的加密挑战 是:
Single-byte XOR cipher
The hex encoded string:
1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
... has been XOR'd against a single character. Find the key, decrypt the message.
You can do this by hand. But don't: write code to do it for you.
How? Devise some method for "scoring" a piece of English plaintext. Character frequency is a good metric. Evaluate each output and choose the one with the best score.
这是解决方案吗? :
由于XOR的反转是XOR,我应该对字符串a-z
中的每个字符进行异或,但是我应该如何评分此字符串?字符频率与得分有何关系?
答案 0 :(得分:1)
请注意,该字符串是十六进制的,因此您必须将其解释为一系列十六进制字符(可能是ascii编码)。
1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
1b 37 37 33 31 36 3f 78
15 1b 7f 2b 78 34 31 33
3d 78 39 78 28 37 2d 36
3c 78 37 3e 78 3a 39 3b
37 36
77316?x+x413=x9x(7-6<x7>x:9;76
7 7 3 1 6 ? x
+ x 4 1 3
= x 9 x ( 7 - 6
< x 7 > x : 9 ;
7 6
评分基本上是将输出与我们期望的输出结果进行比较,并且是开发正式称为启发式的非常重要的概念;有根据的猜测/问题的解决方案。
在英语中,某些字母比其他字母更常见。 &#39; E&#39;经常引用英文文本中最常用的字母。字母频率表允许您检查字符串是否可能是英语。换句话说,得分解密字符串时的所有猜测。
为了好玩,您可以编写一个程序来制作频率表。它将扫描明文(例如这个答案),计算每个字母,然后显示使用该字母的文本的百分比。在汇总了足够的样本后,您将拥有自己的频率表!如果您不想编译自己的,请咨询wikipedia article,或搜索其他信息。
另一件需要注意的事情是,当我们转换为ascii时,我们会遗漏一些数据。某些数据变为无法显示的特殊字符。这提出了另一种可能的评分机制;某些特殊字符不会出现在键盘输入的字符串中,因此使用其中许多字符串的字符串不太可能是正确的。
至于如何对解决方案进行编码,您希望通过a-z
范围内的每个ascii字符对每个十六进制字符进行xor。请注意,每个&#39;使用了两次,因此您的代码中可能会有两个for
语句或循环结构。
根据XOR
函数的实现方式,减少迭代的一种聪明方法可能是将单个ascii字符复制足够的次数以匹配字符串的长度,然后XOR
这两个值。
在这里,我通过ascii&#39; a&#39;:
进行异或Input:
1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
Length of input:
34
Repeat (a in ascii) by length:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Then XOR:
input
repeat
Output:
zVVRPW^tzJUPR\XIVLW]V_[XZVW
看到很长一段时间过去了,我已经在python中为后代实现了一个解决方案。
import string
import re
in_hex = '1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736'
def take(n, s):
'''yield n-sized chunks from iterable s'''
for i in range(0, n, 2):
yield s[i:i+2]
def hex2str(s):
'''given an ascii string of single-byte hex literals, interpret as ascii'''
return bytes.fromhex(s).decode('ascii')
def string_xor(s, c):
'''given an ascii string s of hexadecimal values, xor each one by char c'''
c = ord(c) # dirty dynamic typing
return ''.join(map(lambda h: chr(ord(h) ^ c), s))
for letter in string.ascii_letters:
result = string_xor(hex2str(in_hex), letter)
# remove ascii control chars
pretty_result = re.sub(r'[\x00-\x1F]+', '', result)
# print the result and the corresponding letter used to decode
print(f'{letter}: {pretty_result}')
成功的路线:
X: Cooking MC's like a pound of bacon