Wener‘s attack(RSA低解密指数攻击)
参考文章
Wener’s attack
重点知识:
连分数、渐进分数。 举个例子比较清晰,如图 那么e/N的依次每个渐进分数
描述:
Wiener 表示如果满足:d<(1/3)* n **(1/4) 那么一种基于连分数(一个数论当中的问题)的特殊攻击类型就可以危害 RSA 的安全。
思路如下:
在RSA中有式子:ed = 1%n 推到公式变换为: **e/phi -k/d = 1/(dphi)** 因为p,q很大有phi接近与n e/n -k/d = 1/(d*n) 又因为d * n很大所以有e/n接近于k/d (e/n略大于k/d) 计算e/n的连分数展开,依次算出每一个渐进分数。因为e/n > k/d 所以e/n 的渐进分数覆盖了k/d。也就是说e/n的渐进分数里有等于k/d的分数。接着验证k,d是否满足条件。
算法过程:
- 通过对e/n进行连分数展开
- 然后依次求其渐进分数
- 遍历所有渐进分数如果找到了d的话,(ed-1)会整除phi,也就是存在k使得(ed-1)//k=phi,建立方程求p,q。( x2−(p+q)∗x+pq=0这个方程的解就是p,q)如果p*q==n则找到了d
搬运代码:
理解最重要!!!
import gmpy2 # numerator(n):分子, denominator(d):分母 def t_cf(n, d): # 将分数 x/y 转为连分数的形式 res = [] while d: res.append(n // d) n, d = d, n % d return res def cf(sub_res): # 得到渐进分数的分母和分子 n, d = 1, 0 for i in sub_res[::-1]: # 从后面往前循环 d, n = n, i * n + d return d, n def list_fraction(x, y): # 列出每个渐进分数 res = t_cf(x, y) res = list(map(cf, (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 list_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("求解d失败")
上一篇:
IDEA上Java项目控制台中文乱码