对RSA私钥泄露攻击

RSA基本关系

核心方程

  • \(n = p \cdot q\),其中\(p\)\(q\)为大素数
  • \(\phi(n) = (p-1)(q-1)\)
  • \(e \cdot d \equiv 1 \pmod{\phi(n)} \Rightarrow e \cdot d = k \cdot \phi(n) + 1\)

关键推导

由欧拉定理:对于任意\(a\)满足\(\gcd(a, n) = 1\),有:

\[a^{\phi(n)} \equiv 1 \pmod{n} \]

代入\(e \cdot d = k \cdot \phi(n) + 1\)得:

\[a^{e \cdot d - 1} = a^{k \cdot \phi(n)} = (a^{\phi(n)})^k \equiv 1^k \equiv 1 \pmod{n} \]

因此对任意与\(n\)互素的\(a\)

\[a^{e \cdot d - 1} \equiv 1 \pmod{n} \quad \]

攻击原理推导

步骤1:指数分解

设:

\[e \cdot d - 1 = 2^s \cdot t \]

其中\(t\)为奇数(不断除以2直到得到奇数)

步骤2:构建平方序列

由核心等式:\(a^{2^s \cdot t} \equiv 1 \pmod{n}\)

定义序列:

\[\begin{aligned} x_0 &= a^t \pmod{n} \\ x_1 &= x_0^2 = a^{2t} \pmod{n} \\ x_2 &= x_1^2 = a^{2^2 t} \pmod{n} \\ &\vdots \\ x_s &= x_{s-1}^2 = a^{2^s t} \equiv 1 \pmod{n} \end{aligned} \]

步骤3:寻找非平凡平方根

引理1:如果存在\(i\)\(1 \leq i \leq s\))使得:

\[x_i \equiv 1 \pmod{n} \quad \text{且} \quad x_{i-1} \not\equiv \pm 1 \pmod{n} \]

\(x_{i-1}\)\(1\)\(n\)的一个非平凡平方根。

证明:

  • \(x_i = x_{i-1}^2 \equiv 1 \pmod{n}\)\(x_{i-1}^2 \equiv 1 \pmod{n}\)
  • \(x_{i-1} \not\equiv \pm 1 \pmod{n}\) ⇒ 平方根是非平凡的

非平凡平方根分解\(n\)

定理1

如果\(x\)满足:

  1. \(x^2 \equiv 1 \pmod{n}\)
  2. \(x \not\equiv \pm 1 \pmod{n}\)

\(\gcd(x-1, n)\)\(\gcd(x+1, n)\)都是\(n\)的非平凡因子。

证明:

  1. \(x^2 \equiv 1 \pmod{n}\)\(x^2 - 1 \equiv 0 \pmod{n}\)\(n \mid (x-1)(x+1)\)
  2. \(x \not\equiv 1 \pmod{n}\)\(n \nmid (x-1)\)
  3. \(x \not\equiv -1 \pmod{n}\)\(n \nmid (x+1)\)
  4. \(n = p \cdot q\)整除\((x-1)(x+1)\),但\(p\)\(q\)不能同时整除\((x-1)\)\((x+1)\)(否则会整除它们的差\(2\)
  5. 因此:
    • 情况A:\(p \mid (x-1)\)\(q \mid (x+1)\)
    • 情况B:\(p \mid (x+1)\)\(q \mid (x-1)\)
  6. 无论哪种情况,\(\gcd(x-1, n)\)\(\gcd(x+1, n)\)中至少有一个是\(n\)的非平凡因子

成功分析

\(\mathbb{Z}_n\)中,方程\(x^2 \equiv 1 \pmod{n}\)有4个解:

  1. \(x \equiv 1 \pmod{p}\)\(x \equiv 1 \pmod{q}\)\(x \equiv 1 \pmod{n}\)
  2. \(x \equiv 1 \pmod{p}\)\(x \equiv -1 \pmod{q}\)\(x \equiv c_1 \pmod{n}\)
  3. \(x \equiv -1 \pmod{p}\)\(x \equiv 1 \pmod{q}\)\(x \equiv c_2 \pmod{n}\)
  4. \(x \equiv -1 \pmod{p}\)\(x \equiv -1 \pmod{q}\)\(x \equiv -1 \pmod{n}\)

其中\(c_1\)\(c_2\)是非平凡解。

成功率分析

设:

  • \(p-1 = 2^{\alpha} u\)\(u\)为奇数
  • \(q-1 = 2^{\beta} v\)\(v\)为奇数
  • 对于随机\(a\),在\(\mathbb{Z}_p^*\)\(a\)的阶为\(2^{\gamma_p} w_p\)
  • \(\mathbb{Z}_q^*\)\(a\)的阶为\(2^{\gamma_q} w_q\)

则:

\[i_p = \max(0, \alpha - \gamma_p), \quad i_q = \max(0, \beta - \gamma_q) \]

\(i_p \neq i_q\)时,算法成功概率至少为\(1/2\)

完整算法描述

输入

  • RSA公钥\((n, e)\)
  • 私钥\(d\)

输出

  • \(n\)的素因子\(p\)\(q\)

算法步骤

def factorize_with_d(n, e, d):
    # 1. 计算并分解指数
    M = e * d - 1
    s = 0
    t = M
    while t % 2 == 0:
        t //= 2
        s += 1
    
    # 2. 随机尝试
    for attempt in range(max_attempts):
        a = random.randint(2, n-1)
        
        # 如果a与n不互素,直接找到因子
        g = gcd(a, n)
        if g > 1:
            return g, n // g
        
        # 3. 计算平方序列
        x = pow(a, t, n)
        
        # 4. 寻找非平凡平方根
        for i in range(s):
            x_prev = x
            x = (x * x) % n
            
            if x == 1 and x_prev != 1 and x_prev != n-1:
                # 找到非平凡平方根
                p = gcd(x_prev - 1, n)
                q = gcd(x_prev + 1, n)
                return (p, n//p) if p > 1 else (q, n//q)
            
            if x == n-1:
                break  # 平凡情况,重新选择a
    
    return None  # 失败

示例

\(n = 15 = 3 \cdot 5\)\(\phi(n) = 8\)
已知\(e=3\),则\(d=3\)(因为\(3 \times 3 = 9 \equiv 1 \pmod{8}\)

  1. 计算指数:

    \[M = e \cdot d - 1 = 9 - 1 = 8 = 2^3 \cdot 1 \]

    所以\(s=3\)\(t=1\)

  2. 选择\(a=2\)

    • \(x_0 = 2^1 \bmod 15 = 2\)
    • \(x_1 = 2^2 \bmod 15 = 4\)
    • \(x_2 = 4^2 \bmod 15 = 1\)
  3. 发现非平凡平方根:

    • \(i=2\)\(x_2 = 1\)
    • \(x_1 = 4 \neq \pm 1 \pmod{15}\)
    • 因此\(x_1 = 4\)是非平凡平方根
  4. 计算因子:

    • \(\gcd(4-1, 15) = \gcd(3, 15) = 3\)\(p=3\)
    • \(q = 15/3 = 5\)
  5. 验证:\(3 \times 5 = 15\)

实现

rsa_d_leakage_attack
"""
RSA分解算法 - 已知解密指数d和公钥(n, e)分解n

当已知RSA的解密指数d和公钥(n, e)时,可以通过以下方法分解n:
1. 利用 ed ≡ 1 (mod φ(n)) 的关系
2. 得出 ed - 1 = kφ(n) 
3. 随机构造一个数a,计算a^k mod n
4. 通过寻找非平凡的平方根来分解n
"""

import random
def extended_gcd(a, b):
    if a == 0:
        return b, 0, 1
    gcd, x1, y1 = extended_gcd(b % a, a)
    x = y1 - (b // a) * x1
    y = x1
    return gcd, x, y


def mod_inverse(a, m):
    gcd, x, _ = extended_gcd(a % m, m)
    if gcd != 1:
        raise ValueError()
    return (x % m + m) % m


def power_mod(base, exp, mod):
    result = 1
    base = base % mod
    while exp > 0:
        if exp % 2 == 1:
            result = (result * base) % mod
        exp = exp >> 1
        base = (base * base) % mod
    return result


def gcd(a, b):
    while b:
        a, b = b, a % b
    return a


def factorize_with_d(n, e, d):
    """
    利用已知的解密指数d分解RSA模数n
    """
    print(f"开始分解: n = {n}, e = {e}, d = {d}")
    ed_minus_1 = e * d - 1
    print(f"步骤1: 计算 ed - 1 = {e} * {d} - 1 = {ed_minus_1}")
    s = 0
    t = ed_minus_1
    while t % 2 == 0:
        t //= 2
        s += 1
    print(f"步骤2: 将 ed - 1 分解为 2^{s} * {t} 的形式")
    # 随机选择一个数a,使得 2 <= a <= n-1
    attempts = 0
    max_attempts = 100  #limit
    
    while attempts < max_attempts:
        a = random.randint(2, n - 1)
        print(f"\n尝试 #{attempts + 1}: 选择 a = {a}")
        g = gcd(a, n)
        if g > 1:
            print(f"  找到因子: gcd({a}, {n}) = {g}")
            return g, n // g
        x = power_mod(a, t, n)
        print(f"  计算 x = {a}^{t} mod {n} = {x}")
        
        #x ≡ 1 (mod n) 或 x ≡ -1 (mod n)
        if x == 1 or x == n - 1:
            print(f"  x ≡ {x} (mod {n}), 重新选择a")
            attempts += 1
            continue
        # 迭代计算 x 的平方,直到找到非平凡平方根或达到终止条件
        found = False
        for i in range(s):
            x_prev = x
            x = (x * x) % n
            print(f"  第{i+1}次迭代: x = {x_prev}^2 mod {n} = {x}")
            
            # 如果 x ≡ 1 (mod n) 且 x_prev ≠ 1, n-1,则找到了非平凡平方根
            if x == 1 and x_prev != 1 and x_prev != n - 1:
                print(f"  找到非平凡平方根: {x_prev}^2 ≡ 1 (mod {n})")
                
                # 计算 gcd(x_prev - 1, n) 和 gcd(x_prev + 1, n)
                factor1 = gcd(x_prev - 1, n)
                factor2 = gcd(x_prev + 1, n)
                
                print(f"  计算 gcd({x_prev} - 1, {n}) = gcd({x_prev - 1}, {n}) = {factor1}")
                print(f"  计算 gcd({x_prev} + 1, {n}) = gcd({x_prev + 1}, {n}) = {factor2}")
                
                if factor1 > 1 and factor1 < n:
                    print(f"  找到因子: p = {factor1}, q = {n // factor1}")
                    return factor1, n // factor1
                elif factor2 > 1 and factor2 < n:
                    print(f"  找到因子: p = {factor2}, q = {n // factor2}")
                    return factor2, n // factor2
                else:
                    print("  没有找到非平凡因子,继续尝试")
                    
                found = True
                break
            elif x == n - 1:
                print(f"  x ≡ -1 (mod {n}), 重新选择a")
                break
        
        if found:
            break
            
        attempts += 1
    
    print(f"经过{max_attempts}次尝试后未能分解n")
    return None


def verify_rsa_factors(n, e, d, p, q):
    print(f"\n验证分解结果:")
    print(f"n = {n}")
    print(f"p = {p}")
    print(f"q = {q}")
    print(f"p * q = {p * q}")
    
    if p * q == n:
        print("验证通过")
    else:
        print("验证失败")
        return False
    
    phi = (p - 1) * (q - 1)
    print(f"φ(n) = ({p} - 1) * ({q} - 1) = {phi}")
    
    if (e * d) % phi == 1:
        print(f"验证通过: {e} * {d} = {(e * d)}, ({e * d}) mod {phi} = {(e * d) % phi}")
    else:
        print(f"验证失败: {e} * {d} = {(e * d)}, ({e * d}) mod {phi} = {(e * d) % phi}")
        return False
    
    return True


def main():
    print("RSA分解算法 - 已知解密指数d和公钥(n, e)分解n")
    p1, q1 = 61, 53
    n1 = p1 * q1
    phi1 = (p1 - 1) * (q1 - 1)
    e1 = 17
    d1 = mod_inverse(e1, phi1)
    print(f"原始参数: p = {p1}, q = {q1}, n = {n1}, e = {e1}, d = {d1}")
    result1 = factorize_with_d(n1, e1, d1)
    if result1:
        p_found, q_found = result1
        verify_rsa_factors(n1, e1, d1, p_found, q_found)
    else:
        print("分解失败")

    try:
        n = int(input("RSA模数n: "))
        e = int(input("公钥指数e: "))
        d = int(input("解密指数d: "))
        print(f"\n输入参数: n = {n}, e = {e}, d = {d}")
        
        result2 = factorize_with_d(n, e, d)
        if result2:
            p_found, q_found = result2
            success = verify_rsa_factors(n, e, d, p_found, q_found)
            if success:
                print(f"\n成功分解: n = {p_found} * {q_found}")
            else:
                print("\n分解结果验证失败")
        else:
            print("分解失败")
            
    except ValueError:
        print("输入格式错误,请输入有效的整数")
    except KeyboardInterrupt:
        pass
posted @ 2026-01-01 20:57  lumiere_cloud  阅读(3)  评论(0)    收藏  举报