解决Cryptopals第一组第3题时遭遇‘b is an invalid keyword for max()’错误的技术求助
解决Cryptopals第1组第3题的调试建议
嘿,我看到你在Cryptopals第一组第3题卡壳了,那个max()的错误提示其实很好定位,咱们一步步来搞定它:
1. 先解决直接报错的问题
你调用max()的时候写了b = lambda h: score(xor(unhexstring, h)),但Python的max()函数用来指定排序规则的参数是key,不是b——这就是报错'b is an invalid keyword for max()'的根源。把参数名改成key就能解决这个语法错误:
max(range(255), key=lambda h: score(xor(unhexstring, h)))
2. 调整你的评分逻辑(这是核心问题)
解决语法错误后,你的评分函数score()还有几个逻辑问题,会导致你找不到正确的明文:
- 反转的参考字符串完全没用:你用了
commondata = b'This is a nice sentence for referal'[::-1],反转后的字节串根本没法正确匹配常用字符,应该换成英文里出现频率最高的字符集合(比如空格、e、t、a这些),甚至可以用频率加权的方式打分。 - 漏掉了关键的空格字符:你的字符过滤集合里没有包含空格,但空格是英文文本里出现频率最高的字符之一,这会直接把正确的明文打0分。
- 简单计数的评分不够精准:只是计数匹配到的字符,没有根据字符频率加权,很难区分正确密钥和相似得分的错误密钥。
修改后的评分函数示例
这里给你一个更贴合Cryptopals题目的评分函数,基于英文字符频率加权:
def score(data): # 英文字符频率(空格权重最高,然后是e、t等) char_freq = { b' ': 10, b'e': 9, b't': 8, b'a': 7, b'o': 6, b'i': 5, b'n': 4, b's': 3, b'h': 2, b'r': 2, b'd': 1, b'l': 1, b'c': 1, b'u': 1 } total = 0 for byte in data: # 转成小写字母或者空格来匹配频率表 lower_byte = bytes([byte.lower()]) if byte.isalpha() else bytes([byte]) total += char_freq.get(lower_byte, 0) # 如果出现不可打印字符,直接降低评分(可选,但能过滤垃圾结果) if not (32 <= byte <= 126 or byte in [9, 10, 13]): total -= 5 return total
3. 整合后的完整代码
把修改后的部分整合起来,代码应该能正常运行并输出正确的明文:
hexstring = '1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736' unhexstring = bytes.fromhex(hexstring) def xor(ciphertext, b): return bytes([x ^ b for x in ciphertext]) def score(data): char_freq = { b' ': 10, b'e': 9, b't': 8, b'a': 7, b'o': 6, b'i': 5, b'n': 4, b's': 3, b'h': 2, b'r': 2, b'd': 1, b'l': 1, b'c': 1, b'u': 1 } total = 0 for byte in data: lower_byte = bytes([byte.lower()]) if byte.isalpha() else bytes([byte]) total += char_freq.get(lower_byte, 0) if not (32 <= byte <= 126 or byte in [9, 10, 13]): total -= 5 return total # 找到得分最高的密钥 best_key = max(range(255), key=lambda h: score(xor(unhexstring, h))) # 解密并输出结果 print(xor(unhexstring, best_key).decode('utf-8'))
调试小技巧
- 先单独测试
xor函数:比如用已知的密钥和明文加密,再解密,确认函数逻辑正确。 - 测试
score函数:给它一段正常的英文文本,看看得分是否合理;再给它一段乱码,看看得分是否很低。 - 分步打印中间结果:比如打印每个密钥对应的得分和明文片段,能帮你快速定位哪一步出了问题。
内容的提问来源于stack exchange,提问作者Hi_ImTim
相关产品推荐
相关产品推荐

