RSA之初学维纳攻击

当RSA公钥中的指数e过大或过小时,Wiener's Attack可能威胁到RSA的安全性。如果满足特定条件,攻击者能在多项式时间内分解n。文章介绍了如何在不分解n的情况下,利用Wiener攻击求解私钥d,通过连分数展开计算渐进分数,从而找到d的值。给出了具体的e和n值,并提到实际操作中涉及的数学计算较为复杂。

Wiener’s Attack

适用情况:e过大或过小。

在e过大或过小的情况下,可使用算法从e中快速推断出d的值。

Wiener 表示如果满足:

d<1/3n1/4

那么一种基于连分数的特殊攻击类型就可以危害 RSA 的安全。此时需要满足:

q<p<2q

如果满足上述条件,通过 Wiener Attack 可以在多项式时间中分解 n,思路如下:

N = pq

φ(n)=(p−1)(q−1)=pq−(p+q)+1=N−(p+q)+1

∵p, q 非常大 ,
∴pq≫p+q,
∴φ(n)≈N

∵ed≡1modφ(n),
∴ed−1=kφ(n),
这个式子两边同除 dφ(n)

可得:

eφ(n)−kd=1dφ(n)

∵φ(n)≈N,
∴eN−kd=1dφ(n),同样 dφ(n) 是一个很大的数,所以 eN 略大于 kd, e 和 N 是我们是知道的,公钥中给我们的,所以我们计算出 eN后,比它略小的 kd 用计算 eN 的连分数展开,依次算出这个分数每一个渐进分数,由于 eN 略大于 kd,wiener 证明了,该攻击能精确的覆盖 kd。

例题:
在不分解n的前提下,求d。

给定:

e = 14058695417015334071588010346586749790539913287499707802938898719199384604316115908373997739604466972535533733290829894940306314501336291780396644520926473

n = 33608051123287760315508423639768587307044110783252538766412788814888567164438282747809126528707329215122915093543085008547092423658991866313471837522758159

说明过程。

按照求解的渐进分数的分子分母分别对应减数的分子分母,从头将所有的渐进分数的分子分母求解出来。

由于水平限制,我能看懂代码,但是写不出来,以下内容来自搬运。

import gmpy2
def transform(x,y):       #使用辗转相处将分数 x/y 转为连分数的形式
    res=[]
    while y:
        res.append(x//y)
        x,y=y,x%y
    return res
    
def continued_fraction(sub_res):
    numerator,denominator=1,0
    for i in sub_res[::-1]:      #从sublist的后面往前循环
        denominator,numerator=numerator,i*numerator+denominator
    return denominator,numerator   #得到渐进分数的分母和分子,并返回

    
#求解每个渐进分数
def sub_fraction(x,y):
    res=transform(x,y)
    res=list(map(continued_fraction,(res[0:i] for i in range(1,len(res)))))  #将连分数的结果逐一截取以求渐进分数
    return res

def get_pq(a,b,c):      #由p+q和pq的值通过维达定理来求解p和q
    par=gmpy2.isqrt(b*b-4*a*c)   #由上述可得,开根号一定是整数,因为有解
    x1,x2=(-b+par)//(2*a),(-b-par)//(2*a)
    return x1,x2

def wienerAttack(e,n):
    for (d,k) in sub_fraction(e,n):  #用一个for循环来注意试探e/n的连续函数的渐进分数,直到找到一个满足条件的渐进分数
        if k==0:                     #可能会出现连分数的第一个为0的情况,排除
            continue
        if (e*d-1)%k!=0:             #ed=1 (mod φ(n)) 因此如果找到了d的话,(ed-1)会整除φ(n),也就是存在k使得(e*d-1)//k=φ(n)
            continue
        
        phi=(e*d-1)//k               #这个结果就是 φ(n)
        px,qy=get_pq(1,n-phi+1,n)
        if px*qy==n:
            p,q=abs(int(px)),abs(int(qy))     #可能会得到两个负数,负负得正未尝不会出现
            d=gmpy2.invert(e,(p-1)*(q-1))     #求ed=1 (mod  φ(n))的结果,也就是e关于 φ(n)的乘法逆元d
            return d
    print("该方法不适用")
    
    
e = 14058695417015334071588010346586749790539913287499707802938898719199384604316115908373997739604466972535533733290829894940306314501336291780396644520926473
n = 33608051123287760315508423639768587307044110783252538766412788814888567164438282747809126528707329215122915093543085008547092423658991866313471837522758159
d=wienerAttack(e,n)
print("d=",d)`

参考:https://en.wikipedia.org/wiki/Wiener%27s_attack

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值