重复密钥 XOR 与已知明文攻击
XOR 本身不是加密方案。只要同一段密钥重复使用,并且攻击者能拿到一组明文和对应密文,就可以直接恢复密钥,再解密其他消息。靶场里它常以“自研安全消息系统”“测试加密数据”的形式出现。
识别特征
常见信号:
- 页面展示长十六进制字符串。
- 测试站泄露
testdata.txt、sample.txt、message.txt。 - 文档或注释里直接提到
XOR、key、encrypt。 - 同一系统里既有“历史密文”,又有“测试明文”。
基本原理
XOR 满足:
ciphertext = plaintext XOR key
key = ciphertext XOR plaintext
plaintext = ciphertext XOR key
如果密钥循环使用,恢复出来的 key 会呈现重复周期。
恢复最短循环密钥
python3 - <<'PY'
from binascii import unhexlify
ct = unhexlify("HEX_CIPHERTEXT_HERE")
pt = open("/tmp/plain.txt", "rb").read().rstrip(b"\n")
stream = bytes(c ^ p for c, p in zip(ct, pt))
for size in range(1, len(stream) + 1):
candidate = stream[:size]
if stream == (candidate * (len(stream) // size + 1))[:len(stream)]:
print(candidate.decode(errors="replace"))
break
PY
解密其他密文
python3 - <<'PY'
from binascii import unhexlify
key = b"recovered-key"
ct = unhexlify("HEX_CIPHERTEXT_HERE")
pt = bytes(c ^ key[i % len(key)] for i, c in enumerate(ct))
print(pt.decode(errors="replace"))
PY
结果判断
有效结果通常会出现:
- 可读英文句子。
- 用户名、密码、后台路径。
- 和页面主题一致的短语。
- 多段密文用同一个 key 能解出相似格式。
防坑点
- 明文和密文长度不一致时,只能恢复重叠部分。
- Hex 字符串必须先
unhexlify,不要直接对 ASCII 字符做 XOR。 - 文本末尾换行会影响最后一个字节,必要时用
rstrip(b"\n")。 - 如果恢复出的 key 没有短周期,可能不是重复密钥 XOR,或者明文不对应这段密文。
防御建议
- 不使用自研加密。
- 同一密钥流绝不能重复使用。
- 使用经过审计的 AEAD 模式,例如 AES-GCM、ChaCha20-Poly1305。
- 测试明文和密钥材料不能放在可访问 Web 路径。
来源案例
- The Planets: Earth:测试站泄露
testdata.txt,结合主站历史密文恢复重复密钥earthclimatechangebad4humans,进而登录后台。