Common Modulus 共模攻击¶
若同一 RSA 模数 \(n\) 被多个公钥指数复用,并使用不同指数加密同一明文:
\[
c_1\equiv m^{e_1}\pmod n,\qquad
c_2\equiv m^{e_2}\pmod n
\]
当 \(\gcd(e_1,e_2)=1\) 时,根据贝祖定理可求得整数 \(a,b\):
\[
ae_1+be_2=1
\]
于是:
\[
c_1^a c_2^b\equiv m^{ae_1+be_2}\equiv m\pmod n
\]
识别条件¶
- 两个公钥使用相同模数 \(n\);
- 两个指数 \(e_1,e_2\) 不同且互质;
- 两组密文对应同一个未经随机填充的明文;
- 通常要求 \(\gcd(c_i,n)=1\),以便负指数对应的模逆存在。
Python 实现¶
def extended_gcd(a, b):
if b == 0:
return a, 1, 0
gcd_value, x1, y1 = extended_gcd(b, a % b)
return gcd_value, y1, x1 - (a // b) * y1
def signed_mod_pow(base, exponent, modulus):
if exponent < 0:
base = pow(base, -1, modulus)
exponent = -exponent
return pow(base, exponent, modulus)
def common_modulus_attack(n, e1, c1, e2, c2):
gcd_value, a, b = extended_gcd(e1, e2)
if gcd_value != 1:
raise ValueError("e1 与 e2 必须互质")
return (
signed_mod_pow(c1, a, n)
* signed_mod_pow(c2, b, n)
) % n
p, q = 1009, 1013
n = p * q
m = 12345
e1, e2 = 17, 65537
c1, c2 = pow(m, e1, n), pow(m, e2, n)
print(common_modulus_attack(n, e1, c1, e2, c2))
特殊情况¶
若计算负指数时发现密文不存在模逆,即 \(\gcd(c_i,n)>1\),这个 GCD 本身可能已经给出了 \(n\) 的非平凡因子。
若 \(g=\gcd(e_1,e_2)>1\),贝祖组合通常只能得到 \(m^g\bmod n\),不能直接恢复 \(m\);只有在额外满足整数开根等条件时才能继续。
防护¶
- 不要让不同用户共享同一个 RSA 模数;
- 每个密钥对都应独立生成 \(p,q,n\);
- 使用 RSA-OAEP,使相同原始消息编码为不同的随机块。