湖湘杯 2021 Crypto
hxb 2021 crypto signin $n1/n2$ 的连分数展开是对 $q1/q2$ 的一个逼近,所以枚举连分数中的每一项,就可以得到 $q1, q2$ 了,分解之后正常进行 RSA 解密得到 flag。 from Crypto.Util.number import GCD, inverse, long_to_bytes, isPrime pk = (1150398070565459492080597718626032792435556703413923483458704675295997646493249759818468321328556510074044954676615760446708253531839417036997811506222349194302791943489195718713797322878586379546657275419261647635859989280700191441312691274285176619391539387875252135478424580680264554294179123254566796890998243909286508189826458854346825493157697201495100628216832191035903848391447704849808577310612723700318670466035077202673373956324725108350230357879374234418393233, 1242678737076048096780023147702514112272319497423818488193557934695583793070332178723043194823444815153743889740338870676093799728875725651036060313223096288606947708155579060628807516053981975820338028456770109640111153719903207363617099371353910243497871090334898522942934052035102902892149792570965804205461900841595290667647854346905445201396273291648968142608158533514391348407631818144116768794595226974831093526512117505486679153727123796834305088741279455621586989) c1, c2 = (361624030197288323178211941746074961985876772079713896964822566468795093475887773853629454653096485450671233584616088768705417987527877166166213574572987732852155320225332020636386698169212072312758052524652761304795529199864805108000796457423822443871436659548626629448170698048984709740274043050729249408577243328282313593461300703078854044587993248807613713896590402657788194264718603549894361488507629356532718775278399264279359256975688280723740017979438505001819438, 33322989148902718763644384246610630825314206644879155585369541624158380990667828419255828083639294898100922608833810585530801931417726134558845725168047585271855248605561256531342703212030641555260907310067120102069499927711242804407691706542428236208695153618955781372741765233319988193384708525251620506966304554054884590718068210659709406626033891748214407992041364462525367373648910810036622684929049996166651416565651803952838857960054689875755131784246099270581394) n1, n2 = pk e = 0x10001 def getRoot(x, n): high = 1 while high ** n <= x: high *= 2 low = high // 2 while low < high: mid = (low + high) // 2 if low < mid and mid**n < x: low = mid elif high > mid and mid**n > x: high = mid else: return mid return mid + 1 # https://github.com/pablocelayes/rsa-wiener-attack def rational_to_contfrac(x, y): a = x // y pquotients = [a] while a * y != x: x, y = y, x - a*y a = x // y pquotients.append(a) return pquotients def convergents_from_contfrac(frac): convs = [] for i in range(len(frac)): convs.append(contfrac_to_rational(frac[0:i])) return convs def contfrac_to_rational(frac): if len(frac) == 0: return (0, 1) num = frac[-1] denom = 1 for _ in range(-2, -len(frac) - 1, -1): num, denom = frac[_] * num + denom, num return (num, denom) frac = rational_to_contfrac(n1, n2) convergents = convergents_from_contfrac(frac) p1, p2 = None, None for (P1, P2) in convergents: gcd1, gcd2 = GCD(P1, n1), GCD(P2, n2) p1 = gcd1 if (gcd1.bit_length() <= 128 and isPrime(gcd1)) else p1 p2 = gcd2 if (gcd2.bit_length() <= 128 and isPrime(gcd2)) else p2 print(f"[+]p1: {p1}") print(f"[+]p2: {p2}") q1, q2 = getRoot(n1 // p1, 4), getRoot(n2 // p2, 4) phi1 = (p1 - 1) * (q1 - 1) * q1**3 phi2 = (p2 - 1) * (q2 - 1) * q2**3 m1 = pow(c1, inverse(e, phi1), n1) m2 = pow(c2, inverse(e, phi2), n2) flag = (long_to_bytes(m1) + long_to_bytes(m2)).decode() print(f"[~]flag: {flag}") ''' [+]p1: 181856133933383097933223133658050179553 [+]p2: 196443958511498599913330690975430421229 [~]flag: flag{8ef333ac-21a7-11ec-80f1-00155d83f114} ''' fastOT Python 的random的内部是MT19937 伪随机数生成器,虽然生成的随机数周期很大,但是内部状态(state)很少,仅仅有 624 个,每个值都是 32bit 的。 ...