defwiener_attack(e,n): a=f2c(e,n) for (d,k) in sf(a): if d!=0and k!=0: phi=(e*d-1)//k (p,q)=solve_p_q(n,phi) if p*q==n: m=pow(c,d,n) print(long_to_bytes(m)) break#这里break一方面降低运算量,另一方面随着phi增大,x减小,y可能会成负数,z不能开方报错,或者直接return p,q在外面计算也可以
defwiener(e, n): m = 12345 c = pow(m, e, n) q0 = 1 list1 = continued_fraction(Integer(e) / Integer(n)) conv = list1.convergents() for i in conv: k = i.numerator() q1 = i.denominator() for r inrange(20): for s inrange(20): d = r * q1 + s * q0 m1 = pow(c, d, n) if m1 == m: return d q0 = q1
n = 1051380872316823433883636764584789285333736434524933570584976014001214015195582230652890036553897972507709868668015209942849015953126067065245745528656185713975834472569979390688522786334308265267342203713851528468719085926942222541344057327637925939220941677328780957242592769934672272901444344368132925072596706265951382183962516395989020286284674233929275036820658314907868575906130423049124591076625494555958927499995127864266451094815485831694951169813864579090722449382301556276181043387840715294133205479396272801536638003449150191833236756230648343641542001617352347728075031395009393805016183916046647042759712436405458561551257959973189661621088021485676031370872948254252297718720969276447566410825701049555286286171854286210170310303122812022424180992567945938220732070586725895910160295026510702457152084383868466740490026825254620849716745141621210206706738899418272128830937154184366826368016614460538955646609 # p*r*q e = 401736266490324552517217032225246450087649254466718075727966287757972026925163477893539047721223580215545684494442007744774900721388024851291175127388784748482162997733029569314385345465782341732251402815344448962923207292061517106665954257137567332560956608813590130048988674456360832136718517222056109287921167927946304453828334895683526480626294649396329610693963520850896266343295069273447109718037817671775114733403154525393468056590686142168244467303584451585069101584798590889529292526446832857035880715351476044875846461493125136227486230514153648388383654116769560511713813660841282782474519612727725715364718394717990336084691567425849567195154254431858216101902309862385524999911892987920197370958210721993073768994565808825036701082088990540391431078200077738350023726344360396487614841476654096629864029557926380538230445278881935443675347998379733770494280427033480933837349115145552011734379818969027809471037 d=wiener(e, n) print(d)
n=p*q*r #n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733 c=pow(flag,e,n) #e=0x1001 #c=75700883021669577739329316795450706204502635802310731477156998834710820770245219468703245302009998932067080383977560299708060476222089630209972629755965140317526034680452483360917378812244365884527186056341888615564335560765053550155758362271622330017433403027261127561225585912484777829588501213961110690451987625502701331485141639684356427316905122995759825241133872734362716041819819948645662803292418802204430874521342108413623635150475963121220095236776428 #so,what is the flag?
from random import choice from Crypto.Util.number import isPrime, sieve_base as primes from flag import flag
defgetPrime(bits): whileTrue: n = 2 while n.bit_length() < bits: n *= choice(primes) #primes为前10000个素数的列表 if isPrime(n + 1): return n + 1
e = 0x10001 m = int.from_bytes(flag.encode(), 'big') p, q = [getPrime(2048) for _ inrange(2)] n = p * q c = pow(m, e, n)
n = 32849718197337581823002243717057659218502519004386996660885100592872201948834155543125924395614928962750579667346279456710633774501407292473006312537723894221717638059058796679686953564471994009285384798450493756900459225040360430847240975678450171551048783818642467506711424027848778367427338647282428667393241157151675410661015044633282064056800913282016363415202171926089293431012379261585078566301060173689328363696699811123592090204578098276704877408688525618732848817623879899628629300385790344366046641825507767709276622692835393219811283244303899850483748651722336996164724553364097066493953127153066970594638491950199605713033004684970381605908909693802373826516622872100822213645899846325022476318425889580091613323747640467299866189070780620292627043349618839126919699862580579994887507733838561768581933029077488033326056066378869170169389819542928899483936705521710423905128732013121538495096959944889076705471928490092476616709838980562233255542325528398956185421193665359897664110835645928646616337700617883946369110702443135980068553511927115723157704586595844927607636003501038871748639417378062348085980873502535098755568810971926925447913858894180171498580131088992227637341857123607600275137768132347158657063692388249513 c = 26308018356739853895382240109968894175166731283702927002165268998773708335216338997058314157717147131083296551313334042509806229853341488461087009955203854253313827608275460592785607739091992591431080342664081962030557042784864074533380701014585315663218783130162376176094773010478159362434331787279303302718098735574605469803801873109982473258207444342330633191849040553550708886593340770753064322410889048135425025715982196600650740987076486540674090923181664281515197679745907830107684777248532278645343716263686014941081417914622724906314960249945105011301731247324601620886782967217339340393853616450077105125391982689986178342417223392217085276465471102737594719932347242482670320801063191869471318313514407997326350065187904154229557706351355052446027159972546737213451422978211055778164578782156428466626894026103053360431281644645515155471301826844754338802352846095293421718249819728205538534652212984831283642472071669494851823123552827380737798609829706225744376667082534026874483482483127491533474306552210039386256062116345785870668331513725792053302188276682550672663353937781055621860101624242216671635824311412793495965628876036344731733142759495348248970313655381407241457118743532311394697763283681852908564387282605279108
defpollard(n,B): i=2 a=2 limit=int(0.8*B) for i inrange(2,limit): a=pow(a,i,n) for i inrange(limit,B+1): a=pow(a,i,n) p=gmpy2.gcd(a-1,n) if1<p<n: return p,n//p
from Crypto.Util.number import long_to_bytes,sieve_base#前一万个素数数组 import gmpy2
n=32849718197337581823002243717057659218502519004386996660885100592872201948834155543125924395614928962750579667346279456710633774501407292473006312537723894221717638059058796679686953564471994009285384798450493756900459225040360430847240975678450171551048783818642467506711424027848778367427338647282428667393241157151675410661015044633282064056800913282016363415202171926089293431012379261585078566301060173689328363696699811123592090204578098276704877408688525618732848817623879899628629300385790344366046641825507767709276622692835393219811283244303899850483748651722336996164724553364097066493953127153066970594638491950199605713033004684970381605908909693802373826516622872100822213645899846325022476318425889580091613323747640467299866189070780620292627043349618839126919699862580579994887507733838561768581933029077488033326056066378869170169389819542928899483936705521710423905128732013121538495096959944889076705471928490092476616709838980562233255542325528398956185421193665359897664110835645928646616337700617883946369110702443135980068553511927115723157704586595844927607636003501038871748639417378062348085980873502535098755568810971926925447913858894180171498580131088992227637341857123607600275137768132347158657063692388249513 c = 26308018356739853895382240109968894175166731283702927002165268998773708335216338997058314157717147131083296551313334042509806229853341488461087009955203854253313827608275460592785607739091992591431080342664081962030557042784864074533380701014585315663218783130162376176094773010478159362434331787279303302718098735574605469803801873109982473258207444342330633191849040553550708886593340770753064322410889048135425025715982196600650740987076486540674090923181664281515197679745907830107684777248532278645343716263686014941081417914622724906314960249945105011301731247324601620886782967217339340393853616450077105125391982689986178342417223392217085276465471102737594719932347242482670320801063191869471318313514407997326350065187904154229557706351355052446027159972546737213451422978211055778164578782156428466626894026103053360431281644645515155471301826844754338802352846095293421718249819728205538534652212984831283642472071669494851823123552827380737798609829706225744376667082534026874483482483127491533474306552210039386256062116345785870668331513725792053302188276682550672663353937781055621860101624242216671635824311412793495965628876036344731733142759495348248970313655381407241457118743532311394697763283681852908564387282605279108 e=0x10001
X=1 for i in sieve_base: X*=i p=gmpy2.gcd(pow(2,X,n)-1,n) q=n//p phi=(p-1)*(q-1) d=gmpy2.invert(e,phi) m=pow(c,d,n) print(long_to_bytes(m))#b'NCTF{Th3r3_ar3_1ns3cure_RSA_m0duli_7hat_at_f1rst_gl4nce_appe4r_t0_be_s3cur3}'
from gmpy2 import * from Crypto.Util.number import * import random import math
defonemod(e, q): p = random.randint(1, q-1) while(powmod(p, (q-1)//e, q) == 1): # (r,s)=1 p = random.randint(1, q) return p
defAMM_rth(o, r, q): # r|(q-1 assert((q-1) % r == 0) p = onemod(r, q)
t = 0 s = q-1 while(s % r == 0): s = s//r t += 1 k = 1 while((s*k+1) % r != 0): k += 1 alp = (s*k+1)//r
a = powmod(p, r**(t-1)*s, q) b = powmod(o, r*a-1, q) c = powmod(p, s, q) h = 1
for i inrange(1, t-1): d = powmod(int(b), r**(t-1-i), q) if d == 1: j = 0 else: j = (-math.log(d, a)) % r b = (b*(c**(r*j))) % q h = (h*c**j) % q c = (c*r) % q result = (powmod(o, alp, q)*h) return result
defALL_Solution(m, q, rt, cq, e): mp = [] for pr in rt: r = (pr*m) % q # assert(pow(r, e, q) == cq) mp.append(r) return mp
defcalc(mp, mq, e, p, q): i = 1 j = 1 t1 = invert(q, p) t2 = invert(p, q) for mp1 in mp: for mq1 in mq: j += 1 if j % 1000000 == 0: print(j) ans = (mp1*t1*q+mq1*t2*p) % (p*q) if check(ans): return return
defALL_ROOT2(r, q): # use function set() and .add() ensure that the generated elements are not repeated li = set() while(len(li) < r): p = powmod(random.randint(1, q-1), (q-1)//r, q) li.add(p) return li
if __name__ == '__main__': c=257142110273808470353932790260834385423195836240947804445043168231453970823430490856329111213189231868252755966778005793663199810057119020960651706963993282769973864494156391386075051462934130430940835471240579618826284534276211239463295726838485842840227094026972973568755487969486042883286010886114853697684439422818236539054061509350796956754115566635281319223039237365252887952785342564138484884780518096718205122966618504897723001949304358011007666606602453554821466955282438373689460 p=19936217237033573753894155829225442996983351260648079359790039921271372502978979089255944115115517326597713075963827804905342890524775515960525156828602110668810581490760693054089408458756578501439658313103640176379107393837271103113860091147479 q=15835321764158530652228056326151107407225353281494241384475003369802102321837994236516023188966354559804738234055721039001493117376126537075924755525606506532010338074320834686510734601985723266842927770379824450335028680072267894221203184802411 e=14 cp = c % p cq = c % q
import random import math import libnum import time from Crypto.Util.number import bytes_to_long,long_to_bytes #设置模数 defGF(a): global p p = a #乘法取模 defg(a,b): global p returnpow(a,b,p)
defAMM(x,e,p): GF(p) y = random.randint(1, p-1) while g(y, (p-1)//e) == 1: y = random.randint(1, p-1) print(y) #p-1 = e^t*s t = 1 s = 0 while p % e == 0: t += 1 print(t) s = p // (e**t) # s|ralpha-1 k = 1 while((s * k + 1) % e != 0): k += 1 alpha = (s * k + 1) // e #计算a = y^s b = x^s h =1 #h为e次非剩余部分的积 a = g(y, (e ** (t - 1) ) * s) b = g(x, e * alpha - 1) c = g(y, s) h = 1 # for i inrange(1, t-1): d = g(b,e**(t-1-i)) if d == 1: j = 0 else: j = -math.log(d,a) b = b * (g(g(c, e), j)) h = h * g(c, j) c = g(c, e) #return (g(x, alpha * h)) % p root = (g(x, alpha * h)) % p roots = set() for i inrange(e): mp2 = root * g(a,i) %p #assert(g(mp2, e) == x) roots.add(mp2) return roots defcheck(m): if'flag'in m: returnTrue else: returnFalse e = 997
p = 169192804045017094881483391290948160084538928031716323749363864952453968973507689162051165395748104110078160856791051809212190939432475142974911541618441458487669050818296365973889691415623806933502603345031427784795571665740530721508383685794846991682950112717404480456329219127191697671498037366841158723543 q = 107516396467746261711633898678341416690878446946218041251896502835689317784482747676107795221812916591321630759086326505565275611515776242892889358779953138176525964380991025435521861396436904104071935067377647496422254521013295763929078451759522826104921925202219553793049032407587608850233803508977340633609 c = 7296955328866123806615327249732627185102404227332181196296735121223965109231156544280256472492779759505533523060928048594910557437933201943976173955148680274140829916070075759044441331615135242760488256932238858269529909634447825461421412145996149026770528870738269768868586920051310346790350630656242240675615378779267818783700730455951708072880647986805110335263926177449091704517836266354071222826319675028232152825498040408774211261689801412297908590166114832939080331783731498956480608994534272354837899909567113733994622681549792329747132730450648055557829163328285671440063040320192447007187073122676185153708
mps = AMM(c,e,q) # print(mps) for mpp in mps: solution = str(long_to_bytes(mpp)) if check(solution): print(solution)
import random from Crypto.Util.number import long_to_bytes
defAMM(o, r, q):
g = GF(q) o = g(o) p = g(random.randint(1, q)) while p ^ ((q-1) // r) == 1: p = g(random.randint(1, q))
t = 0 s = q - 1 while s % r == 0: t += 1 s = s // r k = 1 while (k * s + 1) % r != 0: k += 1 alp = (k * s + 1) // r a = p ^ (r**(t-1) * s) b = o ^ (r*alp - 1) c = p ^ s h = 1 for i inrange(1, t): d = b ^ (r^(t-1-i)) if d == 1: j = 0 else: j = - discrete_log(d, a) b = b * (c^r)^j h = h * c^j c = c^r result = o^alp * h return result
deffindAllSolutions(mp, proot, cp, p): all_mp = set() for root in proot: mp2 = mp * root % p assert(pow(mp2, e, p) == cp) all_mp.add(mp2) return all_mp
c = 15433214846771804225704093824935372144929516863829752998270111032551363583267576397009018518790803908369965458162930857063271509296349091229352855725285388975497906340053281554202527432848881160125418406408621879995822551367228501163128699032015069585502994319524445505522625561831240862136447585120010288772692097621553249775117843166714346924868089146429002417223863834435968726551668931140147337199939823985783939085842479154589529244209712172799274024573845157268545992888944742377166586536479490962335287124809557709167220756920767331929168230518135523463578566851417486746667008938122693256033127001185017237773 p = 0xa892eb59b175bcf896be2176598f278437fe10ef032279f06e1092143acfb3c16b31811cca5286699595c2720c652ee64f8adc92c8b16a5601dd981d6f839ce9c0513db30de88c2ec6cae1a726acbd235ea946631bde633707d766287a2f075e9aace1606bd8b4f52d4f5b87dfb81f14fbc5338004575e9430257e180a169eff q = 0xe3d47225b77e56129dc3fed716181845f89fa15b2eb35453ffdc0f05cdf57c0d90410911d209818e886b202bc4893ebe85a07ef670122f0e70092de1b7963c3b24a58c6a9ec9ed677db3473b1882d10d550e45c18fd57b85a70a5401a074d36760e85c7e6258f0ab08fa69cd433709910fad6e145f7b85f589e83d61d3baf6ad n = p * q e = 0x3 cp = c % p cq = c % q mp = AMM(cp, e, p) mq = AMM(cq, e, q) p_proot = findAllPRoot(p, e) q_proot = findAllPRoot(q, e) mps = findAllSolutions(mp, p_proot, cp, p) mqs = findAllSolutions(mq, q_proot, cq, q) print("mps=",mps) print("mqs=",mqs)
flag = [] for mpp in mps: for mqq in mqs: solution = CRT_list([int(mpp), int(mqq)], [p, q]) flag.append(solution) print("flag=",flag)
for i inrange(len(flag)): assert (((flag[i] ** 3)) % n == c) f = long_to_bytes(flag[i] - p) ifb"DAS"in f: print(f) break else: print("No flag.") continue
from Crypto.Util.number import * import gmpy2 import time import random from tqdm import tqdm e = 65537 q= 12408795636519868275579286477747181009018504169827579387457997229774738126230652970860811085539129972962189443268046963335610845404214331426857155412988073 p= 12190036856294802286447270376342375357864587534233715766210874702670724440751066267168907565322961270655972226761426182258587581206888580394726683112820379 c= 68960610962019321576894097705679955071402844421318149418040507036722717269530195000135979777852568744281930839319120003106023209276898286482202725287026853925179071583797231099755287410760748104635674307266042492611618076506037004587354018148812584502385622631122387857218023049204722123597067641896169655595 n = p*q defAMM(o, r, q): start = time.time()
g = GF(q) o = g(o) p = g(random.randint(1, q)) while p ^ ((q-1) // r) == 1: p = g(random.randint(1, q)) print('[+] Find p:{}'.format(p)) t = 0 s = q - 1 while s % r == 0: t += 1 s = s // r print('[+] Find s:{}, t:{}'.format(s, t)) k = 1 while (k * s + 1) % r != 0: k += 1 alp = (k * s + 1) // r print('[+] Find alp:{}'.format(alp)) a = p ^ (r**(t-1) * s) b = o ^ (r*alp - 1) c = p ^ s h = 1 for i inrange(1, t): d = b ^ (r^(t-1-i)) if d == 1: j = 0 else: print('[+] Calculating DLP...') j = - discrete_log(d, a) print('[+] Finish DLP...') b = b * (c^r)^j h = h * c^j c = c^r result = o^alp * h end = time.time() print("Finished in {} seconds.".format(end - start)) print('Find one solution: {}'.format(result)) return result
defsolution(p,root,e): g = onemod(p,e) may = set() for i inrange(e): may.add(root * pow(g,i,p)%p) return may
cp = c % p mp = AMM(cp,e,p) print('-------',mp)
mps = solution(p,mp,e) for mpp in tqdm(mps): ai = [int(mpp)] mi = [p] m = CRT_list(ai,mi) flag = long_to_bytes(m) ifb'moectf'in flag: print(flag) exit(0)
''' e = 101684733522589049376051051576215902510166244234370429058800153902445053536138419222096346715560283781778705047246555278271919928248836576236044123786248907522717751222608113597458768397652361813688176017155353220911686089871315647328303370846954697334521948003485878793121446614220897034652783771882675756065 n = 106490064297459077911162044548396107234298314288687868971249318200714506925762583340058042587392504450330878677254698499363515259785914237880057943786202091010532603853142050802310895234445611880617572636397946757345480447391544962796834842717321639098108976593541239044249391398321435940436125823407760564233 c = 92367575354201067679929326801477992215675304496512806779109227230237905402825022908214026985431756172011616861246881703226244396008088878308925377019775353026444957454196182919500667632574210469783704454438904889268692709062013797002819384105191802781841741128273810101308641357704215204494382259638905571144 '''
由题目可知,q = next_prime(p+2**420),由此我们可以构造一个一元多项式方程 f = p*q-n = p*(p+2**420)-n,然后求解方程的根,此时p在根附近,于是在将根值往前推直至n%p=0为止,此时p为所求,接下来就是普通RSA解密:
e = 101684733522589049376051051576215902510166244234370429058800153902445053536138419222096346715560283781778705047246555278271919928248836576236044123786248907522717751222608113597458768397652361813688176017155353220911686089871315647328303370846954697334521948003485878793121446614220897034652783771882675756065 n = 106490064297459077911162044548396107234298314288687868971249318200714506925762583340058042587392504450330878677254698499363515259785914237880057943786202091010532603853142050802310895234445611880617572636397946757345480447391544962796834842717321639098108976593541239044249391398321435940436125823407760564233 c = 92367575354201067679929326801477992215675304496512806779109227230237905402825022908214026985431756172011616861246881703226244396008088878308925377019775353026444957454196182919500667632574210469783704454438904889268692709062013797002819384105191802781841741128273810101308641357704215204494382259638905571144
from Crypto.Util.number import * from tqdm import trange
n = 18993579800590288733556762316465854395650778003397512624355925069287661487515652428099677335464809283955351330659278915073219733930542167360381688856732762552737791137784222098296804826261681852699742456526979985201331982720936091963830799430264680941164508709453794113576607749669278887105809727027129736803614327631979056934906547015919204770702496676692691248702461766117271815398943842909579917102217310779431999448597899109808086655029624478062317317442297276087073653945439820988375066353157221370129064423613949039895822016206336117081475698987326594199181180346821431242733826487765566154350269651592993856883 c1 = 3089900890429368903963127778258893993015616003863275300568951378177309984878857933740319974151823410060583527905656182419531008417050246901514691111335764182779077027419410717272164998075313101695833565450587029584857433998627248705518025411896438130004108810308599666206694770859843696952378804678690327442746359836105117371144846629293505396610982407985241783168161504309420302314102538231774470927864959064261347913286659384383565379900391857812482728653358741387072374314243068833590379370244368317200796927931678203916569721211768082289529948017340699194622234734381555103898784827642197721866114583358940604520 c2 = 6062491672599671503583327431533992487890060173533816222838721749216161789662841049274959778509684968479022417053571624473283543736981267659104310293237792925201009775193492423025040929132360886500863823523629213703533794348606076463773478200331006341206053010168741302440409050344170767489936681627020501853981450212305108039373119567034948781143698613084550376070802084805644270376620484786155554275798939105737707005991882264123315436368611647275530607811665999620394422672764116158492214128572456571553281799359243174598812137554860109807481900330449364878168308833006964726761878461761560543284533578701661413931
defGCD(a,b): if b == 0: return a.monic() else: return GCD(b,a % b) P.<x> = PolynomialRing(Zmod(n))
for e in trange(2**10): if isPrime(e): i=e f1 = (114*x+2333) ^ i - c1 f2 = (514*x+4555) ^ i - c2 if GCD(f1,f2)[0] != 1: print(long_to_bytes(int(n - GCD(f1,f2)[0])))
""" Setting debug to true will display more informations about the lattice, the bounds, the vectors... """ debug = True
""" Setting strict to true will stop the algorithm (and return (-1, -1)) if we don't have a correct upperbound on the determinant. Note that this doesn't necesseraly mean that no solutions will be found since the theoretical upperbound is usualy far away from actual results. That is why you should probably use `strict = False` """ strict = False
""" This is experimental, but has provided remarkable results so far. It tries to reduce the lattice as much as it can while keeping its efficiency. I see no reason not to use this option, but if things don't work, you should try disabling it """ helpful_only = True dimension_min = 7# stop removing if lattice reaches that dimension
# display stats on helpful vectors defhelpful_vectors(BB, modulus): nothelpful = 0 for ii inrange(BB.dimensions()[0]): if BB[ii,ii] >= modulus: nothelpful += 1
print (nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")
# display matrix picture with 0 and X defmatrix_overview(BB, bound): for ii inrange(BB.dimensions()[0]): a = ('%02d ' % ii) for jj inrange(BB.dimensions()[1]): a += '0'if BB[ii,jj] == 0else'X' if BB.dimensions()[0] < 60: a += ' ' if BB[ii, ii] >= bound: a += '~' print (a)
# tries to remove unhelpful vectors # we start at current = n-1 (last vector) defremove_unhelpful(BB, monomials, bound, current): # end of our recursive function if current == -1or BB.dimensions()[0] <= dimension_min: return BB
# we start by checking from the end for ii inrange(current, -1, -1): # if it is unhelpful: if BB[ii, ii] >= bound: affected_vectors = 0 affected_vector_index = 0 # let's check if it affects other vectors for jj inrange(ii + 1, BB.dimensions()[0]): # if another vector is affected: # we increase the count if BB[jj, ii] != 0: affected_vectors += 1 affected_vector_index = jj
# level:0 # if no other vectors end up affected # we remove it if affected_vectors == 0: print ("* removing unhelpful vector", ii) BB = BB.delete_columns([ii]) BB = BB.delete_rows([ii]) monomials.pop(ii) BB = remove_unhelpful(BB, monomials, bound, ii-1) return BB
# level:1 # if just one was affected we check # if it is affecting someone else elif affected_vectors == 1: affected_deeper = True for kk inrange(affected_vector_index + 1, BB.dimensions()[0]): # if it is affecting even one vector # we give up on this one if BB[kk, affected_vector_index] != 0: affected_deeper = False # remove both it if no other vector was affected and # this helpful vector is not helpful enough # compared to our unhelpful one if affected_deeper andabs(bound - BB[affected_vector_index, affected_vector_index]) < abs(bound - BB[ii, ii]): print ("* removing unhelpful vectors", ii, "and", affected_vector_index) BB = BB.delete_columns([affected_vector_index, ii]) BB = BB.delete_rows([affected_vector_index, ii]) monomials.pop(affected_vector_index) monomials.pop(ii) BB = remove_unhelpful(BB, monomials, bound, ii-1) return BB # nothing happened return BB
""" Returns: * 0,0 if it fails * -1,-1 if `strict=true`, and determinant doesn't bound * x0,y0 the solutions of `pol` """ defboneh_durfee(pol, modulus, mm, tt, XX, YY): """ Boneh and Durfee revisited by Herrmann and May finds a solution if: * d < N^delta * |x| < e^delta * |y| < e^0.5 whenever delta < 1 - sqrt(2)/2 ~ 0.292 """
# x-shifts gg = [] for kk inrange(mm + 1): for ii inrange(mm - kk + 1): xshift = x^ii * modulus^(mm - kk) * polZ(u, x, y)^kk gg.append(xshift) gg.sort()
# x-shifts list of monomials monomials = [] for polynomial in gg: for monomial in polynomial.monomials(): if monomial notin monomials: monomials.append(monomial) monomials.sort()
# y-shifts (selected by Herrman and May) for jj inrange(1, tt + 1): for kk inrange(floor(mm/tt) * jj, mm + 1): yshift = y^jj * polZ(u, x, y)^kk * modulus^(mm - kk) yshift = Q(yshift).lift() gg.append(yshift) # substitution
# y-shifts list of monomials for jj inrange(1, tt + 1): for kk inrange(floor(mm/tt) * jj, mm + 1): monomials.append(u^kk * y^jj)
# construct lattice B nn = len(monomials) BB = Matrix(ZZ, nn) for ii inrange(nn): BB[ii, 0] = gg[ii](0, 0, 0) for jj inrange(1, ii + 1): if monomials[jj] in gg[ii].monomials(): BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](UU,XX,YY)
# Prototype to reduce the lattice if helpful_only: # automatically remove BB = remove_unhelpful(BB, monomials, modulus^mm, nn-1) # reset dimension nn = BB.dimensions()[0] if nn == 0: print ("failure") return0,0
# check if vectors are helpful if debug: helpful_vectors(BB, modulus^mm)
# check if determinant is correctly bounded det = BB.det() bound = modulus^(mm*nn) if det >= bound: print ("We do not have det < bound. Solutions might not be found.") print ("Try with highers m and t.") if debug: diff = (log(det) - log(bound)) / log(2) print ("size det(L) - size e^(m*n) = ", floor(diff)) if strict: return -1, -1 else: print ("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")
# display the lattice basis if debug: matrix_overview(BB, modulus^mm)
# LLL if debug: print ("optimizing basis of the lattice via LLL, this can take a long time")
BB = BB.LLL()
if debug: print ("LLL is done!")
# transform vector i & j -> polynomials 1 & 2 if debug: print ("looking for independent vectors in the lattice") found_polynomials = False
for pol1_idx inrange(nn - 1): for pol2_idx inrange(pol1_idx + 1, nn): # for i and j, create the two polynomials PR.<w,z> = PolynomialRing(ZZ) pol1 = pol2 = 0 for jj inrange(nn): pol1 += monomials[jj](w*z+1,w,z) * BB[pol1_idx, jj] / monomials[jj](UU,XX,YY) pol2 += monomials[jj](w*z+1,w,z) * BB[pol2_idx, jj] / monomials[jj](UU,XX,YY)
# are these good polynomials? if rr.is_zero() or rr.monomials() == [1]: continue else: print ("found them, using vectors", pol1_idx, "and", pol2_idx) found_polynomials = True break if found_polynomials: break
ifnot found_polynomials: print ("no independant vectors could be found. This should very rarely happen...") return0, 0
rr = rr(q, q)
# solutions soly = rr.roots()
iflen(soly) == 0: print ("Your prediction (delta) is too small") return0, 0
soly = soly[0][0] ss = pol1(q, soly) solx = ss.roots()[0][0]
# return solx, soly
defexample(): ############################################ # How To Use This Script ##########################################
# # The problem to solve (edit the following values) #
# the modulus N = 0xbadd260d14ea665b62e7d2e634f20a6382ac369cd44017305b69cf3a2694667ee651acded7085e0757d169b090f29f3f86fec255746674ffa8a6a3e1c9e1861003eb39f82cf74d84cc18e345f60865f998b33fc182a1a4ffa71f5ae48a1b5cb4c5f154b0997dc9b001e441815ce59c6c825f064fdca678858758dc2cebbc4d27 # the public exponent e = 0x11722b54dd6f3ad9ce81da6f6ecb0acaf2cbc3885841d08b32abc0672d1a7293f9856db8f9407dc05f6f373a2d9246752a7cc7b1b6923f1827adfaeefc811e6e5989cce9f00897cfc1fc57987cce4862b5343bc8e91ddf2bd9e23aea9316a69f28f407cfe324d546a7dde13eb0bd052f694aefe8ec0f5298800277dbab4a33bb
# the hypothesis on the private exponent (the theoretical maximum is 0.292) delta = 0.280# this means that d < N^delta
# # Lattice (tweak those values) #
# you should tweak this (after a first run), (e.g. increment it until a solution is found) m = 4# size of the lattice (bigger the better/slower)
# you need to be a lattice master to tweak these t = int((1-2*delta) * m) # optimization from Herrmann and May X = 2*floor(N^delta) # this _might_ be too much Y = floor(N^(1/2)) # correct if p, q are ~ same size
# # Don't touch anything below #
# Problem put in equation P.<x,y> = PolynomialRing(ZZ) A = int((N+1)/2) pol = 1 + x * (A + y)
g = 17 p = 509 y = 438 m = gmpy2.iroot(p, 2)[0] + 1
defBSGS(g, y, p): m = gmpy2.iroot(p, 2)[0] + 1 s = {pow(g, j, p): j for j inrange(m)} gs = pow(g, -m, p) for i inrange(m): if y in s: return m*i + s[y] y = y * gs % p returnNone
print(BSGS(g, y, p))
一道例题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from libnum import * from gmpy2 import *
flag = "flag{big_and_small}" a = s2n(flag) print(a) m = a >> 16 << 16 p = generate_prime(1024) g = 5 y = pow(g,a,p) print(f"m = {m}") print("g =", g) print("p =", p) print("y =", y)
m = 2284117282071477104642039231536944446836572160 g = 5 p = 104902226273988324576427043280139630983677434981789024088951356016939994526304119354435543071985576434554541580765980475339863817923069063092822047759376193281443519615446894334112711636144801809678018855363243259870518701678872861580764859373668820885488992214504069164524801155987240703746883303678741931657 y = 52132387535704137390458836331516728932227502073670482441552732370459557430160087735998314933737812855984248770511516860301143061293647971484306910330283327130899876785232553721318312581135200914802966676159312701878015611579070659605675344114334474279389271370807188711609485615280774712598619602033548583710
defBSGS(g, y, p, bound): x = iroot(bound, 2)[0] + 1 s = {pow(g, j, p): j for j inrange(x)} sg = pow(g, -m, p) for i inrange(m): if y in s: return i*x + s[y] y = y * sg % p returnNone
a = BSGS(g, y*invert(pow(g,m,p), p)%p, p, 2**32) + m print(n2s(int(a)))