defgetM2(a,b,c1,c2,n): a3 = pow(a,3,n) b3 = pow(b,3,n) first = c1-a3*c2+2*b3 first = first % n second = 3*b*(a3*c2-b3) second = second % n third = second*gmpy2.invert(first,n) third = third % n fourth = (third+b)*gmpy2.invert(a,n) return fourth % n a=1 b=-1 padding2=b n=0xf9526aad4d41c9b28f8bae279c7ef6b07d729d1f56e530219851f656ad521218815bdccb15167a25633a2f76969fccd3fe1ef379ded08d1a9c3307f680e952956d2b3d04cc50040efb30e40bf2562aae4b05b8ec0d5e0e0ea5fdc1b00b80dee9b6de1d77d41d8d040d3465c89133d9af23b1d43f57e70606e3433d35a47e2ed c1=0x798841c574b7c88ce1430d4b02bac01fc9368c71a7966176b22f9dc2e0c2f6d4d5b8a9e10dbcaa4584e667ef1afd213b78c2bdc16ba5ab909c2de2fe5a7a5fa36a390bdccf794451cd9db8489ed7870efa4a4d7d1cacacfec92e81f6bb955a4ef5d71d80631c0726d22ec3d5b115de7ff42f22e67854b59ed816e06485ab523 c2=0xe92c4c99052fa3c4bb5e54477b0afe8e18da37255269f070ffa6824492a87153e428fa4ed839b7f3249966259a0c88641185594fc2fa4881cf32b7af5b18baa6f5200453ee80e38c74dbeb90f32118e4f33e636a808e44f27e09286d109ee8f41765ad64c7afea9775974d78a80e0977a37689c7f15a23a83a87b1f5bdbcdec m = getM2(a,b,c1,c2,n)-padding2 print (m)
Known High Bits Message Attack / Stereotyped Messages
load("coppersmith.sage") N = #N的值 e = #e的值 m = #m的大概值 c = #c的值 ZmodN = Zmod(N) P.<x> = PolynomialRing(ZmodN) f = (m + x)^e - c dd = f.degree() beta = 1 epsilon = beta / 7 mm = ceil(beta**2 / (dd * epsilon)) tt = floor(dd * mm * ((1/beta) - 1)) XX = ceil(N**((beta**2/dd) - epsilon)) //XX是根的上界,根据所知的m的位数进行调整 roots = coppersmith_howgrave_univariate(f, N, beta, mm, tt, XX)
sage:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
n = 0x2519834a6cc3bf25d078caefc5358e41c726a7a56270e425e21515d1b195b248b82f4189a0b621694586bb254e27010ee4376a849bb373e5e3f2eb622e3e7804d18ddb897463f3516b431e7fc65ec41c42edf736d5940c3139d1e374aed1fc3b70737125e1f540b541a9c671f4bf0ded798d727211116eb8b86cdd6a29aefcc7 e = 3 m = randrange(n) c = pow(m, e, n) beta = 1 epsilon = beta^2/7 nbits = n.nbits() kbits = floor(nbits*(beta^2/e-epsilon)) mbar = 0xb11ffc4ce423c77035280f1c575696327901daac8a83c057c453973ee5f4e508455648886441c0f3393fe4c922ef1c3a6249c12d21a000000000000000000 c = 0x1f6f6a8e61f7b5ad8bef738f4376a96724192d8da1e3689dec7ce5d1df615e0910803317f9bafb6671ffe722e0292ce76cca399f2af1952dd31a61b37019da9cf27f82c3ecd4befc03c557efe1a5a29f9bb73c0239f62ed951955718ac0eaa3f60a4c415ef064ea33bbd61abe127c6fc808c0edb034c52c45bd20a219317fb75 print ("upper %d bits (of %d bits) is given" % (nbits-kbits, nbits))
PR.<x> = PolynomialRing(Zmod(n)) f = (mbar + x)^e - c x0 = f.small_roots(X=2^kbits, beta=1)[0] # find root < 2^kbits with factor = n1 print (mbar + x0)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
n = 131889193322687215946601811511407251196213571687093913054335139712633125177496800529685285401802802683116451016274353008428347997732857844896393358010946452397522017632024075459908859131965234835870443110233375074265933004741459359128684375786221535003839961829770182916778717973782408036072622166388614214899 c = 11188201757361363141578235564807411583085091933389381887827791551369738717117549969067660372214366275040055647621817803877495473068767571465521881010707873686036336475554105314475193676388608812872218943728455841652208711802376453034141883236142677345880594246879967378770573385522326039206400578260353074379 from Crypto.Util.number import * part = 724544392969230558511482768252916758716788586090548475884579#part m F = Zmod(n) x = PolynomialRing(F, 'x').gen() f = ((part << 64) + x) ** 5 - c
xx = f.small_roots(X = 2 ** 64)[0] flag = (part << 64) + xx
h1 = 1514296530850131082973956029074258536069144071110652176122006763622293335057110441067910479 h2 = 40812438243894343296354573724131194431453023461572200856406939246297219541329623 n = 21815431662065695412834116602474344081782093119269423403335882867255834302242945742413692949886248581138784199165404321893594820375775454774521554409598568793217997859258282700084148322905405227238617443766062207618899209593375881728671746850745598576485323702483634599597393910908142659231071532803602701147251570567032402848145462183405098097523810358199597631612616833723150146418889589492395974359466777040500971885443881359700735149623177757865032984744576285054725506299888069904106805731600019058631951255795316571242969336763938805465676269140733371287244624066632153110685509892188900004952700111937292221969 c = 19073695285772829730103928222962723784199491145730661021332365516942301513989932980896145664842527253998170902799883262567366661277268801440634319694884564820420852947935710798269700777126717746701065483129644585829522353341718916661536894041337878440111845645200627940640539279744348235772441988748977191513786620459922039153862250137904894008551515928486867493608757307981955335488977402307933930592035163126858060189156114410872337004784951228340994743202032248681976932591575016798640429231399974090325134545852080425047146251781339862753527319093938929691759486362536986249207187765947926921267520150073408188188 e = 0x10001
mod = 1<<265 pl = n*inverse_mod(h2, mod) % mod pbar = (h1 << 724) + pl
PR.<x> = PolynomialRing(Zmod(n))
for i inrange(64): f = pbar + (x*mod*64) + (i<<265) print(f) f = f.monic() print(f) print('--------------') pp = f.small_roots(X=2^453, beta=0.4) if pp: break
p = int(pbar + (pp[0]<<271) + (i<<265)) q = n // p d = inverse_mod(e, (p-1)*(q-1)) print(long_to_bytes(power_mod(c, d, n)))
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 = number_n e = 3 d = number_d
//本题e = 3,有3组n,c from struct import pack,unpack import zlib import gmpy defmy_parse_number(number): string = "%x" % number erg = [] while string != '': erg = erg + [chr(int(string[:2], 16))] string = string[2:] return''.join(erg) defextended_gcd(a, b): x,y = 0, 1 lastx, lasty = 1, 0 while b: a, (q, b) = b, divmod(a,b) x, lastx = lastx-q*x, x y, lasty = lasty-q*y, y return (lastx, lasty, a) defchinese_remainder_theorem(items): N = 1 for a, n in items: N *= n result = 0 for a, n in items: m = N//n r, s, d = extended_gcd(n, m) if d != 1: N=N/n continue result += a*s*m return result % N, N
sessions=[{"c": 0x25e206422ea328f1b295dd121970b874b002789b2419a57584b2f1a682a36312a45efe22bb68694b9c9dfdc63c4f10b746a4a2893b29f918d90cb5129d52e66babf7f8516c44cd33ee27d2cf2968e0002ab2b711387d8f111315bd23d3f92073634ed6e57fa9b56d14104f75336f46c6dd43fbac810a6337a7ad3f60890873b, "e": 3, "n":0x5797fdb74bcea6788212fb2c32c5d98d308c617f893d1f375d0e611b424d5656df4465772e278c25e7d1d5fd73b0fdfdac4a786a11403d239a2f84dc77a46c1108219eed98567605ab29ffdeef10594863bb49d45d41c1f3925d6a33bb34205321ab03d906e2d89c2153e76f2ad185bac9fb26099910dd19cf3be35ec7e01df5}, {"c":0x448f88bec6795e11b06a7810faf617931bc6d99d1628cafecff1e933154ce575caaf752c3daf50b288ad7759ea8133f7dc9ca42a1b950eb8d538f98e00a4f3ad6bb0d6a9ad5d042d6db710c060bb72aa13065986d8dfb800409c08e4cdee471bc7ef31a6e3e2027ecb8ea9fb9b19440c5272fecf04aefdf2dbeafd994589c09f , "e": 3, "n":0x50998a3cf7f86a3044fe3c1fda2f6df7050383833279ebdbfe943f83faae3ada1bb6e684e48efd0487056849d47552d8052144364a72324b038ea73812960015c678c4e903e25515d874d1435761f20d1d6a066d2b70651c051dc157d2183d91ed6e7ae25d4adb0ce04833b816f96c5fd718c687474cacca6ad1dcc85db07e89 }, {"c":0xc9ddbb9478d0b64086091aac64efd51eb37b5067feb380995d39a917c0c927b26902f06dc449b53d80cd59c5d912fb5a5f45b223278919ae1ce449f4db7afbc252f16247129ea68dc6011093da6b11356591a9e8c0e10057e9d733712a6e0caafc462e9b2d07fb2aa3a451403a7f84de3504a60e72872df20bc244a0f1c837b , "e": 3, "n":0x15ed9002077c66e48a6fc80ce744f16b87e237ddd9a4efb4ffa2f9f89d09af382dddfc259dbf932728c23757957638f3ec9327fc0eaf3fd5d72b91c714798ca1459dfdf6c7505eb6e39f26624431239b6daa7bbaa6c5aad3dc3bf6b377923781ab5c221c195115d39c477c0561d5c769c17583c5b66d5f21f6683cea2670215b }] data = [] for session in sessions: e=session['e'] n=session['n'] msg=session['c'] data = data + [(msg, n)] print ("Please wait, performing CRT") x, n = chinese_remainder_theorem(data) e=session['e'] realnum = gmpy.mpz(x).root(e)[0].digits() print (my_parse_number(int(realnum)).encode("UTF-8").hex())
import gmpy import gmpy2 defmodinv(a, m): returnint(gmpy2.invert(a, m)) defchinese_remainder(n, a): sum = 0 prod = reduce(lambda a, b: a * b, n) for n_i, a_i inzip(n, a): p = prod / n_i sum += a_i * modinv(p, n_i) * p me = int(sum % prod) return gmpy.mpz(me).root(len(n))[0] ns = given_ns cs = given_cs m = chinese_remainder(ns, cs) print m