import gmpy2 import libnum import random import uuid
flag = "flag{" + str(uuid.uuid4()) + "}" print(flag) m = libnum.s2n(flag)
while1: e = random.randint(100, 1000) p = libnum.generate_prime(1024) q = libnum.generate_prime(1024) phi_n = (p - 1) * (q - 1) t = gmpy2.gcd(e, phi_n) if t == e: continue t1 = e // t if gmpy2.invert(t1, phi_n) and t > 1: break n = p * q c = pow(m, e, n) print("p=", p) print("q=", q) print("e=", e) print("c=", c)
exp.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
from Crypto.Util.number import * import gmpy2
p = 171854505164939390402295426493389586289972154851849140728417624619463988154808053805729538974688869671559032639921300088271234681410193379381085714252211392886408792711387524667824537369266846649573070209815436507363007636943912350208275895292853801665488228125846058987049326903498661007035974420392738723323 q = 145951936627745243523384785325963094339728144811023266133546816860787405503371056873662508073284279180417626507724315776654624382665743082805910036891739754019932290977071276850239245644056698685966997752654383650764557358649666141576105936215709831181842086893228254304235678475375978464394818353375373451573 n = p*q e = 830 c= 4413268199893347044741276120215584703428167052744516280494996526431559720190092261631829389527634625276020346166956540800884139234489942113764564139232948414263452549927818365096023041932432723988241639527832673120924732407691135173154085803338322715604275530735968992726708155724384432557207264839248502158712330572704509492520346044648676055223193900826626346707083590815897507927683083455678855000344499804465073698745769989966769567497677402668725931090596642504740789789740965769347050166069295727209131555338513809368814890255851742010120871635378654904140016065148709710206173069000137023824698858539843753921
phi = (p-1)*(q-1) t = gmpy2.gcd(e,phi) if t != 1: print(t) e1 = e // t d = gmpy2.invert(e1,phi) m = pow(c,d,n) print(long_to_bytes(gmpy2.iroot(m,t)[0]))
""" c = 3136716033729406787100895984031132591372408032397380657110411936279557864804613451803228203558942365572618855741582340710496951283998288077886684480798840909615843832888291672118118174611935731391325961 p = 6995170125828760803175021463861846748101755707034027896253692749933464491557662142860042836548188827042797130278821285624095121174944527912522028416084887 q = 12272700813225623560132355056448185486009112345760462061684545263916365691442580749089054915285013385322910087693364777427389347919562222271368766699836367 n = 85849630091910220195429598000499270755938566349764235961421375317755949910077610512936495968854306764812963460054159547290157103999299511719875933657730205460710045409434205381402766954402709130620384187298033137488697869180531872534818830013412093865496100309052022972165149312556870258314510623053681685529 """
exp.sage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from Crypto.Util.number import *
c = 3136716033729406787100895984031132591372408032397380657110411936279557864804613451803228203558942365572618855741582340710496951283998288077886684480798840909615843832888291672118118174611935731391325961 p = 6995170125828760803175021463861846748101755707034027896253692749933464491557662142860042836548188827042797130278821285624095121174944527912522028416084887 q = 12272700813225623560132355056448185486009112345760462061684545263916365691442580749089054915285013385322910087693364777427389347919562222271368766699836367 n = 85849630091910220195429598000499270755938566349764235961421375317755949910077610512936495968854306764812963460054159547290157103999299511719875933657730205460710045409434205381402766954402709130620384187298033137488697869180531872534818830013412093865496100309052022972165149312556870258314510623053681685529
R.<x> = PolynomialRing(Zmod(p)) f = x^2 - c res1 = f.roots()
R.<x> = PolynomialRing(Zmod(q)) f = x^2 - c res2 = f.roots()
for i in res1: for j in res2: m = crt([int(i[0]),int(j[0])],[p,q]) print(long_to_bytes(m))
当$m < p$的时候,不需要中国剩余定理也能出
两种处理方式的综合
例题1——2022ctfshow卷王杯
task.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from Crypto.Util.number import bytes_to_long from secrets import p,q,r,s,t,flag
n = p * q * r * s * t e = 2 m = bytes_to_long(os.urandom(500) + flag) c = pow(m,e,n)
from sympy.ntheory.modular import crt import gmpy2 from Crypto.Util.number import *
p = 145332367700944303747548912160113939198078051436029477960348968315913956664143693347226702600438608693933768134575289286283267810723137895903153829001826223446477799895493265422562348917012216790077395795861238257357035152687833639085415763850743538206986781418939737511715957738982536382066693822159860701263 q = 116660458253067608044065523310547233337730583902133756095473339390057738510707447906971188577217274861047379404014140178165569604404468897712846876108444468370709141219302291601408652742006268186059762087155933131837323952675627966299810891805398890428420575425160696531236660480933905879208166090591482794763 r = 157931722402853245421436270609912823260313730941283152856444641969403238646482562190531038393124087232554754746464603598717356255570166081501573727336977292059427220330169044611674973569766966838498453232642731737958791706086957762244686953294662693939604300864961637325536379321027705854708492453330690705531 s = 100973451687449518854742673778783266158999451072058606348222018797891147675959983616210003484476577612134482311993701677242007759556951494382833070563369964294544839433671087037596159753825249018950693369209927951667775267086896180395776150188902057785214767230658487267587289809918132337927575673868568976679 t = 93960345071948255233882121683650797512129333868351496468898834736770441398743300745703393838320587998953678254272245400344928586394089488734271897540051673996675973642347859306921527430850673334243441180183460927865980713929789963587608547554858491264614271309608925634272282292964002897650355047792764365447 c = 9144597920381774885442906257311149465702295057238600973973598305004391534618770363098565074541384771979931799878381439264848137810353858418200992191234142740194489573540381681161219332611454834544291634628456257670178843484698324641739324687497388018406214041657278323855749902661752448796122517061920880552011343608609622885787617238758769398972009949575526258430282648817039091284796330585349957724522615105102735930258969562103112238020133587096826386028128471852377225525357348919204333121695432662339443004327748973224423132988376298843862056631045488285859621661802413201793962883794915513510467912312842687601478117040419013468059983777273699192408773551806581458197324620065210523913467414181480875280203580147077789063808832356486197271376615883221558265591069223727607585313240243619515521180600435114131162272519949101464089935441251751426683447701142156416866113627126765919641034042927519834229168536331952275698122511502745177547569813354280565828372968703810158857859460406828090199683324760956105682902577189283246483314689365570862217407333103243336691401424548702387876409228977278498691200028282744239512091373110111792177228979867318546462714521296256938374618636206565791541769138267080789842400796973226733816939794717596194090232425688504890234304977612220790858557639246367437740975495450011676714198668471438814299689325208882261918460708833888406187912527346628912894921059735420931656953236560178909180587372589456926690219114173193202048332172538564489660440225377822914097420807957784201785024166011709377791129 e = 2
R.<x> = PolynomialRing(Zmod(p)) f = x^e - c f = f.monic() res1 = f.roots()
R.<x> = PolynomialRing(Zmod(q)) f = x^e - c f = f.monic() res2 = f.roots()
R.<x> = PolynomialRing(Zmod(r)) f = x^e - c f = f.monic() res3 = f.roots()
R.<x> = PolynomialRing(Zmod(s)) f = x^e - c f = f.monic() res4 = f.roots()
R.<x> = PolynomialRing(Zmod(t)) f = x^e - c f = f.monic() res5 = f.roots()
for i in res1: for j in res2: for k in res3: for a in res4: for b in res5: m_list = [int(i[0]),int(j[0]),int(k[0]),int(a[0]),int(b[0])] a_list= [p,q,r,s,t] solve = CRT_list(m_list,a_list) flag = long_to_bytes(solve) ifb'ctfshow'in flag: print(flag) # ctfshow{D0_y0u_R3aLly_Kn0w_Ra8IN_alg0RI7HM?}
phi1 = (p1-1)*(q1-1) phi2 = (p2-1)*(q2-1) defdecrypt(c,e,phi,n): t = gmpy2.gcd(e,phi) if t != 1: e1 = e // t d = gmpy2.invert(e1,phi) m = pow(c,d,n) return m res1 = decrypt(c1,e1,phi1,n1) res2 = decrypt(c2,e2,phi2,n2)
res = crt([res1,res2],[n1,n2]) phi = (p1 - 1)*(q2 - 1) n = p1 * q2 m2 = decrypt(res,14,phi,n)
for i in sol1: for j in sol2: m = crt([int(i[0]),int(j[0])],[p1,q2]) print(long_to_bytes(m)) # EIS{Comm0n_Div15or_plus_CRT_is_so_easy|cb2733b9e69ab3a9bd526fa1}
c =821562155714228494350968286343241874202753771452745916900616612053610190986294297934462409534126095213198464996196364868528238538372119009517541428785632007137206972918081643841690069171088425923887930051635578719252415693144672179185417101210954906623326286804995637775062840407550493095027500638719998 p =19897846550210846565807788524492364050901480736489979129040638436463635149815428186161001280958415730930156556581274966745574164608778242980049611665461488306439665507971670397595035647317930606555771720849158745264269952668944940061576328219674721623208805067371087817766416300084129945316973502412996143
from Crypto.Util.number import * import gmpy2 import time import random from tqdm import tqdm
e = 1801 c = 821562155714228494350968286343241874202753771452745916900616612053610190986294297934462409534126095213198464996196364868528238538372119009517541428785632007137206972918081643841690069171088425923887930051635578719252415693144672179185417101210954906623326286804995637775062840407550493095027500638719998 p = 19897846550210846565807788524492364050901480736489979129040638436463635149815428186161001280958415730930156556581274966745574164608778242980049611665461488306439665507971670397595035647317930606555771720849158745264269952668944940061576328219674721623208805067371087817766416300084129945316973502412996143
defAMM(o, r, q): start = time.time() print('\n----------------------------------------------------------------------------------') print('Start to run Adleman-Manders-Miller Root Extraction Method') print('Try to find one {:#x}th root of {} modulo {}'.format(r, o, 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)) 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(a, d) 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 deffindAllPRoot(p, e): print("Start to find all the Primitive {:#x}th root of 1 modulo {}.".format(e, p)) start = time.time() proot = set() whilelen(proot) < e: proot.add(pow(random.randint(2, p-1), (p-1)//e, p)) end = time.time() print("Finished in {} seconds.".format(end - start)) return proot
deffindAllSolutions(mp, proot, cp, p): print("Start to find all the {:#x}th root of {} modulo {}.".format(e, cp, p)) start = time.time() all_mp = set() for root in proot: mp2 = mp * root % p assert(pow(mp2, e, p) == cp) all_mp.add(mp2) end = time.time() print("Finished in {} seconds.".format(end - start)) return all_mp
for i in mps: flag = long_to_bytes(int(i)) ifb'flag'in flag: print(flag) # flag{Enj01_m1sc_A0d_cr0}
另一种解法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
from Crypto.Util.number import *
e = 1801 c = 821562155714228494350968286343241874202753771452745916900616612053610190986294297934462409534126095213198464996196364868528238538372119009517541428785632007137206972918081643841690069171088425923887930051635578719252415693144672179185417101210954906623326286804995637775062840407550493095027500638719998 p = 19897846550210846565807788524492364050901480736489979129040638436463635149815428186161001280958415730930156556581274966745574164608778242980049611665461488306439665507971670397595035647317930606555771720849158745264269952668944940061576328219674721623208805067371087817766416300084129945316973502412996143
import gmpy2 import libnum import random import uuid
flag = "flag{" + str(uuid.uuid4()) + "}" print(flag) m = libnum.s2n(flag) p = libnum.generate_prime(512) q = libnum.generate_prime(512) n = p * q e = 2 c = pow(m, e, n) print("p=", p) print("q=", q) print("n=", n) print("c=", c) print("e=", e)
p = 13314362720917602133969793252481444316247612541287913579795797774897851142465370812511985605994998073433561235021924708067874236781706611485522371488232623 q = 10711516497864529822020903304369858958930042711451857859791558135232705853374332295320094676061294774680048276363750484537945067473851592618816785752809803 n = 142617015943661365869136488949628046624950745436416195175536421279851751774402291519010668496730147866462378904972514253007029491632653461771497495733152729212900224242492221133006321373540619376544526943204146111719397605460529531608654329571698129077171108416638061409327725762114841023226929126272738803269 c = 3136716033731857617369889733308430982192049734478834150612954276064433287574994581343168243135342097712334250357890492021703404008556737899236668582163912130637742227325170121650071435166332685070232329 e = 2
R.<x> = PolynomialRing(Zmod(p)) f = x^2 - c res1 = f.roots()
R.<x> = PolynomialRing(Zmod(q)) f = x^2 - c res2 = f.roots()
for i in res1: for j in res2: m = crt([int(i[0]),int(j[0])],[p,q]) print(long_to_bytes(int(m)))
多次解Rabin
题目来源NSSCTF ROUND#11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
from Crypto.Util.number import * from secret import flag
p = getPrime(512) q = getPrime(512) assert p > q n = p*q e = 65536 m = bytes_to_long(flag) num1 = (pow(p,e,n)-pow(q,e,n)) % n num2 = pow(p-q,e,n) c = pow(m,e,n)
cs = [c] for i inrange(16): ps = [] for c2 in cs: r = pow(c2, (p + 1) // 4, p) s = pow(c2, (q + 1) // 4, q)
x = (r * inv_q * q + s * inv_p * p) % n y = (r * inv_q * q - s * inv_p * p) % n if x notin ps: ps.append(x) if n - x notin ps: ps.append(n - x) if y notin ps: ps.append(y) if n - y notin ps: ps.append(n - y) cs = ps
m = libnum.s2n(flag) p = libnum.generate_prime(512) q = libnum.generate_prime(512) n = p * q m1 = ((m >> 300) << 300) e = 3 c = pow(m, e, n)
print("n =", n) print("c =", c) print("e =", e) print("m1 =", m1) """ n = 89449659165373664419599666603079125351786161891254199117045952387178298091726343680198833028457552478360463001966084179577576990766724383528486250298768666097882661565765202949881673799125950008229527772973603379916117935790703989917655837756217393025354969853495238961762669326690100145696530290685977278593 c = 175676150266637032446485438802315236532165610668245377791442524569846934587347877260997089793552024464242407355427955652050327122630649033488529560135042402737218074153101020540979958586399761415542047850951996733997549252310811350769808163958303048261417309757780500291307110596781699418188514782424677 e = 3 m1 = 56006392791978632601307849398736624069259692797382051345599538506145258779412417900757721790977933312 """
exp.sage
1 2 3 4 5 6 7 8 9 10 11 12 13 14
from Crypto.Util.number import long_to_bytes
n = 89449659165373664419599666603079125351786161891254199117045952387178298091726343680198833028457552478360463001966084179577576990766724383528486250298768666097882661565765202949881673799125950008229527772973603379916117935790703989917655837756217393025354969853495238961762669326690100145696530290685977278593 c = 175676150266637032446485438802315236532165610668245377791442524569846934587347877260997089793552024464242407355427955652050327122630649033488529560135042402737218074153101020540979958586399761415542047850951996733997549252310811350769808163958303048261417309757780500291307110596781699418188514782424677 e = 3 m1 = 56006392791978632601307849398736624069259692797382051345599538506145258779412417900757721790977933312
R.<x> = PolynomialRing(Zmod(n)) f = (m1 + x)^e - c res = f.small_roots(X = 2^300,beta = 1) if res != []: m = m1 + res[0] print(long_to_bytes(int(m)))
情况2:利用flag头等已知信息
例题——2024XYCTF 反方向的密码 相思
task.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from Crypto.Util.number import * import hashlib from secrets import flag
m = bytes_to_long(pad(flag)) p = getStrongPrime(512) q = getStrongPrime(512) n = p * q e = 3 print(pow(m, e, n)) print(n) # 120440199294949712392334113337541924034371176306546446428347114627162894108760435789068328282135879182130546564535108930827440004987170619301799710272329673259390065147556073101312748104743572369383346039000998822862286001416166288971531241789864076857299162050026949096919395896174243383291126202796610039053 # 143413213355903851638663645270518081058249439863120739973910994223793329606595495141951165221740599158773181585002460087410975579141155680671886930801733174300593785562287068287654547100320094291092508723488470015821072834947151827362715749438612812148855627557719115676595686347541785037035334177162406305243
c = 120440199294949712392334113337541924034371176306546446428347114627162894108760435789068328282135879182130546564535108930827440004987170619301799710272329673259390065147556073101312748104743572369383346039000998822862286001416166288971531241789864076857299162050026949096919395896174243383291126202796610039053 n = 143413213355903851638663645270518081058249439863120739973910994223793329606595495141951165221740599158773181585002460087410975579141155680671886930801733174300593785562287068287654547100320094291092508723488470015821072834947151827362715749438612812148855627557719115676595686347541785037035334177162406305243
flag = "flag{" + str(uuid.uuid4()) + "}" m = libnum.s2n(flag) p = libnum.generate_prime(1024) q = libnum.generate_prime(1024) n = p * q e = 65537 p1 = ((p >> 256) << 256) c = pow(m, e, n) print("n =", n) print("c =", c) print("e =", e) print("p1 =", p1) """ n = 25412529168113241701978154909309452589891277619233574149177682749114694998754065178357796120946044207438029964927062297462478639487054245771692139625849995546462111249773750389956600652870714030563605023702161513442866609937847422556059608499864578170270126239637444959812121589196901129645564580908045557218006330672260617798453633543627607790892960895904087738679492228779277752739734608284915605638138243297198792777112179909034121738317943791638151509031222745851940804609153731748776002638455252820409482251897734211263626398933847861538578761515233197699408866935293343456161438639398890089434015875977218250399 c = 11832017536820850822990089557724269863899815227776358234936663617587241671432348464674233033185082415100398087268764691266148966050993867487703853445199053612975005945065305992972854436834255574224203980327515867976652513642869374642661621841855735886358661741631500029948344306194937625466742946921106659582316643893949403548828556819907948714983462986507817955376793071143086032085845182853003634916425312911434933416448638808160541352834497686975061092257675653110414264672490891200433992043618040530275350634723043175666891682239033429796170154980192829798607191555482341170827932551423162833473892514972387547888 e = 65537 p1 = 174553077493661081676268351785469032783476528521014320107330821253075206651723812600343204348306643031578070226902979453793372875180300634043015175074746912397887970195415967163417566827459210112867899640388623940244194079258961165834045219906954836822089775153665401751146892024327963835455414059781203165184 """
exp.sage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
import gmpy2 from Crypto.Util.number import *
n = 25412529168113241701978154909309452589891277619233574149177682749114694998754065178357796120946044207438029964927062297462478639487054245771692139625849995546462111249773750389956600652870714030563605023702161513442866609937847422556059608499864578170270126239637444959812121589196901129645564580908045557218006330672260617798453633543627607790892960895904087738679492228779277752739734608284915605638138243297198792777112179909034121738317943791638151509031222745851940804609153731748776002638455252820409482251897734211263626398933847861538578761515233197699408866935293343456161438639398890089434015875977218250399 c = 11832017536820850822990089557724269863899815227776358234936663617587241671432348464674233033185082415100398087268764691266148966050993867487703853445199053612975005945065305992972854436834255574224203980327515867976652513642869374642661621841855735886358661741631500029948344306194937625466742946921106659582316643893949403548828556819907948714983462986507817955376793071143086032085845182853003634916425312911434933416448638808160541352834497686975061092257675653110414264672490891200433992043618040530275350634723043175666891682239033429796170154980192829798607191555482341170827932551423162833473892514972387547888 e = 65537 p_high = 174553077493661081676268351785469032783476528521014320107330821253075206651723812600343204348306643031578070226902979453793372875180300634043015175074746912397887970195415967163417566827459210112867899640388623940244194079258961165834045219906954836822089775153665401751146892024327963835455414059781203165184
R.<x> = PolynomialRing(Zmod(n)) f = p_high + x res = f.small_roots(X = 2^256,beta = 0.4) if res != []: p = p_high + int(res[0]) q = n // p d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(int(m)))
例题2——2023LitCTF Babyxor
task.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from Crypto.Util.number import * from secret import flag
m = bytes_to_long(flag) assertlen(flag)==32 p = getPrime(512) q = getPrime(512) n = p*q e = 65537 c1 = p^m c2 = pow(m,e,n) print(f'n = {n}') print(f'c1 = {c1}') print(f'c2 = {c2}') """ n = 139167681803392690594490403105432649693546256181767408269202101512534988406137879788255103631885736461742577594980136624933914700779445704490217419248411578290305101891222576080645870988658334799437317221565839991979543660824098367011942169305111105129234902517835649895908656770416774539906212596072334423407 c1 = 11201139662236758800406931253538295757259990870588609533820056210585752522925690049252488581929717556881067021381940083808024384402885422258545946243513996 c2 = 112016152270171196606652761990170033221036025260883289104273504703557624964071464062375228351458191745141525003775876044271210498526920529385038130932141551598616579917681815276713386113932345056134302042399379895915706991873687943357627747262597883603999621939794450743982662393955266685255577026078256473601 """
import gmpy2 from tqdm import * from Crypto.Util.number import *
n = 139167681803392690594490403105432649693546256181767408269202101512534988406137879788255103631885736461742577594980136624933914700779445704490217419248411578290305101891222576080645870988658334799437317221565839991979543660824098367011942169305111105129234902517835649895908656770416774539906212596072334423407 c1 = 11201139662236758800406931253538295757259990870588609533820056210585752522925690049252488581929717556881067021381940083808024384402885422258545946243513996 c2 = 112016152270171196606652761990170033221036025260883289104273504703557624964071464062375228351458191745141525003775876044271210498526920529385038130932141551598616579917681815276713386113932345056134302042399379895915706991873687943357627747262597883603999621939794450743982662393955266685255577026078256473601 e = 65537 pbits = 512
p_high = c1 >> 256 for i in trange(2**8): p4 = p_high << 8#这里需要先爆破8位,使得知道264位以后再恢复p p4 = p4 + i kbits = pbits - p4.nbits() p4 = p4 << kbits R.<x> = PolynomialRing(Zmod(n)) f = x + p4 res = f.small_roots(X=2^kbits, beta=0.4, epsilon=0.01) if res != []: p = p4 + int(x[0]) q = n // p d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c2,d,n) print(long_to_bytes(int(m))) break
p0 = 111984935426070810628244029907949697819351004665202173622240566580193974673163315128983603277856218378729883402496424467491406698035050254407170555432448523469880166015507303737468316933545613178461925283040643344197452758878116752692499745309765526523083790825015522124083482964296662782850606081657447935191 c = 6187845844052645335477666563187579997555293403110620879123121166924703361821847984760733842049752886698011561451715570810292323756091403783920480396052120046379755571530451812078574368413924390017994278703794257118954968480994077586245800902748815905644287545189605031883291488844527496906890127546594960138582150272568163575590734246290813150131949296550974206595456421136190026954855755623761557179760444906148376433584795779131477110538212742401420633087881506416368853221110426491868881029814841479615979710066371796507692025126150957315754738584387325388998533227577023142894876376702128870643448600352603905149 n = 14195810221536708489210274086946022255792382922322850338983263099316341767896809249586174293795778082892237356582757544364274847341220303582304283372889068290282580493623042441421715338444710303281638639785784613434328659529884972238348336971186339482788748316527376410510261228354155806341136524162787121212184386900663470590652770503564816948407257603737938414126069053610568675347826390537145556511048774030823322301932088595499671755944744816524811272617200683384649389274196659297432212847319503330409792704612575414010711158873031786577877685578976140462539734553598745329712188216200905451774357282278403189943 e = 65537
f = phigh + x*2**444 + plow f = f.monic() res = f.small_roots(X=2^432,beta=0.4) if res != []: p = int(phigh + res[0]*2**444+plow) print("p =",p) q = n // p d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(int(m)))
十六、d低位泄露
攻击条件:e在可爆破范围,并且已知d的低位
推导: $$ \because ed \equiv 1 \mod \phi(n) $$
$$ \therefore ed = k(p-1)(q-1) + 1 $$
即 $$ ed = kn - kp - kq + k + 1 $$ 假设我们知道d的低L位,并且记为$d_{low}$,我们对上式同模$2^L$,于是有 $$ ed_{low} \equiv kn - kp - kq + k + 1 \mod 2^L $$ 两边同时乘上p得到 $$ ed_{low} \equiv knp -kp^2 - kn +(k+1)p \mod 2^L $$ 此时上式只有k和p是未知的,因为$0 < k < e$,所以可对k进行爆破,解同余式得到p的低位,再用coppersmith恢复p
from Crypto.Util.number import long_to_bytes,inverse from tqdm import *
n = 52742121495363456830645578439066440260525635701449452038623040460534514676940962601979528301396249463310635013618692939847284377316096998174539886900202801371512846078230196507601167693580439935790730812348102969592553942497201279143623565409782692807615767067494338127711608771029145341503069929345973282553 e = 3 c = 175676150266403096249431407570554929021369604168136874268275844375181688894753012319267533769923727863698572157250017689244151605424698000831986135513112136594197978237874400825236288135820643994889528170234514127521418132167932446836545721803621236277931291609749528037915073270452302613264065194049125 dlow = 8681746171122274095992828774600905650260279086049883317863420271848455130773826835383939352151607850521826888046119078445911475580784484455485323
defget_full_p(p_low,n,pbits): kbits = p_low.bit_length() R.<x> = PolynomialRing(Zmod(n)) f = x * 2^kbits + p_low f = f.monic() res = f.small_roots(X = 2^(pbits-kbits),beta=0.4) if res != []: p = int(res[0]) * 2^kbits + p_low return p for k in trange(e): var('p') f1 = e*dlow*p - (k*n*p - k*p^2 - k*n + (k+1)*p) roots = solve_mod(f1,2^486) if roots != []: for root in roots: ifint(root[0]).bit_length() == 486: p = get_full_p(int(root[0]),n,512) if p: q = n // p d = inverse(3,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m)) break
''' e = 149 leak = 6001958312144157007304943931113872134090201010357773442954181100786589106572169 n = 88436063749749362190546240596734626745594171540325086418270903156390958817492063940459108934841028734921718351342152598224670602551497995639921650979296052943953491639892805985538785565357751736799561653032725751622522198746331856539251721033316195306373318196300612386897339425222615697620795751869751705629 c = 1206332017436789083799133504302957634035030644841294494992108068042941783794804420630684301945366528832108224264145563741764232409333108261614056154508904583078897178425071831580459193200987943565099780857889864631160747321901113496943710282498262354984634755751858251005566753245882185271726628553508627299 '''
e = 149 d0 = 6001958312144157007304943931113872134090201010357773442954181100786589106572169 n = 88436063749749362190546240596734626745594171540325086418270903156390958817492063940459108934841028734921718351342152598224670602551497995639921650979296052943953491639892805985538785565357751736799561653032725751622522198746331856539251721033316195306373318196300612386897339425222615697620795751869751705629 c = 1206332017436789083799133504302957634035030644841294494992108068042941783794804420630684301945366528832108224264145563741764232409333108261614056154508904583078897178425071831580459193200987943565099780857889864631160747321901113496943710282498262354984634755751858251005566753245882185271726628553508627299
for k inrange(1,e): var("p") temp = e*d0*p f = (k*n*p - k*p^2 - k*n + k*p + p) - temp == 0
roots = solve_mod([f],2^265) if roots != []: for root in roots: plow = int(root[0]) # print(plow) # 55136429770900518182274612434328885021714880080534773062619965935822096183916139 R.<x> = PolynomialRing(Zmod(n)) f1 = x*2^265 + plow f1 = f1.monic() res = f1.small_roots(X=2^247,beta=0.5,epsilon = 0.01) if res != []: print(res) # [188210689227294472160085325314952069542671020803828390144430392548173787275] p = int(res[0])*2^265 + plow print("p =",p) # p = 11158174168280917736979570452068827611755694573672250873587467083259280584739528118050085070475912733864211083865201596017044398008278425498714490994488939 q = n // p d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(int(m))) # flag{827ccb0eea8a706c4c34a16891f84e7b} break
n = 51296885372346449295388453471330409021784141081351581975478435681552082076338697136130122011636685327781785488670769096434920591920054441921039812310126089859349902066456998315283909435249794317277620588552441456327265553018986591779396701680997794937951231970194353001576159809798153970829987274504038146741 a = 13256631249970000274738888132534852767685499642889351632072622194777502848070957827974250425805779856662241409663031192870528911932663995606616763982320967 b = 12614470377409090738391280373352373943201882741276992121990944593827605866548572392808272414120477304486154096358852845785437999246453926812759725932442170 c1 = 18617698095122597355752178584860764221736156139844401400942959000560180868595058572264330257490645079792321778926462300410653970722619332098601515399526245808718518153518824404167374361098424325296872587362792839831578589407441739040578339310283844080111189381106274103089079702496168766831316853664552253142 c2 = 14091361528414093900688440242152327115109256507133728799758289918462970724109343410464537203689727409590796472177295835710571700501895484300979622506298961999001641059179449655629481072402234965831697915939034769804437452528921599125823412464950939837343822566667533463393026895985173157447434429906021792720 e = 17
""" 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 = 0xc2fd2913bae61f845ac94e4ee1bb10d8531dda830d31bb221dac5f179a8f883f15046d7aa179aff848db2734b8f88cc73d09f35c445c74ee35b01a96eb7b0a6ad9cb9ccd6c02c3f8c55ecabb55501bb2c318a38cac2db69d510e152756054aaed064ac2a454e46d9b3b755b67b46906fbff8dd9aeca6755909333f5f81bf74db # the public exponent e = 0x19441f679c9609f2484eb9b2658d7138252b847b2ed8ad182be7976ed57a3e441af14897ce041f3e07916445b88181c22f510150584eee4b0f776a5a487a4472a99f2ddc95efdd2b380ab4480533808b8c92e63ace57fb42bac8315fa487d03bec86d854314bc2ec4f99b192bb98710be151599d60f224114f6b33f47e357517
# the hypothesis on the private exponent (the theoretical maximum is 0.292) delta = .18# 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)
# # Find the solutions! #
# Checking bounds if debug: print("=== checking values ===") print("* delta:", delta) print("* delta < 0.292", delta < 0.292) print("* size of e:", int(log(e)/log(2))) print("* size of N:", int(log(N)/log(2))) print("* m:", m, ", t:", t)
""" 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 = 116518679305515263290840706715579691213922169271634579327519562902613543582623449606741546472920401997930041388553141909069487589461948798111698856100819163407893673249162209631978914843896272256274862501461321020961958367098759183487116417487922645782638510876609728886007680825340200888068103951956139343723 e = 113449247876071397911206070019495939088171696712182747502133063172021565345788627261740950665891922659340020397229619329204520999096535909867327960323598168596664323692312516466648588320607291284630435682282630745947689431909998401389566081966753438869725583665294310689820290368901166811028660086977458571233 # the public exponent # the hypothesis on the private exponent (the theoretical maximum is 0.292) delta = .27# 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 = 5# 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)
# # Find the solutions! #
# Checking bounds if debug: print("=== checking values ===") print("* delta:", delta) print("* delta < 0.292", delta < 0.292) print("* size of e:", int(log(e)/log(2))) print("* size of N:", int(log(N)/log(2))) print("* m:", m, ", t:", t)
from Crypto.Util.number import * from secret import flag
p = getPrime(512) q = getPrime(512) n = p * q d = getPrime(299) e = inverse(d,(p-1)*(q-1)) m = bytes_to_long(flag) c = pow(m,e,n) hint1 = p >> (512-70) hint2 = q >> (512-70)
import libnum import gmpy2 import uuid from Crypto.Util.number import *
flag = "flag{" + str(uuid.uuid4()) + "}" m = libnum.s2n(flag)
e = 65537 p = getPrime(1024) q = getPrime(1024 n = p * q c = pow(m, e, n) hint = pow(2020 * p + 2021, q, n) print(f'n={n}') print(f'c={c}') print(f'hint={hint}')
把hint展开 $$ hint \equiv (2020p + 2021)^q \mod n $$ 模$p$能得到 $$ hint \equiv 2021^q \mod p $$ 两边同时取p次方 $$ hint^p \equiv 2021^n \mod p $$ 即 $$ hint \equiv 2021^n \mod p $$ p = gcd(pow(2021,n,n) - hint,n)
exp
1 2 3 4 5 6 7 8 9 10 11 12 13
from Crypto.Util.number import * import gmpy2
n = 27020725261160598541077357737650775795182555998856810737571508044949928734067444441660366270392732456051807439301564552672200975582350577967001486740668193835704559129378410828266554536148151615878808327988333060924165410762016082268322936465413880236634083213834739549234631742766416876749808978934944262651307600621868854944164060642189749365967978497831698002669974744487926082412272998646851047638183126945784060957075393737537570645086672473571281053798891685646561828588448040073373363454584468753860529849749093081434144360661566815886630699933232263079413562069476421802192735693386029862725050469209845710383 c = 10188807385387617708190575473905502994151677148079820873886980571555051900701810208218351138721306416600688313703084580808183634201231599134123549448962443376514560489130860694363901933597676373555599555647232128717993571185822894818704143675318690577221330618533739592165564396729937983659337232822442555504262694675199751730664450120569727835850996566436129543730932040989365233424791093843941154003052950306359994891955336607690065213304872738280674213630736611351982705373394299097653653497017756036211550125607093109216729483090391729134062236908282557149575812220142872855836932590459512028618076264332235518829 hint = 15179972145975733285419381814235528011288991423484121653543845156913121513320504879647666067298415751234264897435338898933073713420024176276221164394369781676781604128149168834126855517212300158864797800121336042194751965268493010327202598446572764475343894613152062609436699715193914479572113800212525965140106015838636914979735618606768207651697548364440806425770871133439416876157686985836939255598747973339866125864303982956813846287509191028829738926404992619459242904729015823730553526572575372668559669124599614613391797015393641171177282129497503752370800088634017972208535899870704612274473042064675033593148 e = 65537
p = gmpy2.gcd(pow(2021,n,n)-hint,n) q = n // p d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m))
flag = "flag{" + str(uuid.uuid4()) + "}" print(flag) m = libnum.s2n(flag) p = libnum.generate_prime(512) q = libnum.generate_prime(512) e = 65537 n = p * q h = 20211102 hc = pow(h + p * 1111, e, n) c = pow(m, e, n) print("hc=", hc) print("n=", n) print("c=", c) hc = 71505320953946158049530109094654497075489963071106175336722892393493112481336409391299522595724154571954223093317880494307263262649833222750675105885636892419350501821324979706283867758665536771783209816719106279467902518895579024290387800216711663670572861182058425925280993190282267615052256942516011995207 n = 76856511192427852645963041043072791148703422665129663050712492700760489247788743818199589072069758934570218804936479267319288093436111548055922916898782764333246946326823653877357695179165138863843657328764265204547147092074499832221138997131011222722917338444675582832114206750168113207646100633238664244737 c = 39246179387125192271554620313966311736032348078183121707012959204367908070472764506984235827179206718838172586811066682034907967943722841257765922283692526422653916506577810629430853963448057701574209912936660396486847365579797147723437378122880075493171892191049105237005801787649587080840600670585409293046
$$ hint \equiv (ap + b)^e \mod n $$
两边模p得到 $$ hint \equiv b^e \mod p $$ p = gcd(pow(b,e,n)-hint,n)
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14
from Crypto.Util.number import * import gmpy2
hint = 71505320953946158049530109094654497075489963071106175336722892393493112481336409391299522595724154571954223093317880494307263262649833222750675105885636892419350501821324979706283867758665536771783209816719106279467902518895579024290387800216711663670572861182058425925280993190282267615052256942516011995207 n = 76856511192427852645963041043072791148703422665129663050712492700760489247788743818199589072069758934570218804936479267319288093436111548055922916898782764333246946326823653877357695179165138863843657328764265204547147092074499832221138997131011222722917338444675582832114206750168113207646100633238664244737 c = 39246179387125192271554620313966311736032348078183121707012959204367908070472764506984235827179206718838172586811066682034907967943722841257765922283692526422653916506577810629430853963448057701574209912936660396486847365579797147723437378122880075493171892191049105237005801787649587080840600670585409293046 e = 65537 b = 20211102
p = gmpy2.gcd(pow(b,e,n)-hint,n) q = n // p d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m))
3.q = inverse(e,p)
task.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
import gmpy2 import libnum import uuid
flag = "flag{" + str(uuid.uuid4()) + "}" m = libnum.s2n(flag) e = 65537
while1: p = libnum.generate_prime(512) q = libnum.invmod(e, p) if gmpy2.is_prime(q): break n=p*q c=pow(m,e,n) print("n=",n) print("c=",c)
n = 58204114420266684815970658378327773998564393394613074044159240444415512492622689982761518905542522328879289101538953676661805875053162972893258897360344016406294652339343767887745752686437325346837603712186500309908703326587069304255508650910107794737000566778637055164127273830551001009133332601839918695739 c = 43430611858598126654595145883807180034546121754009334579568652220639483233618841529702503298293207886941913478597477904682701187000781983315547295293641024286170190626012102497319037012751300959255076727985925313853559910457404758461819072120343343943528618993507783981659418177044469142912677141806591464788 e = 65537
for k inrange(1,e): t = gmpy2.iroot((4*k*e*n + 1),2) if t[1]: p = (t[0]-1) // (2*k) q = n // p d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m)) break
n = 119168018353396473071220326930634033296857570351877525203349067654228903288865563346158289110924833018314600851680403536994000145188490252887831026813814036968773088160020677568623347649228357482873911613625537196000702331852604517461327776409524836030721808860499640682583008287503643735346752806150919473547 x = 20889450245206188360163017466832661797042512279294313816641964974342193835127401896327018708629718120262511077145232274218469726065543657294173612852238031375768722870519066517281989421725687761586428233882899166319861093186744865410310768961853709659722549327714475931676224727563796969392665870925936060875 y = 32080707538492572190029237251694217148237404571842762312567934187316746458298295007401945958852986479911593108750816992042333214302313415615710205763277908672519589955718578006218124903939275787171888825356704546781455848117466648569999021535956085557973651213126679157398458139672913801297571585910183741493
R.<m> = PolynomialRing(Zmod(n))
f = x*y - m^2 - m*(x - m + y - m) f = f.monic() root = f.small_roots(X=2^336) if root != []: print(long_to_bytes(int(root[0])))
5.leak = d + p
task.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
from Crypto.Util.number import * import uuid flag = "flag{" + str(uuid.uuid4()) + "}"
m = bytes_to_long(flag.encode()) p = getPrime(512) q = getPrime(512) n = p * q e = 65537 d = inverse(e,(p-1)*(q-1))
leak = d + p c = pow(m,e,n) print(f"leak = {leak}") print(f"c = {c}") print(f"n = {n}")
$$ leak = d + p $$
同时乘上e $$ leak \times e = ed + ep $$
$$ \because ed = k(p-1)(q-1) + 1 $$
$$ \therefore leak \times e = k(p-1)(q-1) + ep + 1 = (k_1 + e)(p-1) + e + 1 $$
则 $$ 2^{leak\times e} \equiv 2^{(p-1)(k_1+e)+e+1} \equiv 2^{e+1} \mod p $$ p = gcd(pow(2,e*leak,n) - pow(2,e+1,n),n)
exp.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from Crypto.Util.number import * import gmpy2
leak = 43773730595208010615167769243389712919043986781372553925103531305753192121900940758872887224717935746491356121136709395293427821519713664465479239343568683512805566797519940659245386786069452631897152582632812964236464253538638932777814445952543179981728372597574240011522586022744496408528369815424689627714 c = 32609109759602838902299290553935199233727818772965249106067660946940666082748851189532358246129713630287421754985189526470019256048805899987261287835158990237267846168718587057488187109882012577904592602367187436017302897260666096753156638501800052563311351183911829268477864436682312113353547663292164618797 n = 73687428902140845363357908478989818544523419338611246958530518113252515978963884581173646615800353308789787478447973996695401703969420384980841285031836556985268236880854319562700104921035182736733530699304849659644263120110205601793351720111745179867010541532557489688430577820860370652773129870929371931513 e = 65537
p = gmpy2.gcd(pow(2,leak * e,n) - pow(2,e + 1,n),n) q = n // p d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m))
from Crypto.Util.number import * from sympy import solve,symbols import gmpy2
e = 65537 c = 846622880180923496523897101093587388412673197929101816777894080453907929979417582433675846206418833989406082027835614960931951892393700870678469052366477889491688459558189367255658278968722099012534045477993924284003153851171132420751750724394405070269223797513951991873714156884423926582172189394011114952 n = 159452716285492879108396025652299064897348745847754101475050126796260046052685162344131542880739092630022413124977374334652652450809186959288635651980201026825896903174847709657312399801033678426271413442323084354665643010763178857967804623680894444913369256168333223214048037661178587978535722147091129404833 leak = 2669103705669857828725305123419482758456336465207378766363532584323475128597302561377245054918781031448710846825859151788151496659511563529987056456136018
p = symbols('p') q = symbols('q')
eq1 = 2*(p-q+1) - leak eq2 = p*q - n
solution = solve((eq1,eq2),(p,q)) print(solution)
p = int(solution[1][0]) q = int(solution[1][1]) d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m))
则 $$ m \equiv c^d \equiv c^{leak -(p+q)} \mod n $$ 因为$\phi(n) = n - (p+q) + 1$ $$ \therefore m \equiv c^{leak - (n + 1)} \mod n $$
exp.py
1 2 3 4 5 6 7 8
from Crypto.Util.number import *
c = 65194823373091792824101730983124740337276083358867621564067880339279446092377567969207237986613196892737474455781661885696122256698478429450971196633786693648866129636737262041654769618993094832127875251068775632567036646408374963058703320605733921797230106462440860984746880466416824674570639694481298708147 n = 101929257180069933443442160085713121307068880188090652033345240568607589666231813199686824369361640378636124324844158355533056421197926269617986872835671463371353540696806173813019752742218460997272803573114119876536384486655117245296360474103378827486280279523273344156760793016731778663058274770626116861407 leak = 87007773233816810147344015772388866522443114032719766646343787373996588014373656496789294836431302130125588646180886383013958151442324020038131736683796464202667423644714259545194662934238144990354387370533656134036753530002005551694211595695927699196016268145816389892292091218491443784193805171731592693841
e = 0x10001 n = p * q c = pow(m, e, n) leak = (pow(p, q, n) + pow(q, p, n)) % n print(f'{e = }') print(f'{c = }') print(f'{n = }') print(f'{leak = }')
$$ leak \equiv (p^q \mod n + q^p \mod n) \mod n $$
由费马小定理得 $$ leak \equiv (p^q \mod q + q^p \mod p) \mod n $$ 即 $$ leak \equiv p + q \mod n $$
$$ \because p + q < n $$
$$ \therefore leak = p + q $$
然后 $$ (p-q)^2 = (p+q)^2 - 4n = leak^2 - 4n $$
$$ \therefore p = \frac{((p+q) + (p-q))}{2} $$
或者解方程
exp.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14
from Crypto.Util.number import * import gmpy2
e = 65537 c = 59662555342583061013008608133060203475725526601468647442902301335538953096485921516133656618941085620436784211565880744663573927593670579237831797055934897166262528476227281479029026508166848256301828084036716500159067642101104810756620735383857351274773983199968924981397675373272878756685629789497697821620 n = 83332115751539889489689110273690067288993797655970253065863170986174973047785854940017477990345318506407680986257706329521142524295434171889087917406552261883625775754882538291980506944585738241124811588555071095223782766762626040473256423491630224616140407276984106458673447870374272906086783555489477673207 leak = 18881487897809480964326513919135880296801378921812225600834164247018332292886076618571738627353925482046410714540439662613766662197119044934743578662330528
p_q = gmpy2.iroot(leak ** 2 - 4 * n,2)[0] p = (leak + p_q) // 2 q = n // p d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m))
defchallenge1(m): p, q = [getPrime(bits) for i inrange(2)] if p <= q: p, q = q, p e = 0x10001 n = p * q c = pow(m, e, n) leak = (n + p) % (q-1) print('-------- challenge 1 --------') print(f'{e = }') print(f'{c = }') print(f'{n = }') print(f'{leak = }')
defchallenge2(m): p, q = [getPrime(bits) for i inrange(2)] e = 0x10001 n = p * q d = inverse(e, (p-1)*(q-1)) c = pow(m, e, n) leak = d + p + q print('-------- challenge 2 --------') print(f'{e = }') print(f'{c = }') print(f'{n = }') print(f'{leak = }')
defchallenge3(m): p, q = [getPrime(bits) for i inrange(2)] e = 0x10001 n = p * q c = pow(m, e, n) leak = (pow(p, q, n) + pow(q, p, n)) % n print('-------- challenge 3 --------') print(f'{e = }') print(f'{c = }') print(f'{n = }') print(f'{leak = }')
assertlen(flag) == 42 ms = [] for i inrange(0, 42, 14): ms.append(bytes_to_long(pad(flag[i:i+14], bits//4-1)))
m1, m2, m3 = ms challenge1(m1) challenge2(m2) challenge3(m3)
""" -------- challenge 1 -------- e = 65537 c = 112742443814287255411540092433156061065388404049949520959549377871297566383025041892192679147481155020865118811016470498351633875090973546567374001852295013083192495299811476604405637385307524194793969533646755764136014187430115618114840780368311166911900457224593131166970676797547489278410997707815915932756 n = 121127425328043404860413278637978444801342472819958112597540188142689720655042880213001676368390521140660355813910726809125567752172921410143437643574528335234973793653775043030021036875866776532570781661875022102733555943967261003246543180935987772711036868216508554536086688819118597075508026787867088355603 leak = 216638862637129382765636503118049146067015523924032194492700294200289728064297722088882791754351329407138196573832392846467607399504585045028165699421278 -------- challenge 2 -------- e = 65537 c = 7964477910021153997178145480752641882728907630831216554750778499596527781702830885213467912351097301767341858663701574005489585561370961723264247818377063081744522471774208105250855114831033452448184392499682147532404562876275189577321587660597603848038824026981539659156304028998137796242331160312370913038 n = 140571013522095816880929287025269553867630639381779595547026503691829940612178900269986625350464874598461222087427155791855120339533208468121389480964471710028253589422629569889402475311387750348466199387760629889238062977271925350490110043385800605640905324122017637306715108727700910035925728362455954862209 leak = 58442382248753295429370894053397615609981110383986887405127350139482893508400422595729520437678203735054593866306478994471465948872565590901376309380029015549809468112086393107585011072503638322671608471684607214064187044372418770555236721845694224676090744181562673509234801011420696349507624867568099759003 -------- challenge 3 -------- e = 65537 c = 54161995127842474543974770981473422085334044100057089719350274921419091368361244533281599379235907845996678762379778310924192757650322930707785543132446159092950451255660204858292974657119337026589911330412367633761103944916751660957776230135927005700707688661350641600954072696774954805514477330339449799540 n = 88207747624007183083381863279444163105330473097729276113333026679597864128605555600000789783468271680476780366740448641311570797876037993255307716167149079618302706650018518487351604778857406170722209469765782625409279109832638886179654096975665134276856272488090272822541461702907181545730309689190333058151 leak = 19596671928335648228117128090384865424885102632642665068992144783391306491716530155291726644158221224616817878768426330717188403310818678195631582453246848 """
from Crypto.Util.number import * import sys sys.setrecursionlimit(3000)
gift = 39428646082513135314545544161912595458975375891528176714825766497155482031976852156313956476772023258684487799640179241987139554034654104867011313090105438798561154654679825702410748780286094326639330840289843154525176685892323447168072417654823748596238888125898914210332775882916911771786984574407163323116 N = 24044063028844014127418595700558729326190738802687551098858513077613750188240082663594575453404975706225242363463089392757425008423696150244560748490108425645064339883915929498539109384801415313004805586193044292137299902797522618277016789979196782551492020031695781792205215671106103568559626617762521687128199445018651010056934305055040748892733145467040663073395258760159451903432330506383025685265502086582538667772105057401245864822281535425692919273252955571196166824113519446568745718898654447958192533288063735350717599092500158028352667339959012630051251024677881674246253876293205648190626145653304572328397 c = 14883053247652228283811442762780942186987432684268901119544211089991663825267989728286381980568977804079766160707988623895155236079459150322336701772385709429870215701045797411519212730389048862111088898917402253368572002593328131895422933030329446097639972123501482601377059155708292321789694103528266681104521268192526745361895856566384239849048923482217529011549596939269967690907738755747213669693953769070736092857407573675987242774763239531688324956444305397953424851627349331117467417542814921554060612622936755420459029769026126293588814831034143264949347763031994934813475762839410192390466491651507733968227
# 低位往高位爆 deffindp(p,q): iflen(p) == 1024: pp = int(p,2) if N % pp == 0: print("p = ",pp) print("q = ",N // pp) qq = N // pp d = inverse(65537,(pp-1)*(qq-1)) m = pow(c,d,N) print(long_to_bytes(m)) return else: l = len(p) pp = int(p,2) qq = int(q,2) if (pp ^ qq) % (2 ** l) == gift % (2 ** l) and pp * qq % (2 ** l) == N % (2**l): findp('1' + p,'1' + q) findp('1' + p,'0' + q) findp('0' + p,'1' + q) findp('0' + p,'0' + q)
from Crypto.Util.number import * from secret import secret, flag defencrypt(m): returnpow(m, e, n) assert flag == b"dasctf{" + secret + b"}" e = 11 p = getPrime(512) q = getPrime(512) n = p * q P = getPrime(512) Q = getPrime(512) N = P * Q gift = P ^ (Q >> 16)
print(N, gift, pow(n, e, N)) print(encrypt(bytes_to_long(secret)), encrypt(bytes_to_long(flag)))
N = 75000029602085996700582008490482326525611947919932949726582734167668021800854674616074297109962078048435714672088452939300776268788888016125632084529419230038436738761550906906671010312930801751000022200360857089338231002088730471277277319253053479367509575754258003761447489654232217266317081318035524086377 gift = 8006730615575401350470175601463518481685396114003290299131469001242636369747855817476589805833427855228149768949773065563676033514362512835553274555294034 pow(n,e,N) = 14183763184495367653522884147951054630177015952745593358354098952173965560488104213517563098676028516541915855754066719475487503348914181674929072472238449853082118064823835322313680705889432313419976738694317594843046001448855575986413338142129464525633835911168202553914150009081557835620953018542067857943 pow(secret,e,n) = 69307306970629523181683439240748426263979206546157895088924929426911355406769672385984829784804673821643976780928024209092360092670457978154309402591145689825571209515868435608753923870043647892816574684663993415796465074027369407799009929334083395577490711236614662941070610575313972839165233651342137645009 pow(flag,e,n) = 46997465834324781573963709865566777091686340553483507705539161842460528999282057880362259416654012854237739527277448599755805614622531827257136959664035098209206110290879482726083191005164961200125296999449598766201435057091624225218351537278712880859703730566080874333989361396420522357001928540408351500991
sys.setrecursionlimit(3000) gift = 8006730615575401350470175601463518481685396114003290299131469001242636369747855817476589805833427855228149768949773065563676033514362512835553274555294034 N = 75000029602085996700582008490482326525611947919932949726582734167668021800854674616074297109962078048435714672088452939300776268788888016125632084529419230038436738761550906906671010312930801751000022200360857089338231002088730471277277319253053479367509575754258003761447489654232217266317081318035524086377
# 低位往高位爆 deffindp(p,q): iflen(p) == 512: pp = int(p,2) if N % pp == 0: print("p = ",pp) print("q = ",N // pp) else: l = len(p) pp = int(p,2) qq = int(q,2) if (pp ^ (qq >> 16)) % (2 ** l) == gift % (2 ** l) and pp * qq % (2 ** l) == N % (2 ** l): findp('1' + p,'1' + q) findp('1' + p,'0' + q) findp('0' + p,'1' + q) findp('0' + p,'0' + q) for i in trange(2**16,2**17): findp('1',bin(i)[2:]) """ p = 8006847171912577069085166877758626954304824756138758266557706391662987806065132448544117840031499707938227955094109779732609035310252723066470330862622641 q = 9366986529377069783394625848920106951220134111548343265311677163992169555436421569730703291128771472885865288798344038000984911921843088200997725324682297 """
3.不会取名字
题目来源:2024HDCTF——ezrsa
task.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
from Crypto.Util.number import * import random import hashlib from secret import flag
gen2 = lambda alpha=512, K=500, T=getPrime(506): next(((p, q, T) for q, r in [(getPrime(alpha), getPrime(alpha))] for k inrange(2, K+1) if (isPrime(p := r + (k * q - r) % T))), None)
from Crypto.Util.number import isPrime,bytes_to_long import random import os
defgetWYSIprime(): whileTrue: digits = [random.choice("727") for _ inrange(272)] prime = int("".join(digits)) if isPrime(prime): return prime # RSA encryption using the WYSI primes p = getWYSIprime() q = getWYSIprime() n = p * q e = 65537 flag = bytes_to_long(os.getenv("FLAG",b"osu{fake_flag_for_testing}")) ciphertext = pow(flag,e,n) print(f"n = {n}") print(f"e = {e}") print(f"ciphertext = {ciphertext}") """ n = 2160489795493918825870689458820648828073650907916827108594219132976202835249425984494778310568338106260399032800745421512005980632641226298431130513637640125399673697368934008374907832728004469350033174207285393191694692228748281256956917290437627249889472471749973975591415828107248775449619403563269856991145789325659736854030396401772371148983463743700921913930643887223704115714270634525795771407138067936125866995910432010323584269926871467482064993332990516534083898654487467161183876470821163254662352951613205371404232685831299594035879 e = 65537 ciphertext = 2087465275374927411696643073934443161977332564784688452208874207586196343901447373283939960111955963073429256266959192725814591103495590654238320816453299972810032321690243148092328690893438620034168359613530005646388116690482999620292746246472545500537029353066218068261278475470490922381998208396008297649151265515949490058859271855915806534872788601506545082508028917211992107642670108678400276555889198472686479168292281830557272701569298806067439923555717602352224216701010790924698838402522493324695403237985441044135894549709670322380450 """
from Crypto.Util.number import * import itertools import gmpy2
n = 2160489795493918825870689458820648828073650907916827108594219132976202835249425984494778310568338106260399032800745421512005980632641226298431130513637640125399673697368934008374907832728004469350033174207285393191694692228748281256956917290437627249889472471749973975591415828107248775449619403563269856991145789325659736854030396401772371148983463743700921913930643887223704115714270634525795771407138067936125866995910432010323584269926871467482064993332990516534083898654487467161183876470821163254662352951613205371404232685831299594035879 e = 65537 ciphertext = 2087465275374927411696643073934443161977332564784688452208874207586196343901447373283939960111955963073429256266959192725814591103495590654238320816453299972810032321690243148092328690893438620034168359613530005646388116690482999620292746246472545500537029353066218068261278475470490922381998208396008297649151265515949490058859271855915806534872788601506545082508028917211992107642670108678400276555889198472686479168292281830557272701569298806067439923555717602352224216701010790924698838402522493324695403237985441044135894549709670322380450
deffindp(p,q): l = len(p) if l == 272and n % int(p) == 0: q = n // int(p) print(f"p = {p}") print(f"q = {q}") else: table = ["2","7"] for i,j in itertools.product(table,repeat=2): pp = int(i + p) qq = int(j + q) if pp * qq % 10**l == n % 10**l: findp(i+p,j+q) # findp("7","7") p = 27777727727777722777277277777272772727772722777777277777277772227772772772227272727777772772772727227772777277727777777222777777277727772272272777772722727722777727277727727777777772772777772777277772222727227777777222727777772772272727777222777777277777727272772272272277 q = 77777772777772222722727222227777272777772777772277727772722777777777227277727272772727277277272772727227272772772222277777772727727772722772777272727777272722772777277777277777277777727777277277777277777272772772777777727772727277727777772772777772272772272222227777777227 d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(ciphertext,d,n) print(long_to_bytes(m)) # osu{h4v3_y0u_3v3r_n0t1c3d_th4t_727_1s_pr1m3?}
c = 77362292774939745985127248740136531356798680244461718641182309736632869439528624490319564705732587035892746550259989967311639940839352531540590481816143399815777578738222244349541298856970218973629828183402846736572747940317185733010901816452760815595925525717774150109667814870300394441913855689875810419726 hint = 3952699881526141586582096584337236735424573202916336803978009509888494841237961467284222140708 n = 101811981048263163700430054305833461232304464649339483324456752139265661172425623344370861924802283149319747333342558424458871624320190755682987168048547266046556603061770039238687342160962557147928318419071351955573359146111983095312306624896541836196196950684743489047140141567937687816622755267268993977151 e = 65537
deffermat(n): a = isqrt(n) b2 = a * a - n b = isqrt(n) count = 0 while b * b != b2: a = a + 1 b2 = a * a - n b = isqrt(b2) count += 1 p = a + b q = a - b assert n == p * q return p, q
withopen("flag.txt","rb") as fs: flag = fs.read().strip() assertlen(flag) == 72
m = int.from_bytes(flag,"big")
from Crypto.Util.number import getPrime, isPrime
defnext_prime(p): whileTrue: p += 2 if isPrime(p): return p
p = getPrime(2048) q = next_prime(p) n = p * q e = 65537 c = pow(m,e,n) print("n =",n) print("c =",c)
# n = 329960318345010350458589325571454799968957932130539403944044204698872359769449414256378111233592533561892402020955736786563103586897940757198920737583107357264433730515123570697570757034221232010688796344257587359198400915567115397034901247038275403825404094129637119512164953012131445747740645183682571690806238508035172474685818036517880994658466362305677430221344381425792427288500814551334928982040579744048907401043058567486871621293983772331951723963911377839286050368715384227640638031857101612517441295926821712605955984000617738833973829140899288164786111118033301974794123637285172303688427806450817155786233788027512244397952849209700013205803489334055814513866650854230478124920442832221946442593769555237909177172933634236392800414176981780444770542047378630756636857018730168151824307814244094763132088236333995807013617801783919113541391133267230410179444855465611792191833319172887852945902960736744468250550722314565805440432977225703650102517531531476188269635151281661081058374242768608270563131619806585194608795817118466680430500830137335634289617464844004904410907221482919453859885955054140320857757297655475489972268282336250384384926216818756762307686391740965586168590784252524275489515352125321398406426217 # c = 307746143297103281117512771170735061509547958991947416701685589829711285274762039205145422734327595082350457374530975854337055433998982493020603245187129916580627539476324521854057990929173492940833073106540441902619425074887573232779899379436737429823569006431370954961865581168635086246592539153824456681688944066925973182272443586463636373955966146029489121226571408532284480270826510961605206483011204059402338926815599691009406841471142048842308786000059979977645988396524814553253493672729395573658564825709547262230219183672493306100392069182994445509803952976016630731417479238769736432223194249245020320183199001774879893442186017555682902409661647546547835345461056900610391514595370600575845979413984555709077635397717741521573798309855584473259503981955303774208127361309229536010653615696850725905168242705387575720694946072789441481191449772933265705810128547553027708513478130258801233619669699177901566688737559102165508239876805822898509541232565766265491283807922473440397456701500524925191214292669986798631732639221198138026031561329502985577205314190565609214349344303324429408234237832110076900414483795318189628198913032900272406887003325858236057373096880675754802725017537119549989304878960436575670784578550
from math import isqrt from Crypto.Util.number import *
deffermat(n): a = isqrt(n) b2 = a * a - n b = isqrt(n) count = 0 while b * b != b2: a = a + 1 b2 = a * a - n b = isqrt(b2) count += 1 p = a + b q = a - b assert n == p * q return p, q
n = c = p,q = fermat(n) d = inverse(65537,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m))
defPollards_p_1(N): a = 2# 为了快速计算以及满足费马小定理条件 n = 2# 从1开始没必要 whileTrue: a = pow(a, n, N) # 递推计算a^B! res = gmpy2.gcd(a - 1, N) # 尝试计算p if res != 1and res != N: # 满足条件后返回 return res n += 1
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) 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
defPollards_p_1(N): a = 2# 为了快速计算以及满足费马小定理条件 n = 2# 从1开始没必要 whileTrue: a = pow(a, n, N) # 递推计算a^B! res = gmpy2.gcd(a - 1, N) # 尝试计算p if res != 1and res != N: # 满足条件后返回 return res n += 1 n = c = p = Pollards_p_1(n) q = n // p d = inverse(65537,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m)) # NCTF{Th3r3_ar3_1ns3cure_RSA_m0duli_7hat_at_f1rst_gl4nce_appe4r_t0_be_s3cur3}
3.p+1光滑
脚本来源:
1 2 3 4 5 6 7 8 9 10 11
deflucas(c, d, N): x = c # a1 y = (c**2 - 2) % N # a2 for bit inbin(d)[3:]: # 快速乘(从高到低位)--我个人理解 if bit == '1': x = (x*y - c) % N # 下标对应a_{x+y},其次保证a_{2k-1}=a_{k}a_{k-1}-a_{0}成立 y = (y**2 - 2) % N # 使得y翻倍--正常的快速幂流程 else: y = (x*y - c) % N # 保证a_{2k-1}=a_{k}a_{k-1}-a_{0}成立 x = (x**2 - 2) % N # a_{k} 翻倍 return x #返回a_{ed}
from math import gcd from math import isqrt from random import randrange from gmpy2 import is_prime
deffactorize(N, phi): """ Recovers the prime factors from a modulus if Euler's totient is known. This method only works for a modulus consisting of 2 primes! :param N: the modulus :param phi: Euler's totient, the order of the multiplicative group modulo N :return: a tuple containing the prime factors, or None if the factors were not found """ s = N + 1 - phi d = s ** 2 - 4 * N p = int(s - isqrt(d)) // 2 q = int(s + isqrt(d)) // 2 return p, q
deffactorize_multi_prime(N, phi): """ Recovers the prime factors from a modulus if Euler's totient is known. This method works for a modulus consisting of any number of primes, but is considerably be slower than factorize. More information: Hinek M. J., Low M. K., Teske E., "On Some Attacks on Multi-prime RSA" (Section 3) :param N: the modulus :param phi: Euler's totient, the order of the multiplicative group modulo N :return: a tuple containing the prime factors """ prime_factors = set() factors = [N] whilelen(factors) > 0: # Element to factorize. N = factors[0]
w = randrange(2, N - 1) i = 1 while phi % (2 ** i) == 0: sqrt_1 = pow(w, phi // (2 ** i), N) if sqrt_1 > 1and sqrt_1 != N - 1: # We can remove the element to factorize now, because we have a factorization. factors = factors[1:]
p = gcd(N, sqrt_1 + 1) q = N // p
if is_prime(p): prime_factors.add(p) elif p > 1: factors.append(p)
if is_prime(q): prime_factors.add(q) elif q > 1: factors.append(q)
defdivide_pq(e, d, n): k = e*d - 1 whileTrue: g = random.randint(2, n-1) t = k whileTrue: if t % 2 != 0: break t //= 2 x = pow(g, t, n) if x > 1and gmpy2.gcd(x-1, n) > 1: p = gmpy2.gcd(x-1, n) return (p, n//p)
n_low = n % 2^624 var('p') f = p * (hint - p) - n_low res = solve_mod(f,2^624) for i in res: plow = int(i[0]) R.<x> = PolynomialRing(Zmod(n)) f2 = x * 2^624 + plow f2 = f2.monic() root = f2.small_roots(X = 2^400,beta=0.4) if root != []: p = int(root[0])*2^624 + plow q = n // p d = inverse(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m))
f = x * ((hint << 400) - x) - n res = f.roots() for root in res: phigh = int(root[0]) >> 405 << 405 PR.<x> = PolynomialRing(Zmod(n)) f1 = phigh + x res1 = f1.small_roots(X = 2^405,beta=0.4) if res1 != []: p = phigh + int(res1[0]) q = n // p d = inverse(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m))
RSAPrivateKey ::= SEQUENCE { version Version, modulus INTEGER, -- n publicExponent INTEGER, -- e privateExponent INTEGER, -- d prime1 INTEGER, -- p prime2 INTEGER, -- q exponent1 INTEGER, -- d mod (p-1) exponent2 INTEGER, -- d mod (q-1) coefficient INTEGER -- (inverse of q) mod p }
#sage from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP from gmpy2 import * from tqdm import *
n = 0xd7152506aa9cec05e5335d6b46f5491407c3199fd51091f1f6030d3762b9e03f49c9dcdc075054e0cc148b974b41854bd93b4ee16a2a876ee62005e80ef806b7aa3b64b1bf9b1fa773e353d0cdb9ff9783ddd5f5e67499ad10f361e938d00b82a6a4c42a0535c5e76721798e86b45cd4b8d03b0d7e75c2be8766a1e843bdc641 e = 0x10001 inv = 0xe3016cb3609c1d643c167439c3b938b881f4237f24860d3b1cb85a626d5ccd4726964e0f8270d6c4df9ebfebcc538e4ee5e1a7b7368ede51ec6ae917f78eb598 d_low = 0xc90bcecf1cbab3358585e8a041d1b1 q_low = [] c = open("flag.enc",'rb').read()
for i in trange(1,e): try: q0 = invert(i, 2 ** 120) * (e * d_low + i - 1) % 2 ^ 120 q_low.append(q0) except: continue
PR.<x> = PolynomialRing(Zmod(n))
for i in trange(len(q_low)-1,-1,-1): f = inv * (2^120*x + int(q_low[i]))^2 - (2^120*x + int(q_low[i])) f = f.monic() root = f.small_roots(X = 2^(512-120)) if root: q = 2^120 * int(root[0]) + int(q_low[i]) p = n // q if p * q == n: d = gmpy2.invert(e, (p - 1) * (q - 1)) print("p = ",p) print("q = ",q) print("d = ",d) key = RSA.construct((int(n),int(e),int(d),int(p),int(q))) newkey = PKCS1_OAEP.new(key) flag = newkey.decrypt(c) print(flag) break
2024CISCN——ezrsa
task.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
from Crypto.Util.number import * from Crypto.PublicKey import RSA import random from secret import flag
m = bytes_to_long(flag) key = RSA.generate(1024) passphrase = str(random.randint(0,999999)).zfill(6).encode() output = key.export_key(passphrase=passphrase).split(b'\n') for i inrange(7, 15): output[i] = b'*' * 64 withopen("priv.pem", 'wb') as f: for line in output: f.write(line + b'\n') withopen("enc.txt", 'w') as f: f.write(str(key._encrypt(m)))
from tqdm import * from Crypto.Util.number import * from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP
n = 0xa18f011bebacceda1c6812730b9e62720d3cbd6857af2cf8431860f5dc83c5520f242f3be7c9e96d7f96b41898ff000fdb7e43ef6f1e717b2b7900f35660a21d1b16b51849be97a0b0f7cbcf5cfe0f00370cce6193fefa1fed97b37bd367a673565162ce17b0225708c032961d175bbc2c829bf2e16eabc7e0881feca0975c81 e = 65537 dq_leak= 0x8f2363b340e5 inv = 0x5f152c429871a7acdd28be1b643b4652800b88a3d23cc57477d75dd5555b635167616ef5c609d69ce3c2aedcb03b62f929bbcd891cadc0ba031ae6fec8a2116d c = 55149764057291700808946379593274733093556529902852874590948688362865310469901900909075397929997623185589518643636792828743516623112272635512151466304164301360740002369759704802706396320622342771513106879732891498365431042081036698760861996177532930798842690295051476263556258192509634233232717503575429327989
defcoppersmith(k): R.<x> = PolynomialRing(Zmod(n)) tmp = e * (x * 2^48 + dq_leak) + k - 1# kq f = inv * tmp^2 - k*tmp f = f.monic() x0 = f.small_roots(X=2^464,beta=1,epsilon=0.09) return x0
for k in trange(1,e): x0 = coppersmith(k) if x0 != []: dq = int(x0[0]) * 2^48 + dq_leak q = (e*dq + k - 1) // k # print(f"k = {k}") # k = 47794 p = n // q d = inverse(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(int(m))) # b'flag{df4a4054-23eb-4ba4-be5e-15b247d7b819}' break