我正在研究matasano加密挑战here
但是我在挑战6中遇到了困难,这可以很好地概述所需的步骤。我必须尝试找到密钥大小,将密文大小分解为密钥大小长度块,转置块以获得与密钥大小的每个字节对应的块,然后将转置块解析为好像它们是单个字符XOR密码。从概念上讲,这一切都是有道理的。但是对python来说还是个新手,我的程序并没有按照需要运行。我已经完成了,看起来下面的汉明距离函数就像它应该的那样,并且分解十六进制编码的文本也可以。但到了调用get_max_single_char_xor
的时候,我收到了一堆难以理解的文字。也许第二双眼睛可以帮助我弄清楚我做错了什么,或者为什么它没有给我可读的输出。
查看以下代码:
def calc_hamming_dist(str1, str2):
diff = 0
val = int(str1, 16) ^ int(str2, 16)
while(val != 0):
diff += 1
val &= val-1
return diff
def break_repeating_key_XOR(hex_text):
keysize = 2
key_hamming_val = []
hex_len = len(hex_text)
print 'hex_len: ' + str(hex_len)
for b in xrange(2, 40):
hamming_vals = 0
pos = 0
counter = 0
while(pos + 2*keysize <= hex_len):
key1 = hex_text[pos:pos+keysize]
pos += keysize
key2 = hex_text[pos:pos+keysize]
pos += keysize
hamming_vals += calc_hamming_dist(key1, key2)
counter += 1
hamming_vals = float(hamming_vals/float(counter))
key_hamming_val.append((float(hamming_vals/float(keysize)), keysize))
keysize += 1
print 'hamming_val length: ' + str(len(key_hamming_val))
key_hamming_val.sort()
for a in xrange(2, 38):
blocks1 = []
blocks2 = []
count = 0
key = ''
min_hamming, keysize_guess = key_hamming_val[a]
#for x in range(keysize_guess):
#blocks2.append('')
while count <= hex_len:
blocks1.append(hex_text[count:count+keysize_guess])
count += keysize_guess
print str(min_hamming) + ', ' + str(keysize_guess)
zzz = 0
for x in blocks1:
zzz += len(x)
#print blocks1
for x in range(keysize_guess):
count = 0
in_str = ''
while count < len(blocks1):
try:
in_str += (blocks1[count])[x]
except IndexError:
break
count += 1
#print in_str
blocks2.insert(x, in_str)
zzz = 0
for x in blocks2:
zzz += len(x)
#print blocks2
for y in blocks2:
if (len(y) % 2) != 0:
y = '0' + y
(score, words, key_guess) = get_max_single_char_xor(y)
#print ' ' + str(key_guess)
key += chr(key_guess)
print key + ' (' + str(len(key)) + ')'
一些注意事项:传入的hex_text是一串已编码的十六进制值。以下是另一个模块中调用的一些函数:
def score_plaintext(s, val):
letters = filter(lambda val: 'a'<=val<='z' or 'A'<=val<='Z', s)
#letters = filter(lambda val: ' '<=val<='~', s)
return float(len(letters)) / len(s)
def get_max_single_char_xor(val):
res = []
for i in range(256):
chrs = [chr(ord(s) ^ i) for s in val.decode('hex')]
res.append([score_plaintext(chrs, val), ''.join(chrs), i])
ret = sorted(res, key=lambda res: res[0], reverse=True)
for i in ret:
(score, words, key) = i
if all(c in string.printable for c in words):
return i
return max(res, key=lambda s: s[0])
基于其他一些挑战,上述两个功能应该可以正常运行。但我无法确定。
有人发现此代码存在任何问题吗?