for p, i in factor((p + 1) // 4): assertnot p in choice if i > 1: cnt += 1 choice.add(p) assertint(p).bit_length() <= 32 else: prime_list.append(p) choice.add(p)
assertall([int(p).bit_length() <= 16for p in prime_list]) assert cnt == 1
return prime_list
defmain(): whileTrue: try: p = int(input("input your prime number or secret > ")) ifint(p).bit_length() == 256: if p == secret: print(FLAG) exit() print("not flag T_T") else: prime_list = check(p) P, Q = T_T(p, prime_list, secret) print(P.xy()) print(Q.xy()) except: print("T_T") exit() main()
# I received advice from Mitsu to write this program. I appreciate it very much
defmontgomery(Fp2, A): return EllipticCurve(Fp2, [0, A, 0, 1, 0])
defto_montgomery(Fp, Fp2, E, G): Ep = E.change_ring(Fp).short_weierstrass_model() a, b = Ep.a4(), Ep.a6() P.<x> = PolynomialRing(Fp) r = (x^3 + a*x + b).roots()[0][0] s = sqrt(3 * r^2 + a) ifnot is_square(s): s = -s A = 3 * r / s phi = E.isomorphism_to(EllipticCurve(Fp2, [0, A, 0, 1, 0])) return Fp(A), phi(G)
defgroup_action(p, primes, Fp, Fp2, pub, priv, G): E = montgomery(Fp2, pub) es = priv[:] whileany(es): x = Fp.random_element() P = E.lift_x(x) s = 1if P[1] in Fp else -1 S = [i for i, e inenumerate(es) if sign(e) == s and e != 0] k = prod([primes[i] for i in S]) Q = ((p + 1) // k) * P for i in S: R = (k // primes[i]) * Q if R.is_zero(): continue phi = E.isogeny(R) E = phi.codomain() Q, G = phi(Q), phi(G) es[i] -= s k //= primes[i] return to_montgomery(Fp, Fp2, E, G)
modd = [] c = [] for p in tqdm(pp): Fp = GF(p) Fp2.<j> = GF(p ^ 2, modulus=x ^ 2 + 1)
io.recvuntil(b"input your prime number or secret > ") io.sendline(str(p).encode()) Px,Py = eval(io.recvline().strip().decode()) Qx,Qy = eval(io.recvline().strip().decode())
A = Fp2((Fp2(Py)^2 - (Fp2(Px)^3 + Fp2(Px))) * Fp2(Px)^(-2)) EA = EllipticCurve(Fp2, [0, A, 0, 1, 0]) P = EA(Px,Py) Q = EA(Qx,Qy) modd.append(Q.order()) c.append((Q.log(P), Q.log(-P)))
for i in product([0,1],repeat=len(pp)): try: t = [c[j][i[j]] for j inrange(len(pp))] secret = crt(t,modd) if(len(bin(secret)) == 258): print(secret) io.sendline(str(secret).encode()) print(io.recvline()) print(io.recvline()) print(io.recvline()) except: pass
p, q, r = getPrime(512), getPrime(512), getPrime(512) N = e = p * q * r phi = (p - 1) * (q - 1) * (r - 1) d = pow(e, -1, phi)
# Genni likes squares and SBG likes cubes. Let's calculate their values value_for_genni = p**2 + (q + r * padded_flag)**2 value_for_sbg = p**3 + (q + r * padded_flag)**3
x0 = randbelow(N) x1 = randbelow(N)
print(f'{N = }') print(f'{x0 = }') print(f'{x1 = }') print('\nDo you prefer squares or cubes? Choose wisely!')
# Generate a random k and send v := (x_i + k^e), for Oblivious Transfer # This will allow you to calculate either Genni's or SBG's value # I have no way of knowing who you support. Your secret is completely safe! v = int(input('Send me v: '))
################################################################## part2 get p and q+rm defpolypow(base, exp, mod): return (mod.parent().quo(mod)(base) ** exp).lift()
PR.<x> = PolynomialRing(Zmod(N)) p = gcd(N, ZZ((polypow(x**3 - m1, N, x**2 - m0) + x0 - x1).monic()[0]**2 - m0)) qr = N // p t = ZZ(-(polypow(x**3 + p**3 - m1, N, x**2 + p**2 - m0) + x0 - x1).monic()[0])
################################################################## part3 get q,r qh = qr*bytes_to_long(b'SEKAI{' + b"\x00"*122) // t PR.<x> = PolynomialRing(Zmod(qr)) f = (qh + x)^2 - t*(qh + x) f = f.monic() res = f.small_roots(X = 2^(512-6*8),beta=1,epsilon=0.05) q = qh + int(res[0]) r = qr // q
################################################################## part4 flag m = (t - q) // r print(long_to_bytes(m))
from ast import literal_eval from hashlib import sha256 from Crypto.Cipher import AES
ells = [*primes(3, 128), 163] p = 4 * prod(ells) - 1 F = GF(p)
defcsidh(A, priv): E = EllipticCurve(F, [0, A, 0, 1, 0]) for sgn in [1, -1]: for e, ell inzip(priv, ells): for i inrange(sgn * e): whilenot (P := (p + 1) // ell * E.random_element()): pass E = E.isogeny_codomain(P) E = E.quadratic_twist() return E.montgomery_model().a2()
# This is the private key for the 163-isogeny, given by [0, 0, ..., 0, 1] priv_163 = [int(ell == 163) for ell in ells] pub_163 = csidh(0, priv_163)
# This is the private key for the sqrt(163)-isogeny, such that if you square it you get the 163-isogeny priv_rt163 = literal_eval(input("Enter private key: ")) pub_rt163 = csidh(0, priv_rt163)
assert csidh(pub_rt163, priv_rt163) == pub_163, "Your private key does not define a sqrt(163)-isogeny!"
from hashlib import sha256 from Crypto.Cipher import AES from tqdm import *
ells = [*primes(3, 128), 163] p = 4 * prod(ells) - 1 F = GF(p)
defcsidh(A, priv): E = EllipticCurve(F, [0, A, 0, 1, 0]) for sgn in [1, -1]: for e, ell inzip(priv, ells): for i inrange(sgn * e): whilenot (P := (p + 1) // ell * E.random_element()): pass E = E.isogeny_codomain(P) E = E.quadratic_twist() return E.montgomery_model().a2()
priv_163 = [int(ell == 163) for ell in ells] pub_163 = csidh(0, priv_163)
################################################################### part1 get order of cyclic group #print(pari.quadclassunit(-4*p)) order = 102019419125180345266808265 q3 = pari.Qfb(3, 2, (p + 1) // 3) assert q3^order == q3^0
################################################################### part2 dlog to get equivalent base if(0): dlogs = [] for ell in tqdm(ells[1:]): qfb = pari.Qfb(ell, 2, (p + 1) // ell) dlog = discrete_log(qfb, q3, order, operation=None, identity=q3^0, inverse=lambda x:x^-1, op=lambda a,b:a*b) dlogs.append(dlog) print(f'{dlogs = }')