LitCTF2026 密码方向详细题解
字数 1874
更新时间 2026-06-01 23:04:52
LitCTF2026 密码方向详细题解教学文档
一、概述
本文档基于LitCTF2026密码方向赛题,涵盖四道典型题目:异或密钥重用攻击、ElGamal加密体制、RSA邻近素数分解、AES部分密钥爆破。适合密码学初学者练习基础概念和常见攻击手法。
二、题目一:lit_xor_two_story —— 异或密钥重用攻击
核心知识点
- 异或性质:
a ⊕ b = c,则a ⊕ c = b,b ⊕ c = a - 密钥重用漏洞:若同一密钥流加密多个明文,已知一个明文即可恢复密钥,进而解密其他密文
题目条件
- 两个密文
c1、c2(十六进制字符串) - 已知明文
M2的长度为40字节,内容为b"litctf2026_xor_keystream_reuse_40bytes!!" - 两个密文长度均为40字节
解题步骤
-
将十六进制密文转换为字节
c1 = bytes.fromhex("5f70a847ce12759e156e3cad1aa9530a119386a02ffc1c31bf14ab7a0a82ccc108f8476f75c98a28") c2 = bytes.fromhex("5f70a847ce123cc153283ca710ae7f042b8490a238eb2228970fad6a2694f2985dc5557e69e5f474") -
定义异或函数
def xor_bytes(a: bytes, b: bytes) -> bytes: return bytes(x ^ y for x, y in zip(a, b)) -
利用已知明文恢复密钥流
M2_KNOWN = b"litctf2026_xor_keystream_reuse_40bytes!!" k = xor_bytes(M2_KNOWN, c2) # k = M2 ⊕ c2 -
用密钥流解密第一个密文
m = xor_bytes(c1, k) # m = c1 ⊕ k print(m)
原理说明
由于 c1 = m1 ⊕ k,c2 = m2 ⊕ k,因此:
k = m2 ⊕ c2m1 = c1 ⊕ k = c1 ⊕ (m2 ⊕ c2)
三、题目二:lit_elgamal_handshake —— ElGamal加密体制
核心知识点
ElGamal加密系统参数
| 参数 | 含义 | 说明 |
|---|---|---|
p |
大素数 | 有限域大小 |
g |
生成元 | 满足 g^q ≡ 1 mod p 且 g ≠ 1 |
x |
私钥 | 从 [1, p-2] 随机选取 |
y |
公钥 | y = g^x mod p |
加密过程
- 选择随机数
r ∈ [1, p-2],满足gcd(r, p-1) = 1 - 计算
c₁ = g^r mod p - 计算
c₂ = (m · y^r) mod p - 密文为
(c₁, c₂)
解密过程
- 计算共享秘密
s = c₁^x mod p - 计算
s的模逆元s⁻¹ - 恢复明文
m = (c₂ · s⁻¹) mod p
题目条件
- 已知所有公开参数:
p,g,y,c1,c2 - 私钥
x已被泄露输出
解题步骤
from Crypto.Util.number import *
p = 9000784855376359808051354825193962042770028561343848432778443672755982397391267124312572697249531643069409873722736348916207732622884411596948807031140651
g = 3
y = 269130883529708333054320571854006406481346665463416017026083074488011546059928157925990665431751017523964760326934454181952822744463714981243407307134357
c1 = 5245857426274383693193378669425243235151460522527004924092730024427525619244222247576829782077334810173274945751493387545849499010408499951268967774043627
c2 = 6059939492718262451327758167005534191200936922719178843825888167191062504030471358635203794720371216217447404436172970111033824674731063386612549785069654
x = 633366293219022684108628483753423657477324253833657141033762971761747669344649667887002347907882241246119223126492863291886751205505360049793728851371884
# 解密
s = power_mod(c1, x, p)
ss = inverse(s, p)
m = power_mod(c2 * ss, 1, p)
print(m)
关键说明
本题特殊之处在于私钥 x 被意外输出,使得原本需要保密的信息暴露,从而可直接按标准解密流程恢复明文。
四、题目三:lit_rsa_neighbor —— RSA邻近素数分解
核心知识点
- RSA安全性基础:大整数分解困难性
- 邻近素数攻击:当
p和q非常接近时,可以通过平方根附近爆破分解
解题思路
- 计算
n的平方根sqrt(n) - 在平方根附近枚举整数,尝试整除
n - 找到因子后即可计算私钥指数
d并解密
实际解法
- 可使用工具 yafu 自动分解
- 也可手动编写爆破脚本
通用RSA解密流程
from Crypto.Util.number import *
# 假设已分解得到 p, q
n = p * q
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))
判断依据
若加密过程中 p 和 q 取值相近,则 n 的平方根附近必然存在因子,这是RSA实现中的常见安全隐患。
五、题目四:lit_tiny_key_aes —— AES部分密钥爆破
核心知识点
- AES对称加密:加解密使用相同密钥
- ECB模式:每个数据块独立加密,无初始向量
- 部分密钥爆破:当密钥大部分已知时,可枚举未知部分
题目条件
- 密钥前缀已知:
b"LitCTF2026!!!"(共12字节) - 密钥总长度16字节(AES-128),未知后4字节
- 密文已知(48字节,对应3个AES块)
解题步骤
import itertools
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
KEY_PREFIX = b"LitCTF2026!!!"
ciphertext = b"\x0c\xdb'`\xc91\xf7\x05\x91+\x0fM\xed\xbc\x9b\xf1\xd8D\xcd\xfd\x0c\xb9\xb6\xb2J<\x86\x19\x06K\xb3\xa2\xa4\x18\x87<v\xac\x1bbu#\xaa\xb5I\x7f\xd8\xd3"
for suffix in itertools.product(range(256), repeat=3):
key = KEY_PREFIX + bytes(suffix)
cipher = AES.new(key, AES.MODE_ECB)
decrypted = cipher.decrypt(ciphertext)
if decrypted.startswith(b"litctf{"):
try:
flag = unpad(decrypted, AES.block_size)
print(f"Flag: {flag.decode('utf-8')}")
break
except (ValueError, KeyError):
continue
关键要点
- 枚举空间:
256³ = 16,777,216,完全可行 - 判定条件:解密结果以
b"litctf{"开头 - 去填充:使用
unpad移除PKCS7填充,确保正确性
六、总结
| 题目 | 攻击类型 | 关键技巧 |
|---|---|---|
| lit_xor_two_story | 异或密钥重用 | 已知明文恢复密钥流 |
| lit_elgamal_handshake | 私钥泄露 | 直接使用泄露私钥解密 |
| lit_rsa_neighbor | RSA因数分解 | 平方根附近爆破 |
| lit_tiny_key_aes | 部分密钥爆破 | 枚举少量未知字节 |
这四道题目难度适中,覆盖了密码学中常见的经典攻击场景,适合作为密码方向入门训练。
相似文章
相似文章