from gmpy2 import * from Crypto.Util.number import * import binascii defgongmo(n, c1, c2, e1, e2): defegcd(a, b): if b == 0: return a, 0 else: x, y = egcd(b, a % b) return y, x - (a // b) * y s = egcd(e1, e2) s1 = s[0] s2 = s[1]
from gmpy2 import * from Crypto.Util.number import *
defpollard(N): a = 2 n = 2 whileTrue: a = powmod(a, n, N) p = gcd(a-1, N) if p != 1and p != N: return p n += 1
n = c = e =
p = pollard(n) q = n // p d = invert(e, (p-1)*(q-1)) print(long_to_bytes(powmod(c, d, n)))
2.p+1光滑
当 p 是 N 的因数,并且 p+1 是光滑数,可能可以使用 Williams’ p + 1 算法来分解 N。
原理太过复杂,这里给出脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defmlucas(v, a, n): """ Helper function for williams_pp1(). Multiplies along a Lucas sequence modulo n. """ v1, v2 = v, (v**2 - 2) % n for bit inbin(a)[3:]: v1, v2 = ((v1**2 - 2) % n, (v1*v2 - v) % n) if bit == "0"else ((v1*v2 - v) % n, (v2**2 - 2) % n) return v1
for v in count(1): for p in primegen(): e = ilog(isqrt(n), p) if e == 0: break for _ in xrange(e): v = mlucas(v, p, n) g = gcd(v-2, n) if1 < g < n: return g # g|n if g == n: break
M = (N - 1) // (2 * g) u = M // (2 * g) v = M - 2 * g * u GF = Zmod(N) x = GF.random_element() y = x ^ (2 * g) # c的范围大概与N^(0.5-2*gamma)很接近 c = bsgs(y, y ^ u, (2**(cbits-1), 2**(cbits+1)), operation='*') #(a, b, bounds, operation='*', identity=None, inverse=None, op=None) ab = u - c apb = v + 2 * g * c P.<x> = ZZ[] f = x ^ 2 - apb * x + ab a = f.roots() if a: a, b = a[0][0], a[1][0] p = 2 * g * a + 1 q = 2 * g * b + 1 assert p * q == N
from Crypto.Util.number import * print(long_to_bytes(int(pow(enc,inverse(e,(p-1)*(q-1)),N))))
from tqdm import trange from Crypto.Util.number import * N=54642322838521966106812419124141939188989640814860878861908076164639367595914512196689546261469345514255441116302800139668437203232194709285409075862419734007902906374266399946334745212375047784704524011282117381662325280446704897787659122983658402386409111680527237824015035597005313191262677046034069311159229487077629209355803968123085023774573470039717820771904932963580385259183454286138826580540970458295849974865118842313357636425032600607639797650353675780470249861726402474026943128529940611865467085977350731870140237435132883515585257875892835970695457915025407153187085139372317622088931196367733198938707 e=65537 g=3040871967959800581351382295274005388082419270793259228509099272494086612979335548205806725469849481228948811909984262857772287453967175931780503026101 enc=16921727990128654940541048454609306049800635968567290885504606585088535877841115259199326146892596740059029032943069902149992954013354005954650241368176166717262074930938187076093385743103257206008984426730319621844540768570052906856372814131242671511736639583796446042340818796492567054682875526286521771179572697525973157614384591867911200189677177846743548750073412797016862500896375745125624115608433787391085807075889515255210830361622016035288935853286037510176320800234097566590023615892000758981191932044064959498134955967145300788171021729870111273798593291304516871631013979858203217888740299565006817016165 h = (N-1)//(2*g) # print(h) from gmpy2 import iroot ab_ = h//(2*g) # print(ab - a*b)
# print((ab - a*b).bit_length())
# print(2**24-13699487)
# for i in trange(2**24): # ab = ab_ - i # absum = h - 2*g*ab # if absum**2-4*ab < 0: # continue # abdiff = iroot(absum**2-4*ab, 2)[0] # a = (absum + abdiff) // 2 # b = (absum - abdiff) // 2 # if a*b == ab: # print(a) # print(b) # break
a = 47937386938884458900370786879118057275877357467300250370371787390211867366084642223134071188443797365024207320451316918915461052607536742271505969247375076726 b = 30817580160697031122119466051933934199293816720246050921169947835585517577173054601468730432823632268542332991565084729244237756343912826384891209074376593659
p = 2*g*a + 1 q = 2*g*b + 1
assert p*q == N phi = (p-1)*(q-1) d = pow(65537, -1, phi) m = pow(enc,d,N) print(long_to_bytes(m))