#we need to define an polynomial == 0 (mod p) that gives us the missing part (x) # f_p(x) = x*2**(knownbits/2) + p_msb + p_lsb # it's not monic so we need to divide by 2**(knownbits/2) # set R = 2**(knownbits/2) and invert it modulo N
R = 2**(knownbits/2)#从第68位开始测试 invR = inverse_mod(R,N) #补齐两边 p_msb = 251000163339563476196 << (sizep-knownbits/2-1) p_lsb=int('2567fcb8c35e6dc63',16) #setup coppersmith F.<x> = PolynomialRing(Zmod(N)) #define the poly in x modulo p f = x + (p_msb+p_lsb)*invR #solve it x0 = f.small_roots(X=2^(sizep-knownbits)-1, beta=0.44, epsilon=1/64)[0]
defpartial_p(p0, kbits, n): PR.<x> = PolynomialRing(Zmod(n)) nbits = n.nbits() f = 2^kbits*x + p0 f = f.monic() roots = f.small_roots(X=2^(nbits//2-kbits), beta=0.3) # find root < 2^(nbits//2-kbits) with factor >= n^0.3 if roots: x0 = roots[0] p = gcd(2^kbits*x0 + p0, n) return ZZ(p)
deffind_p(d0, kbits, e, n): X = var('X') for k in xrange(1, e+1): results = solve_mod([e*d0*X - k*X*(n-X+1) + k*n == X], 2^kbits) for x in results: p0 = ZZ(x[0]) p = partial_p(p0, kbits, n) if p: return p if __name__ == '__main__': n = 0xd463feb999c9292e25acd7f98d49a13413df2c4e74820136e739281bb394a73f2d1e6b53066932f50a73310360e5a5c622507d8662dadaef860b3266222129fd645eb74a0207af9bd79a9794f4bd21f32841ce9e1700b0b049cfadb760993fcfc7c65eca63904aa197df306cad8720b1b228484629cf967d808c13f6caef94a9 e = 3 d = 0x603d033f2ef6c759aec839f132a45215fc8a635b757f3951a731fe60bc6729b3bcf819b57abfcaba3a93e9edef766c0d499cad3f7adb306bcf1645cfb63400e3 beta = 0.5 epsilon = beta^2/7 nbits = n.nbits() print"nbits:%d:"%(nbits) #kbits = floor(nbits*(beta^2+epsilon)) kbits = nbits - d.nbits()-1 print"kbits:%d"%(kbits) d0 = d & (2^kbits-1) print"lower %d bits (of %d bits) is given" % (kbits, nbits) p = find_p(d0, kbits, e, n print"found p: %d" % p q = n//p print d print inverse_mod(e, (p-1)*(q-1))
e=863 n = 100518394843898371534434468452366727877002363101196571557097132988734353726584916462381290904798733002716305256677572628142627545744681541293793069726231800754314572981168235829239563613754713724345581918566947492170647540708428013292098065584617876680109166595710006367308500341766024651457023537770009981295726110940010220082434490215229951191714998895277291076151298363584672162765486380515325199053994651202708865071379999942193926154807059329464291992287421875356468218685095369057734586073271903432589401520355996027480658214090147502829069822606753125953586123331154015992246394834867237734405963056883227552074835515815968441 c=86032824638305503499105979004374728344861493802341583733786447138684660694449673826205271902766363026345759436852747743967254218765160248630402258125202844303276381357264903281385470521070161164325276902001627351570675438339067652784355957225763207341000628151024518554862922220201109512940053316358078220681816224518400117972877854801506805929902506832781106133167532327833813179558969694268634413548545525533605595649634856393268111552838570383386406869870266457914799472663817890880697043874427042958587244568923338441053981863674366842769379075373006984522023718553749977766836594738859315852333132093474709715377682153430675891 d0=8429433927120666131169351623736961178529851960373209550653840828920672665447032524933438956407503522388445988812739437427277858013428300926608147855795349674824173869269407061090165202002106353884034590344852857623737262477675587193006629765892565228448265429521617733861051151345083787592170864896543517637252788111
d = 0 for k in range(0,e): print k X = var('X') results = solve_mod([e*d0*X - k*(n*X-X*X-n+X) == X], 2**1050) for x in results: p0 = ZZ(x[0]) if is_prime(p0) and gcd(n,p0)!=1: print p0 q0 = n//p0 phi=(q0-1)*(p0-1) d = inverse_mod(e,phi) break if(d!=0): break print d m = pow(c,d,n) print m