(1) ed - 1 = k*phi = k(p-1)(q-1) = k*n - k*(q + p - 1)
(2) ed - 1 = A*n + B = (A+1)n - (n - B)
(1) 与 (2) 是等价的:
因此, 令 A = (ed-1)/n , 0 < B < n , k < min(e , d) < max(e, d) < phi 我们得到:
k = A+1 , phi = (ed-1)/k , 这里要检查 余数为0。
然后用 韦达定理 求解一元二次方程的两个根, x1, x2 = p , q:
x^2 - bx + N = 0 其中: b= p+q , N = p*q
另外,有一个常规的方法, 从(N , E, D) 计算(P ,Q) ,对 E ,D 的 size 没有任何要求。这个算法应该在很多书里有记载。
方法2:
伪代码描述如下:
// 通过求解 w^2 = 1 mod n, we get p=gcd(w-1, n),有1/2概率求出非平凡因子p,一般2次即可 // k*phi = ed -1 = r * 2^s // a = rand(n) // w = a^r (mod n) // for ( j = 0 ; j < s ; j++) // if (w != 1) && (w != n-1 ) // if w^2 = 1 (mod n) // gcd(w-1,n) or gcd(w+1 ,n ) will have 1/2 chance to get p.q // 随机选择a,一般 2-3次, 即可求出p
n = gmpy2.mpz("6248BC3AB92A33B000FDB88568F19727F92F79EB68FF6AD73203EFD20A3E331BE941C7AA288095F33BC4B255FD983114D480EFFBEE2E313E6218A57F9CCC8189", 16) e = gmpy2.mpz("2476A7F02588913F228923E1F36F963F29708C07B117396817A6B94C336FC77FF7D381925EB40CFED8FBE894570155E41569B4EC69B26CB0320105A29651CB4B", 16)
# try Wiener 's attack
d = RSAwienerHacker.hack_RSA(e, n) print("d= " + hex(d))
# calc phi(n) = (p - 1)*(q - 1) from (n, e, d) # # 1. trial divide method : # fast method to calc phi(n) from (n, e, d) # if min(e, d ) < n^0.5 # # (1) ed - 1 = k*phi = k(p-1)(q-1) = k*n - k*(p1) # # (2) ed - 1 = A*n + B = (A+1)n - (n - B) # # A = (ed-1)/n , 0 < B < n , k < min(e , d) < max(e, d) < phi # # => k = A+1 , phi = (ed-1)/k # # 2. general method: # e*d - 1 = r * 2^s # choose random a , w = pow(a, r), p = gcd(w, n ) if w != 1 # ed = e*d - 1 k = ed/n + 1 phi = ed / k rem = ed % k print("rem= " + hex(rem))
# x^2 - bx + N = 0 # b= p+q , N = p*q b = n + 1 - phi m = gmpy2.isqrt(b*b - 4*n) p = (b + m)/2 q = (b - m)/2