RSA算法作为非对称加密的基石,其安全性建立在大整数分解难题之上。我们先来看RSA的数学本质:
核心公式:
c ≡ m^e mod Nm ≡ c^d mod N其中关键参数包括:
N = p*q(两个大素数的乘积)φ(N) = (p-1)(q-1)(欧拉函数)e*d ≡ 1 mod φ(N)(模逆关系)生成RSA密钥的典型流程:
python复制from Crypto.Util.number import getPrime
p = getPrime(1024)
q = getPrime(1024)
N = p * q
e = 65537 # 常用公钥指数
d = pow(e, -1, (p-1)*(q-1)) # 私钥
实际CTF中常见陷阱:当p和q非常接近时(|p-q|很小),可以通过费马分解快速破解:
python复制def fermat_factor(N):
a = isqrt(N) + 1
while True:
b2 = a*a - N
if is_square(b2):
return (a - isqrt(b2), a + isqrt(b2))
a += 1
攻击场景:同一明文m用相同N但不同e加密,且gcd(e1,e2)=1
数学原理:利用扩展欧几里得算法找到满足e1*s1 + e2*s2 = 1的整数s1,s2,则:
python复制m ≡ (c1^s1 * c2^s2) mod N
实战案例解析(以De1CTF2019为例):
python复制from gmpy2 import gcdext
def common_modulus(c1, c2, e1, e2, N):
gcd, s1, s2 = gcdext(e1, e2)
return pow(c1,s1,N) * pow(c2,s2,N) % N
关键验证点:必须确保两个加密指数互质,否则攻击无法成立。在CTF中常会给出e1和e2都是小素数的情况。
攻击条件:m^e < N时,直接开e次方即可解密
防御方案:必须使用填充标准(如OAEP),确保m足够大
当同一消息用相同小e和不同N加密时:
python复制def hastad_attack(ct_list, N_list, e):
from sympy.ntheory.modular import crt
m_e = crt(N_list, ct_list)[0]
return gmpy2.iroot(m_e, e)[0]
当d < (1/3)*N^(1/4)时,可以通过连分数展开快速破解:
python复制def wiener_attack(e, N):
convergents = continued_fraction(e/N).convergents()
for frac in convergents:
k, d = frac.numerator, frac.denominator
if k == 0: continue
phi = (e*d -1)//k
# 验证phi是否合理...
定理应用:当p为素数时,(p-1)! ≡ -1 mod p
实战案例(RoarCTF2019):
python复制A = 21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
B = 21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596
def wilson_prime(A, B):
fact = 1
for i in range(B+1, A):
fact = (fact * i) % A
return inverse(fact, A)
当p和q非常接近时(|p-q| ≈ √N):
python复制def fermat_factor(N):
a = gmpy2.isqrt(N) + 1
b2 = a*a - N
while not gmpy2.is_square(b2):
a += 1
b2 = a*a - N
return (a - gmpy2.isqrt(b2), a + gmpy2.isqrt(b2))
GWCTF2019的典型场景:
p和qc1 = F1 + F2和c2 = F1^3 + F2^3python复制from sympy import symbols, Eq, solve
F1, F2 = symbols('F1 F2')
eq1 = Eq(F1 + F2 - c1, 0)
eq2 = Eq(F1**3 + F2**3 - c2, 0)
solution = solve((eq1,eq2), (F1,F2))
密钥生成规范:
|p-q| > 2^(n/2)(n为模数位数)参数选择建议:
python复制def gen_strong_prime(bits):
while True:
p = getPrime(bits)
if isPrime((p-1)//2):
return p
加密注意事项:
e=3,推荐e=65537在CTF竞赛中,这些攻击手法的组合应用往往能破解看似复杂的RSA题目。理解每种攻击背后的数学原理,才能在实际场景中灵活运用。我曾在一个线下赛中遇到需要组合共模攻击和小指数攻击的题目,通过分析参数特征最终成功提取出flag——这正是密码学攻防的魅力所在。