# I found this super cool function on stack overflow \o/ https://stackoverflow.com/questions/2267362/how-to-convert-an-integer-to-a-string-in-any-base defnumberToBase(n, b): if n == 0: return [0] digits = [] while n: digits.append(int(n % b)) n //= b return digits[::-1]
assertlen(flag) <= 45
flag = int.from_bytes(flag, 'big')
base = int(input("Give me a base! "))
if base < 2: print("Base is too small") quit() if base > 256: print("Base is too big") quit()
print(f'Here you go! {sum(numberToBase(flag, base))}')
defexgcd(a, b): if b == 0: return1, 0, a x, y, q = exgcd(b, a % b) x, y = y, (x - a // b * y) return x, y, q
defexCRT(a, m): for i inrange(len(a)): x, y, d = exgcd(m[0], m[i]) if (a[i] - a[0]) % d != 0: return -1 t = m[i] // d x = (a[i] - a[0]) // d * x % t a[0] = x * m[0] + a[0] m[0] = m[0] * m[i] // d a[0] = (a[0] % m[0] + m[0]) % m[0] return a[0]
# sage from pwn import * from Crypto.Util.number import *
context(os='linux', arch='amd64', log_level='warning') m = [] b = [] for i inrange(2, 253): p = remote('basic-sums.chal-kalmarc.tf', 2256) p.sendlineafter(b'Give me a base! ', str(i).encode()) p.recvuntil(b'go! ') m.append(int(p.recvline())) b.append(i-1) p.close()
flag = crt(m, b) print(long_to_bytes(flag).decode()) # kalmar{At_least_it_wasnt_lattices_right???!?}
# FROM python:3 import random withopen("flag.txt","rb") as f: flag=f.read() for i inrange(2**64): print(random.getrandbits(32)+flag[random.getrandbits(32)%len(flag)]) input()
defgetPrimes(bits, k): p = getPrime(bits) a = random.randint(0, p-1) b = random.randint(0, p-1) l = LCG(p, a, b) return [gmpy2.next_prime(l.next()) for _ inrange(k)]
p, q = getPrimes(1024, 2) n = p*q e = 65537 m = bytes_to_long(flag) c = pow(m, e, n) print(n, c) ''' p = 170302223332374952785269454020752010235000449292324018706323228421794605831609342383813680059406887437726391567716617403068082252456126724116360291722050578106527815908837796377811535800753042840119867579793401648981916062128752925574017615120362457848369672169913701701169754804744410516724429370808383640129 a = 95647398016998994323232737206171888899957187357027939982909965407086383339418183844601496450055752805846840966207033179756334909869395071918100649183599056695688702272113280126999439574017728476367307673524762493771576155949866442317616306832252931038932232342396406623324967479959770751756551238647385191314 b = 122891504335833588148026640678812283515533067572514249355105863367413556242876686249628488512479399795117688641973272470884323873621143234628351006002398994272892177228185516130875243250912554684234982558913267007466946601210297176541861279902930860851219732696973412096603548467720104727887907369470758901838 n = 5593134172275186875590245131682192688778392004699750710462210806902340747682378400226605648011816039948262008066066650657006955703136928662067931212033472838067050429624395919771757949640517085036958623280188133965150285410609475158882527926240531113060812228408346482328419754802280082212250908375099979058307437751229421708615341486221424596128137575042934928922615832987202762651904056934292682021963290271144473446994958975487980146329697970484311863524622696562094720833240915154181032649358743041246023013296745195478603299127094103448698060367648192905729866897074234681844252549934531893172709301411995941527 c = 2185680728108057860427602387168654320024588536620246138642042133525937248576850574716324994222027251548743663286125769988360677327713281974075574656905916643746842819251899233266706138267250441832133068661277187507427787343897863339824140927640373352305007520681800240743854093190786046280731148485148774188448658663250731076739737801267702682463265663725900621375689684459894544169879873344003810307496162858318574830487480360419897453892053456993436452783099460908947258094434884954726862549670168954554640433833484822078996925040310316609425805351183165668893199137911145057639657709936762866208635582348932189646 '''
from secrets import flag, get_random_emojiiiiii from Crypto.Util.number import *
defgenarate_emojiiiiii_prime(nbits, base=0): whileTrue: p = getPrime(base // 32 * 32) if base >= 3else0 for i inrange(nbits // 8 // 4 - base // 32): p = (p << 32) + get_random_emojiiiiii() # 猜一猜 if isPrime(p): return p
m = bytes_to_long(flag.encode( ) + "".join([long_to_bytes(get_random_emojiiiiii()).decode() for _ inrange(5)]).encode()) p = genarate_emojiiiiii_prime(512, 224) q = genarate_emojiiiiii_prime(512)
n = p * q e = "💯" c = pow(m, bytes_to_long(e.encode()), n)
print("p0 =", long_to_bytes(p % 2 ** 256).decode()) print("n =", n) print("c =", c) # p0 = 😘😾😂😋😶😾😳😷 # n = 156583691355552921614631145152732482393176197132995684056861057354110068341462353935267384379058316405283253737394317838367413343764593681931500132616527754658531492837010737718142600521325345568856010357221012237243808583944390972551218281979735678709596942275013178851539514928075449007568871314257800372579 # c = 47047259652272336203165844654641527951135794808396961300275905227499051240355966018762052339199047708940870407974724853429554168419302817757183570945811400049095628907115694231183403596602759249583523605700220530849961163557032168735648835975899744556626132330921576826526953069435718888223260480397802737401
# sage from Crypto.Util.number import * from tqdm import trange
e = bytes_to_long("💯".encode()) p0 = bytes_to_long("😘😾😂😋😶😾😳😷".encode()) n = 156583691355552921614631145152732482393176197132995684056861057354110068341462353935267384379058316405283253737394317838367413343764593681931500132616527754658531492837010737718142600521325345568856010357221012237243808583944390972551218281979735678709596942275013178851539514928075449007568871314257800372579 PR.<x> = PolynomialRing(Zmod(n)) for i in trange(0xf09f9880,0xf09f998f): p00 = i*2^256 + p0 f = x*2^288+p00 f = f.monic() roots = f.small_roots(X = 2**224,beta=0.4,epsilon=0.02) if roots: p = int(roots[0])*2^288 + p00 q = n // p print(f"{p = }") print(f"{q = }") break
然后就是e与ϕ不互素,上板子即可
# sage from sage.allimport * from sage.parallel.multiprocessing_sage import parallel_iter # TODO import itertools from tqdm import tqdm from Crypto.Util.number import * import string
defnth_p(y, n, p, k=1): assert is_pseudoprime(p) print('[LOG] Solving pi = %s^%d' % (hex(p), k)) try: xs = Zmod(p**k)(y).nth_root(n, all=True) except: xs = GF(p**k)(y).nth_root(n, all=True) xs = list(set(xs)) xs = [Integer(x) for x in xs] return xs
defnthRSA_p(c, e, p, k=1): assert is_pseudoprime(p) P = Integer(pow(p, k)) phi = euler_phi(P)
rs = [] ei = e whileTrue: r = gcd(phi, ei) if r == 1: break rs += [r] ei //= r r = product(rs) dr = (e // r).inverse_mod(phi) cr = pow(c, dr, P) return nth_p(cr, r, p, k)
defnthRSA_n(c, e, ps, ks=None, checker=None, ret1=False): # ps: p, q, ... assertisinstance(ps, list) if ks == None: ks = [1] * len(ps) else: assertlen(ps) == len(ks) ms = [] for i inrange(len(ps)): mp = nthRSA_p(c, e, ps[i], ks[i]) ms += [mp] total = product([len(x) for x in ms]) print('[Log] Doing crt.\nComplexity = %d: %s' % (total, str([len(x) for x in ms])))
res = [] Ps = [ps[i]**ks[i] for i inrange(len(ps))] for msi in tqdm(itertools.product(*ms), total=total): m = crt(list(msi), Ps) if checker == None: res += [m] continue if checker(m): ifnot ret1: res += [m] continue return m return res
defgenHeaderChecker(hd): ifisinstance(hd, str): hd = hd.encode() assertisinstance(hd, bytes) defcheckHeader(m): try: flag = long_to_bytes(int(m)) if hd in flag: print(flag) returnTrue returnFalse except: returnFalse return checkHeader
defgenStrChecker(dict, n=65537): defcheckStr(m): try: flag = long_to_bytes(int(m)).decode() for fi in flag[:n]: ifnot fi indict: returnFalse print(flag) returnTrue except: returnFalse return checkStr
p = 12424840247075830662687097292458444573014198016321428995092662043898159667123240573630892907827505266982898641483333170032514244713840745287869771915696311 q = 12602471198163266643743702664647336358595911975665358584258749238146841559843060594842063473155049870396568542257767865369797827796765830093256146584311989 e = bytes_to_long("💯".encode()) n = 156583691355552921614631145152732482393176197132995684056861057354110068341462353935267384379058316405283253737394317838367413343764593681931500132616527754658531492837010737718142600521325345568856010357221012237243808583944390972551218281979735678709596942275013178851539514928075449007568871314257800372579 c = 47047259652272336203165844654641527951135794808396961300275905227499051240355966018762052339199047708940870407974724853429554168419302817757183570945811400049095628907115694231183403596602759249583523605700220530849961163557032168735648835975899744556626132330921576826526953069435718888223260480397802737401
ps = [p, q] checker = genHeaderChecker('TGCTF') res = nthRSA_n(c, e, ps, checker=checker) for r in res: flag = long_to_bytes(int(r)) print(flag.decode()) # TGCTF{🙇🏮🤟_🫡🫡🫡_🚩🚩🚩}😃😖😘😨😢
LitCTF2025 - leak(dp高位泄露广义解法)
from Crypto.Util.number import * from enc import flag
m = bytes_to_long(flag) p,q,e = getPrime(1024),getPrime(1024),getPrime(101) n = p*q temp = gmpy2.invert(e,p-1) c = pow(m,e,n) hint = temp>>180 print(f"e = {e}") print(f"n = {n}") print(f"c = {c}") print(f"hint = {hint}") ''' e = 1915595112993511209389477484497 n = 12058282950596489853905564906853910576358068658769384729579819801721022283769030646360180235232443948894906791062870193314816321865741998147649422414431603039299616924238070704766273248012723702232534461910351418959616424998310622248291946154911467931964165973880496792299684212854214808779137819098357856373383337861864983040851365040402759759347175336660743115085194245075677724908400670513472707204162448675189436121439485901172477676082718531655089758822272217352755724670977397896215535981617949681898003148122723643223872440304852939317937912373577272644460885574430666002498233608150431820264832747326321450951 c = 5408361909232088411927098437148101161537011991636129516591281515719880372902772811801912955227544956928232819204513431590526561344301881618680646725398384396780493500649993257687034790300731922993696656726802653808160527651979428360536351980573727547243033796256983447267916371027899350378727589926205722216229710593828255704443872984334145124355391164297338618851078271620401852146006797653957299047860900048265940437555113706268887718422744645438627302494160620008862694047022773311552492738928266138774813855752781598514642890074854185464896060598268009621985230517465300289580941739719020511078726263797913582399 hint = 10818795142327948869191775315599184514916408553660572070587057895748317442312635789407391509205135808872509326739583930473478654752295542349813847128992385262182771143444612586369461112374487380427668276692719788567075889405245844775441364204657098142930 '''
# sage from sage.allimport * from Crypto.Util.number import * import itertools
defsmall_roots(f, bounds, m=1, d=None): ifnot d: d = f.degree()
R = f.base_ring() N = R.cardinality()
f /= f.coefficients().pop(0) f = f.change_ring(ZZ)
G = Sequence([], f.parent()) for i inrange(m + 1): base = N ^ (m - i) * f ^ i for shifts in itertools.product(range(d), repeat=f.nvariables()): g = base * prod(map(power, f.variables(), shifts)) G.append(g)
factors = [monomial(*bounds) for monomial in monomials] for i, factor inenumerate(factors): B.rescale_col(i, factor)
B = B.dense_matrix().LLL()
B = B.change_ring(QQ) for i, factor inenumerate(factors): B.rescale_col(i, 1 / factor)
H = Sequence([], f.parent().change_ring(QQ)) for h infilter(None, B * monomials): H.append(h) I = H.ideal() if I.dimension() == -1: H.pop() elif I.dimension() == 0: roots = [] for root in I.variety(ring=ZZ): root = tuple(R(root[var]) for var in f.variables()) roots.append(root) return roots
return []
e = 1915595112993511209389477484497 n = 12058282950596489853905564906853910576358068658769384729579819801721022283769030646360180235232443948894906791062870193314816321865741998147649422414431603039299616924238070704766273248012723702232534461910351418959616424998310622248291946154911467931964165973880496792299684212854214808779137819098357856373383337861864983040851365040402759759347175336660743115085194245075677724908400670513472707204162448675189436121439485901172477676082718531655089758822272217352755724670977397896215535981617949681898003148122723643223872440304852939317937912373577272644460885574430666002498233608150431820264832747326321450951 c = 5408361909232088411927098437148101161537011991636129516591281515719880372902772811801912955227544956928232819204513431590526561344301881618680646725398384396780493500649993257687034790300731922993696656726802653808160527651979428360536351980573727547243033796256983447267916371027899350378727589926205722216229710593828255704443872984334145124355391164297338618851078271620401852146006797653957299047860900048265940437555113706268887718422744645438627302494160620008862694047022773311552492738928266138774813855752781598514642890074854185464896060598268009621985230517465300289580941739719020511078726263797913582399 hint = 10818795142327948869191775315599184514916408553660572070587057895748317442312635789407391509205135808872509326739583930473478654752295542349813847128992385262182771143444612586369461112374487380427668276692719788567075889405245844775441364204657098142930 leak = hint << 180 PR.<x,y>=PolynomialRing(Zmod(n)) f = e*(leak + x) + y -1 res = small_roots(f, (2^180,2^e.bit_length()),m=1,d=3) for root in res: dp = leak + root[0] p = GCD(pow(2, e*dp, n) -2, n) q = n // p d = inverse(e, (p-1)*(q-1)) m = pow(c, d, n) print(long_to_bytes(m).decode())
NepCTF2025 - ezRSA2
Easy RSA, easy strategy. No need to brute force.
Perhaps it’s easier than ezRSA in NepCTF 2024.
from Crypto.Util.number import getStrongPrime, getRandomNBitInteger, GCD, inverse, long_to_bytes, bytes_to_long, sieve_base from flag import flag
defgen_parameters(gamma=0.33, beta=0.33): p = getStrongPrime(1024) q = getStrongPrime(1024) N = p*q phi = (p-1)*(q-1) whileTrue: d = getRandomNBitInteger(int(2048*beta)) if GCD(d, phi) == 1: break e = inverse(d, phi) hints = [] M = 1 for i inrange(1, len(sieve_base)): li = sieve_base[i] hints.append(d%li) M *= li if M.bit_length() >= 1024*gamma: break return e, N, hints
# sage from sage.allimport * from Crypto.Util.number import * import itertools
defsmall_roots(f, bounds, m=1, d=None): ifnot d: d = f.degree()
R = f.base_ring() N = R.cardinality()
f /= f.coefficients().pop(0) f = f.change_ring(ZZ)
G = Sequence([], f.parent()) for i inrange(m + 1): base = N ^ (m - i) * f ^ i for shifts in itertools.product(range(d), repeat=f.nvariables()): g = base * prod(map(power, f.variables(), shifts)) G.append(g)
factors = [monomial(*bounds) for monomial in monomials] for i, factor inenumerate(factors): B.rescale_col(i, factor)
B = B.dense_matrix().LLL()
B = B.change_ring(QQ) for i, factor inenumerate(factors): B.rescale_col(i, 1 / factor)
H = Sequence([], f.parent().change_ring(QQ)) for h infilter(None, B * monomials): H.append(h) I = H.ideal() if I.dimension() == -1: H.pop() elif I.dimension() == 0: roots = [] for root in I.variety(ring=ZZ): root = tuple(R(root[var]) for var in f.variables()) roots.append(root) return roots
from Crypto.Util.number import * from sympy import *
e = 0x73915608ed64c9cf1a2279684cab4f4a78fba229d45d4f860971a241481363470a19cb0dc0d00f816b5befdaca017cf71483e96ef17b36179012f5194a0e6bf481bb06c2644f74c6812efb65d05c00631f282d6aa55c0bc140a1830b95a1cf4b6024cb0db53f2c2189897c41f22e2eec773723f531ec4bfa537fae6de5fe480cf46fe17850f7eb47df08194d95db3d26ac923b26e110ee645239ab586bbc546ddc5906f280a106edbb727ccb05536b5a3f5c0ebcf865c95ce58be54f7f3547aa53baa218b0dfa98e42d925fa341e45f94a3b16b0c83802660c7f34de3336cb21f219073cf8e9f5e39d47f0a9a9ee7c255f09a6add9a2f7a47960f4a853183d29 N = 0xba8956e81394f3f1265ca5d9c4ad1ab0078bb43c4b80a231ab2cc62246ae45f66a562252622aed2cbbfc08647ef2fec0f97a632bf2242845f4b3af0c427cec3d90f42e90278a5a0feeed0922a8cd2278074ac54e9cfc0e96ff68f8d8f266dd87dc1cc59c2895ec884de2022311767f6a9a7e0bd288c79620e28b83bb3c8d8ad1047c839d6ccf5544eaf434a5f00b951769ab3121298d04b63a162757beb3d49917cd0c9e02ee1ac29398c8130961d5a2f2833aba1e538edb7bb97071f40fae543d1622f0c9206c6d4d8abb2ac1b93ebfb603c2f3a909ede357ade4043550fe540d13a4e87db8d731fe130f15a43a1a00364f5da2d87f7b660c3a04e734218a11 ct = 0x101b284ad196b5bbd3d3df00a7d3577caeb29c681bdd122582b705afc671febf45d4f3786640e55aadd6a31ecc49175f97b772720f1735f8555f768b137a4643cd6958f80a3dfca4d0270ad463d6dde93429940bd2abb5ad8408b0906fa8d776544a1c50cc0d95939bef4c3fb64d0b52dca81ff0f244fc265bfc0bc147435d05f8f1a146e963a1403b3c123b4d6e73d1fd897109995009be1673212607f0ea7ae33d23f3158448b05c28ea6636382eee9436c4a6c09023ead7182ecd55ac73a68d458d726e1abc208810468591e63f4b4c2c1f3ce27c4800b52f7421ccab432c03e88b3b255740d719e40e0226eabb7633d97ed210e32071e2ac36ed17ef442e
mat = [[2^1700, 0, e*d_low-1], [0, 2^1370, e*M], [0, 0, N + 1]] L = Matrix(ZZ, mat) for res in L.LLL(): k, K1, _ = res if k == 2^1700: d = (K1//2^1370)*M + d_low flag = long_to_bytes(pow(ct,d,N)).decode() print('NepCTF{' + flag + '}')
from secret import a0,alpha import gmpy2 from Crypto.Util.number import long_to_bytes import random from math import sqrt,log2
d=981020902672546902438782010902608140583199504862558032616415 p = d - a0
k=sqrt(log2(p))+log2(log2(p)) B = 2**30 assert B < p/2**k
m = 30 assert m > 2*sqrt(log2(p))
samples = [] betas = []
f = open("samples.txt",'w') for _ inrange(m): t = random.randint(1, p-1) beta = random.randint(-B + 1, B - 1) a = (t * alpha - beta) % p samples.append((t, a)) betas.append(beta)
f.write(str(samples))
for i inrange(0,30): assert (betas[i]-samples[i][0]*alpha+samples[i][1])%p == 0
from hashlib import sha256 from Crypto.Cipher import AES
x = int(input('Enter an 8-digit multiplicand: ')) y = int(input('Enter a 7-digit multiplier: ')) assert1e6 <= y < 1e7 <= x < 1e8, "Incorrect lengths" assert x * y != 3_81_40_42_24_40_28_42, "Insufficient ntr-opy"
defdream_multiply(x, y): x, y = str(x), str(y) assertlen(x) == len(y) + 1 digits = x[0] for a, b inzip(x[1:], y): digits += str(int(a) * int(b)) returnint(digits) assert dream_multiply(x, y) == x * y, "More like a nightmare"
t = 29 self.conn.sendline(str(t)) A, b = [], [] for j inrange(t): x = g ** j self.conn.sendline(str(x)) y = int(self.conn.recvline()) A.append([Zp(x) ** i for i inrange(t)]) b.append(Zp(y)) A = matrix(Zp, A) b = vector(Zp, b) x = A.solve_right(b) returnset(x.list())
defgao(self): a = self.gao_1() self.conn.sendline('0') self.conn.recvline() b = self.gao_1() num = a & b print(num) assertlen(num) == 1, "Multiple secrets found" secret = num.pop() self.conn.sendline(str(secret)) self.conn.interactive()
if __name__ == "__main__": g = Gao() g.gao()
SECCON CTF 14 - yukari
#!/usr/bin/env python3
from Crypto.PublicKey import RSA from Crypto.Util.number import getPrime, isPrime
withopen("flag.txt", "r") as f: FLAG = f.read()
for _ inrange(32): p = getPrime(1024) print("p =", p)
这题有点绷不住,居然是要触发RSA.construct((n, e, d))的异常才能过,然后要坚持32轮
vscode跟进函数
defconstruct(rsa_components, consistency_check=True): r"""Construct an RSA key from a tuple of valid RSA components. The modulus **n** must be the product of two primes. The public exponent **e** must be odd and larger than 1. In case of a private key, the following equations must apply: .. math:: \begin{align} p*q &= n \\ e*d &\equiv 1 ( \text{mod lcm} [(p-1)(q-1)]) \\ p*u &\equiv 1 ( \text{mod } q) \end{align} Args: rsa_components (tuple): A tuple of integers, with at least 2 and no more than 6 items. The items come in the following order: 1. RSA modulus *n*. 2. Public exponent *e*. 3. Private exponent *d*. Only required if the key is private. 4. First factor of *n* (*p*). Optional, but the other factor *q* must also be present. 5. Second factor of *n* (*q*). Optional. 6. CRT coefficient *q*, that is :math:`p^{-1} \text{mod }q`. Optional. consistency_check (boolean): If ``True``, the library will verify that the provided components fulfil the main RSA properties. Raises: ValueError: when the key being imported fails the most basic RSA validity checks. Returns: An RSA key object (:class:`RsaKey`). """
n = input_comps.n e = input_comps.e ifnothasattr(input_comps, 'd'): key = RsaKey(n=n, e=e) else: d = input_comps.d ifhasattr(input_comps, 'q'): p = input_comps.p q = input_comps.q else: # Compute factors p and q from the private exponent d. # We assume that n has no more than two factors. # See 8.2.2(i) in Handbook of Applied Cryptography. ktot = d * e - 1 # The quantity d*e-1 is a multiple of phi(n), even, # and can be represented as t*2^s. t = ktot while t % 2 == 0: t //= 2 # Cycle through all multiplicative inverses in Zn. # The algorithm is non-deterministic, but there is a 50% chance # any candidate a leads to successful factoring. # See "Digitalized Signatures and Public Key Functions as Intractable # as Factorization", M. Rabin, 1979 spotted = False a = Integer(2) whilenot spotted and a < 100: k = Integer(t) # Cycle through all values a^{t*2^i}=a^k while k < ktot: cand = pow(a, k, n) # Check if a^k is a non-trivial root of unity (mod n) if cand != 1and cand != (n - 1) andpow(cand, 2, n) == 1: # We have found a number such that (cand-1)(cand+1)=0 (mod n). # Either of the terms divides n. p = Integer(n).gcd(cand + 1) spotted = True break k *= 2 # This value was not any good... let's try another! a += 2 ifnot spotted: raise ValueError("Unable to compute factors p and q from exponent d.") # Found ! assert ((n % p) == 0) q = n // p
ifhasattr(input_comps, 'u'): u = input_comps.u else: u = p.inverse(q)
# Verify consistency of the key if consistency_check:
# Modulus and public exponent must be coprime if e <= 1or e >= n: raise ValueError("Invalid RSA public exponent") if Integer(n).gcd(e) != 1: raise ValueError("RSA public exponent is not coprime to modulus")
# For RSA, modulus must be odd ifnot n & 1: raise ValueError("RSA modulus is not odd")
if key.has_private(): # Modulus and private exponent must be coprime if d <= 1or d >= n: raise ValueError("Invalid RSA private exponent") if Integer(n).gcd(d) != 1: raise ValueError("RSA private exponent is not coprime to modulus") # Modulus must be product of 2 primes if p * q != n: raise ValueError("RSA factors do not match modulus") if test_probable_prime(p) == COMPOSITE: raise ValueError("RSA factor p is composite") if test_probable_prime(q) == COMPOSITE: raise ValueError("RSA factor q is composite") # See Carmichael theorem phi = (p - 1) * (q - 1) lcm = phi // (p - 1).gcd(q - 1) if (e * d % int(lcm)) != 1: raise ValueError("Invalid RSA condition") ifhasattr(key, 'u'): # CRT coefficient if u <= 1or u >= q: raise ValueError("Invalid RSA component u") if (p * u % q) != 1: raise ValueError("Invalid RSA component u with p")
from Crypto.Util.number import * from sage.allimport * from random import choices from secret import flag assertlen(flag) == 23 m = 23 n = 28 p = getPrime(64) q = getPrime(64) N = p * q S = vector(Zmod(N), list(flag)) e = vector(Zmod(N), choices([p, q], k=n)) B = [] A = random_matrix(Zmod(N), n, m) M = random_matrix(ZZ, n, n) C = random_matrix(Zmod(N), n, m) for _ inrange(3): A = M*A+C b = A*S + e B.append(b) save((A,B,M), "output")
A, B, M = load('./n1junior/LargeErrors/output.sobj') N = A.base_ring().order() factors = list(factor(N)) p = factors[0][0] q = factors[1][0] Fp = GF(p) q_inv = inverse_mod(q, p) A_prime = matrix(Fp, A) * q_inv b_prime = vector(Fp, b) * q_inv b = B[2] m, n, esz = 28, 23, 2**0
defprimal_attack2(A,b,m,n,p,esz): L = block_matrix( [ [matrix(Zmod(p), A).T.echelon_form().change_ring(ZZ), 0], [matrix.zero(m - n, n).augment(matrix.identity(m - n) * p), 0], [matrix(ZZ, b), 1], ] ) #print(L.dimensions()) Q = diagonal_matrix([1]*m + [esz]) L *= Q L = L.LLL() L /= Q res = L[0] if(res[-1] == 1): e = vector(GF(p), res[:m]) elif(res[-1] == -1): e = -vector(GF(p), res[:m]) s = matrix(Zmod(p), A).solve_right((vector(Zmod(p), b)-e)) return s
s = primal_attack2(A_prime, b_prime, m, n, p, esz) flag = '' for i in s: flag += chr(i) print(flag) # flag{1W3_W@$_v3rY_34sy}
LilacCTF2026 - myRSA
Secrets in this RSA are congruential
The polynomial and the beautiful
Make up relations in this world
Hey
Just pick up your Sagemath, Python
And be colourful
Because this RSA is wonderful
import gmpy2 from Crypto.Util.number import isPrime, bytes_to_long from sympy.ntheory import sqrt_mod from sympy.ntheory.modular import crt from secret import p, q, r, pp import os
from sage.allimport * from Crypto.Util.number import *
n = 320463398964822335046388577512598439169912412662663009494347432623554394203670803089065987779128504277420596228400774827331351610218400792101575854579340551173392220602541203502751384517150046009415263351743602382113258267162420601780488075168957353780597674878144369327869964465070900596283281886408183175554478081038993938477659926361457163384937565266894839330377063520304463379213493662243218514993889537829099698656597997161855278297938355255410088350528543369288722795261835727770017939399082258134647208444374973242138569356754462210049877096486232693547694891534331539434254781094641373606991238019101335437 c = 80140760654462267017719473677495407945806989083076205994692983838456863987736401342704400427420046369099889997909749061368480651101102957366243793278412775082041015336890704820532767466703387606369163429880159007880606865852075573350086563934479736264492605192640115037085361523151744341819385022516548746015224651520456608321954049996777342018093920514055242719341522462068436565236490888149658105227332969276825894486219704822623333003530407496629970767624179771340249861283624439879882322915841180645525481839850978628245753026288794265196088121281665948230166544293876326256961232824906231788653397049122767633 e = 65537 E = EllipticCurve(Zmod(n), [0, 95]) G = E(1, 34484956620179866074070847926139804359063142072294116788718557980902699327115656987124274229028140189100320603969008330866286764246306228523522742687628880235600852992498136916120692433600681811756379032521946702982740835213837602607673998432757011503342362501420917079002053526006602493983327263888542981905944223306284758287900181549380023600320809126518577943982963226746085664799480543700126384554756984361274849594593385089122492057335848048936127343198814676002820177792439241938851191156589839212021554296197426022622140915752674220260151964958964867477793087927995204920387657229909976501960074230485827919)
p = int(gcd((n*G)[2], n)) d = inverse(e, p-1) flag = long_to_bytes(int(pow(c, d, p))).decode() print(flag) # LilacCTF{wHy_NoT_w4tch1ng_yOutub3_with_NPoYb4mbiOg}