from Crypto.Util.number import isPrime, inverse, long_to_bytes from random import getrandbits, randrange from collections import namedtuple from gmpy2 import iroot
defcomplex_pow(c, exp, modulus): result = Complex(1, 0) while exp > 0: if exp & 1: result = complex_mult(result, c, modulus) c = complex_mult(c, c, modulus) exp >>= 1 return result
n = 591143727706634512649148024939759359125332935965941339741301978100443626383764927192405352906265750441870484772597124866948416540051132797882766876525721890148417364187305274504045823909525810653621572555356644898701170387745996604627164605007922178682643820283078770381294378888391241362701866218417 e = 286946467444242125329232917366005482758108555562774407977935741707895065443551620433804352056018479543399936884283530961542517475681912633594516017006078645316684486996756770475826189189863772520489210693019367686071424252294502612171368401536443115059090019686947917579310650427245795515739689571717195342905189116070822202985869406209819001354794867213391783564718632331851210595177019029809911030842175529435093135302899375148321696495849291318040755489943683469106936515633912280068318274552872682582057701665040704440982616977621678524771480018759950866149932684370941131288823828567953532010239 c = Complex(re=466945074314394618048804903430146870407477348092856785114352121347573765297276603523823356061058665588358168906592812014840355312975623615872669350475423336999911145662063168579527228973092663141715593574293676068879530756106740387499946781859474224812941258752096544261250573356872425877525845188509, im=539172679356466036153667427018194773623808764616135073906943348291977037250808294837529529613499717611287613222519742317858999188657402414805409046190891945128148002520616896558562883270550640806765061686359425281201226450591985013283011470643176844774957570392307535783368083398557427779492426758982)
print(n) print(e)
r = 100 #u0 = Integer(-Zmod(2^r)(n).nth_root(2)) u0s = Zmod(2^r)(n).nth_root(2, all=True) print(u0s) for u0 in u0s: print(u0) u0 = Integer(u0) v0 = Integer(( 2 * u0 + (n - u0^2) * u0.inverse_mod(2^(2*r)) ) % 2^(2*r)) a1 = v0 * (2^(2*r-1)).inverse_mod(e) % e a2 = -((n+1)^2 - v0^2) * (2^(4*r)).inverse_mod(e) % e a3 = -1 * (2^(4*r)).inverse_mod(e) % e X = Integer(2 * n^0.7) Y = Integer(3 * n^0.3)
load('./copper.sage') PR.<x, y> = PolynomialRing(ZZ) f = x * y^2 + a1 * x * y + a2 * x + a3 res = lattice_attack(PR, f, e, 4, 3, X, Y) if res: print(res) break
k, v = res[0]
r = 100 ppq = 2^(2*r) * v + v0 pmq = ppq^2 - 4 * n pmq = iroot(pmq, 2) assert pmq[1] pmq = Integer(pmq[0]) p = (ppq + pmq) // 2 q = n // p assert p * q == n
phi = (p^2-1) * (q^2-1) d = e.inverse_mod(phi)
m = complex_pow(c, d, n) print(m) flag = b''.join([long_to_bytes(mi) for mi inlist(m)]) print(flag)
defmatrix_overview(BB): for ii inrange(BB.dimensions()[0]): a = ('%02d ' % ii) for jj inrange(BB.dimensions()[1]): if BB[ii, jj] == 0: a += ' ' else: a += 'X' if BB.dimensions()[0] < 60: a += ' ' print(a)
deflattice_attack(PR, pol, e, mm, tt, X, Y): x, y = PR.gens() polys = [] dd = pol.degree()
for s inrange(mm + 1): for i inrange(s, mm+1): for j inrange(2*s, 2*s+1+1): poly = x^(i-s) * y^(j-2*s) * pol^s * e^(mm-s) polys.append(poly)
for s inrange(mm + 1): i = s for j inrange(2*s+2, 2*s+tt+1): poly = x^(i-s) * y^(j-2*s) * pol^s * e^(mm-s) polys.append(poly)
polys = sorted(polys) monomials = [] for poly in polys: monomials += poly.monomials() monomials = sorted(set(monomials)) dims1 = len(polys) dims2 = len(monomials) M = matrix(QQ, dims1, dims2)
for ii inrange(dims1): M[ii, 0] = polys[ii](0, 0) for jj inrange(dims2): if monomials[jj] in polys[ii].monomials(): M[ii, jj] = polys[ii](x * X, y * Y).monomial_coefficient(monomials[jj]) matrix_overview(M) print('=' * 128) print(len(M.rows()), len(M.columns())) #M = M.hermite_form() B = M.LLL() print('LLL done')
det = B.det() print(det == 0) print(f"monomials: {monomials}") nn = len(monomials) matrix_overview(B) H = [(i, 0) for i inrange(dims1)] H = dict(H) for j inrange(dims2): for i inrange(dims1): H[i] += (monomials[j] * B[i, j]) / monomials[j](X, Y) PQ.<q> = PolynomialRing(ZZ) H = list(H.values()) solutions = [] print(len(H)) #for i in range(len(H)//2): for i inrange(5): #for j in range(i + 1, len(H)//2): for j inrange(i + 1, 5): pol1 = PR(H[i]) pol2 = PR(H[j]) rr = pol1.resultant(pol2, y) if rr.is_zero() or rr.monomials() == [1]: continue sols = rr(q, q).roots() for sol in sols: solx = sol[0] if solx == -1: continue try: soly = pol1(solx, q).roots()[0][0] solutions.append((solx, soly)) print('=' * 128) except: pass iflen(solutions) > 0: break iflen(solutions) > 0: break iflen(solutions) > 0: break return solutions
#!/usr/bin/env n = 6249734963373034215610144758924910630356277447014258270888329547267471837899275103421406467763122499270790512099702898939814547982931674247240623063334781529511973585977522269522704997379194673181703247780179146749499072297334876619475914747479522310651303344623434565831770309615574478274456549054332451773452773119453059618433160299319070430295124113199473337940505806777950838270849 e = 641747 c = 730024611795626517480532940587152891926416120514706825368440230330259913837764632826884065065554839415540061752397144140563698277864414584568812699048873820551131185796851863064509294123861487954267708318027370912496252338232193619491860340395824180108335802813022066531232025997349683725357024257420090981323217296019482516072036780365510855555146547481407283231721904830868033930943 p = 91027438112295439314606669837102361953591324472804851543344131406676387779969 assert n == p^5
import libnum # https://tover.xyz/p/n-root-in-F/ load('./nth.sage') res = nthRSA_p(c, e, p, 5) for r in res: flag = libnum.n2s(int(r)) ifb'flag'in flag: print(r) print(flag)
#!/usr/bin/env sage p = 173383907346370188246634353442514171630882212643019826706575120637048836061602034776136960080336351252616860522273644431927909101923807914940397420063587913080793842100264484222211278105783220210128152062330954876427406484701993115395306434064667136148361558851998019806319799444970703714594938822660931343299 q = 86691953673185094123317176721257085815441106321509913353287560318524418030801017388068480040168175626308430261136822215963954550961903957470198710031793956540396921050132242111105639052891610105064076031165477438213703242350996557697653217032333568074180779425999009903159899722485351857297469411330465671649 assert p == 2 * q + 1
g = 5 c = 105956730578629949992232286714779776923846577007389446302378719229216496867835280661431342821159505656015790792811649783966417989318584221840008436316642333656736724414761508478750342102083967959048112859470526771487533503436337125728018422740023680376681927932966058904269005466550073181194896860353202252854
print(p.nbits())
from Crypto.Util.number import * from Crypto.Util.Padding import pad from tqdm import tqdm import itertools import string
#for i in range(128-6): i = 14 i = 12 #i = 10 #i = 8 #i = 4 print(i)
''' c = pow(g, bytes_to_long(pad(fake.encode(), 128)), p) j = Integer(bytes_to_long(b'aa')) k = Integer(bytes_to_long(b'aa\x00\x00')) B = 2^(1024-40-8*i) % (p-1) A = pow(g, mh * 2^(1024-40) + ml, p) A = Integer(A).inverse_mod(p) * c % p A = pow(A, B.inverse_mod(q), p) ginv = g.inverse_mod(p) print(pow(g, j, p) % p) print(pow(ginv, k, p) * A % p) print(j, k) '''
n = 16^(i//2) List = set() Lj = {} B = 2^(1024-40-8*i) % (p-1) A = pow(g, mh * 2^(1024-40) + ml, p) A = Integer(A).inverse_mod(p) * c % p A = pow(A, (B).inverse_mod(q), p) for j in tqdm(itertools.product(string.hexdigits[:16], repeat=i//2), total=int(16^(i//2))): j = bytes_to_long(''.join(j).encode()) lj = pow(g, j, p) List.add(lj) Lj[lj] = j
ginv = g.inverse_mod(p) for k in tqdm(itertools.product(string.hexdigits[:16], repeat=i//2), total=int(16^(i//2))): k = bytes_to_long((''.join(k)+'\x00'*(i//2)).encode()) lk = pow(ginv, k, p) * A % p if lk inList: print(k, lk) break
j = Lj[lk] flag = long_to_bytes(k + j) flag = 'flag{%s}' % flag.decode() print(flag)