现代密码学实验一:重复密钥XOR+SHA1密码破解挑战
运行代码及结果:
1. 重复密钥XOR:
import base64
# ========== 1. 汉明距离函数 ==========
def hamming_distance(b1, b2):
"""计算两个字节串的汉明距离(bit 不同数)"""
xor_result = bytes([a ^ b for a, b in zip(b1, b2)])
return sum(bin(byte).count('1') for byte in xor_result)
# 验证汉明距离
test1 = b"this is a test"
test2 = b"wokka wokka!!!"
print(f"汉明距离测试: {hamming_distance(test1, test2)}") # 应该输出 37
# ========== 2. 单字节 XOR 破解(英文评分) ==========
def break_single_byte_xor(byte_block):
"""对单个字节块进行单字节 XOR 破解,返回最佳密钥字节"""
# 英文字母频率(ETAOIN SHRDLU)
freq = {
'e': 12.7, 't': 9.1, 'a': 8.2, 'o': 7.5, 'i': 7.0, 'n': 6.7,
's': 6.3, 'h': 6.1, 'r': 6.0, 'd': 4.3, 'l': 4.0, 'c': 2.8,
'u': 2.8, 'm': 2.4, 'w': 2.4, 'f': 2.2, 'g': 2.0, 'y': 2.0,
'p': 1.9, 'b': 1.5, 'v': 1.0, 'k': 0.8, 'j': 0.2, 'x': 0.2,
'q': 0.1, 'z': 0.1
}
def score_text(text):
try:
text = text.decode('ascii')
except:
return -999999
text_lower = text.lower()
letter_count = sum(1 for c in text_lower if c.isalpha())
space_count = text_lower.count(' ')
if len(text) == 0:
return -999999
letter_ratio = letter_count / len(text)
if letter_ratio < 0.5:
return -1000 + letter_count
freq_score = sum(freq.get(c, 0) for c in text_lower if c.isalpha())
space_score = (space_count / len(text)) * 200
printable_score = sum(1 for c in text if 32 <= ord(c) <= 126) * 2
return freq_score + space_score + printable_score
best_score = -999999
best_key = 0
for key in range(256):
decrypted = bytes([b ^ key for b in byte_block])
score = score_text(decrypted)
if score > best_score:
best_score = score
best_key = key
return best_key
# ========== 3. 主破解函数 ==========
def break_repeating_key_xor(ciphertext_bytes):
# 步骤 1-4: 猜测密钥长度
key_sizes = []
for KEYSIZE in range(2, 41):
# 取前 4 个 KEYSIZE 块
blocks = [ciphertext_bytes[i * KEYSIZE:(i + 1) * KEYSIZE] for i in range(4)]
if len(blocks) < 2:
continue
distances = []
for i in range(len(blocks)):
for j in range(i + 1, len(blocks)):
if len(blocks[i]) == KEYSIZE and len(blocks[j]) == KEYSIZE:
dist = hamming_distance(blocks[i], blocks[j]) / KEYSIZE
distances.append(dist)
avg_distance = sum(distances) / len(distances)
key_sizes.append((avg_distance, KEYSIZE))
# 取最小的 3 个
key_sizes.sort()
candidates = [KEYSIZE for _, KEYSIZE in key_sizes[:3]]
print(f"候选密钥长度: {candidates}")
# 步骤 5-8: 对每个候选密钥长度尝试破解
best_plaintext = None
best_score = -999999
best_key = None
for KEYSIZE in candidates:
# 步骤 5: 分成 KEYSIZE 长度的块
blocks = [ciphertext_bytes[i::KEYSIZE] for i in range(KEYSIZE)]
# 步骤 6-7: 对每个转置块进行单字节 XOR 破解
key_bytes = []
for block in blocks:
key_byte = break_single_byte_xor(block)
key_bytes.append(key_byte)
key = bytes(key_bytes)
# 解密
plaintext = bytes([ciphertext_bytes[i] ^ key[i % KEYSIZE] for i in range(len(ciphertext_bytes))])
# 评分英文程度
try:
text = plaintext.decode('ascii')
letter_ratio = sum(1 for c in text if c.isalpha()) / len(text)
space_ratio = text.count(' ') / len(text)
score = letter_ratio * 1000 + space_ratio * 500
if score > best_score:
best_score = score
best_plaintext = plaintext
best_key = key
except:
pass
return best_key, best_plaintext
# ========== 主程序 ==========
if __name__ == "__main__":
# 读取 base64 文件
with open("6.txt", "r") as f:
base64_data = "".join(line.strip() for line in f)
ciphertext = base64.b64decode(base64_data)
print("正在破解重复密钥 XOR...")
key, plaintext = break_repeating_key_xor(ciphertext)
print(f"\n密钥: {key.decode('ascii')}")
print(f"\n明文:\n{plaintext.decode('ascii')[:500]}...")

破解思路:
核心原理:重复密钥XOR = 多个单字节XOR的组合
1. 猜密钥长度:计算密文块之间的汉明距离(二进制位不同的数量),距离最小的就是正确长度。因为正确长度下,块之间用同一密钥加密,差异最小。
2. 转置分组:按密钥长度把密文分成多列,使每列都只被一个密钥字节加密。
3. 逐列破解:每列用单字节XOR暴力破解(枚举0-255,英文频率评分),得到该列的密钥字节。
4. 拼出完整密钥:把所有列的密钥字节按顺序组合。
5. 解密:用密钥与密文做XOR,得到明文。
2. SHA1密码破解挑战:
import time
import itertools
import hashlib
target = '67ae1a64661ac8b4494666f58c4822408dd0a3e4'
keyChars = [('Q', 'q'), ('W', 'w'), ('%', '5'), ('(', '8'), ('=', '0'), ('I', 'i'), ('*', '+'), ('N', 'n')]
def check_mask(s):
return s[:3].count('0') > 0 and s[3:].count('0') > 0
if __name__ == "__main__":
stime = time.perf_counter()
for i in range(256):
mask = str(bin(i))[2:].zfill(8)
if not check_mask(mask):
continue
C = [keyChars[j][int(mask[j])] for j in range(8)]
for perm in itertools.permutations(C, 8):
password = ''.join(perm)
if hashlib.sha1(password.encode()).hexdigest() == target:
print('The key is:', password)
print('Timer:', round(time.perf_counter() - stime, 2), 's')
break
else:
continue
break

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)