from sage.allimport * from ast import literal_eval from secret import flag import random
ells = [*primes(3, 128), 163] p = 4*prod(ells)-1 B = QuaternionAlgebra(-1, -p) i,j,k = B.gens() O0 = B.quaternion_order([1, i, (i-j)/2, (1-k)/2])
defaction(O, priv): for i,ell inzip(priv,ells): for _ inrange(abs(i)): O = O.left_ideal([ell, j-sign(i)]).right_order() return B.quaternion_order(O.basis())
defcheck_safe_key(key): # for safety iflen(key) != len(ells) or0in key orany(abs(i) > 3for i in key): returnFalse returnTrue
menu = ''' 1. Start 2. Share 3. Guess '''
started = False alice = [randint(-3, 3) for _ inrange(len(ells))]
for __ inrange(16): print(menu) choice = input("Enter your choice: ") if choice == '1': start = literal_eval(input("Enter start: ")) if check_safe_key(start) and started == False: O0 = action(O0, start) Oa = action(O0, alice) started = True elif choice == '2': if started: bob = literal_eval(input("Hi bob, what's your key? ")) if check_safe_key(bob): coeff = random.choice([1, -1]) # random the direction :) bob = [ _ * coeff for _ in bob] Ob = action(O0, bob) O_share = action(Oa, bob) assert O_share.isomorphism_to(action(Ob, alice)) # it's a Diffie-Hellman protocol print("This is your share:", O_share.basis()) else: print("You don't have enough tickets.") continue elif choice == '3': guess = literal_eval(input("Enter your guess: ")) if guess == alice: print("You are really good at QuaternionAlgebra!, This is you flag:", flag) else: exit("Go away, you thief!") else: exit("Invalid choice")
ells = [*primes(3, 128), 163] p = 4*prod(ells)-1 B = QuaternionAlgebra(-1, -p) i,j,k = B.gens() O0 = B.quaternion_order([1, i, (i-j)/2, (1-k)/2])
defaction(O, priv): for i,ell inzip(priv,ells): for _ inrange(abs(i)): O = O.left_ideal([ell, j-sign(i)]).right_order() return B.quaternion_order(O.basis())
alice = [randint(-3, 3) for _ inrange(len(ells))] Oa = action(O0, alice) I = O0*Oa Connect_I = (1/I.norm())
ells = [*primes(3, 128), 163] p = 4*prod(ells)-1 B = QuaternionAlgebra(-1, -p) i,j,k = B.gens() O0 = B.quaternion_order([1, i, (i-j)/2, (1-k)/2])
defaction(O, priv): for i,ell inzip(priv,ells): for _ inrange(abs(i)): O = O.left_ideal([ell, j-sign(i)]).right_order() return B.quaternion_order(O.basis())
context.log_level = "critical" sh = process(["sage", "task.sage"])
################################################################################## First time sh.recvuntil(b"Enter your choice: ") sh.sendline(b"1") sh.sendline(str([3for _ inrange(len(ells))]).encode())
################################################################################## get alice key alice = [set(range(-3+3, 4+3)) for _ inrange(len(ells))] for _ in trange(14): sh.recvuntil(b"Enter your choice: ") sh.sendline(b"2") bob = [choice([-3,-2,-1,1,2,3]) for _ inrange(len(ells))] sh.sendline(str(bob).encode())
sh.recvuntil(b"This is your share:") Oab = B.quaternion_order(sage_eval(sh.recvline().strip().decode(), locals=globals())) I = O0*Oab Connect_I = (1/I.norm()) temp = list(factor(Connect_I))
for ii in ells: ind = ells.index(ii) FIND = 0 for jj in temp: if(ii == jj[0]): FIND = 1 alice[ind] = alice[ind] & set([jj[1]-bob[ind], jj[1]+bob[ind], -jj[1]+bob[ind], -jj[1]-bob[ind]]) break if(FIND == 0): alice[ind] = alice[ind] & set([-bob[ind], bob[ind]]) print(alice)
################################################################################## get flag alice = [list(_)[0]-3for _ in alice] sh.recvuntil(b"Enter your choice: ") sh.sendline(b"3") sh.recvuntil(b"Enter your guess: ") sh.sendline(str(alice).encode()) print(sh.recvline())
import os from hashlib import sha256 from random import SystemRandom
from Crypto.Cipher import AES from sage.allimport *
flag = os.environb.get(b"FLAG", b"flag{test_flag}")
n = 64 m = 200 p = 1048583 F = GF(p)
random = SystemRandom() errs = random.sample(range(p), 3) A = matrix(F, [[random.randrange(0, p - 1) for _ inrange(n)] for _ inrange(m)]) s = vector(F, [random.randrange(0, p - 1) for _ inrange(n)]) e = vector(F, [random.choice(errs) for _ inrange(m)]) b = A * s + e
for i inrange(k): for j inrange(k): for t inrange(k): L[k*i+j, k*i+t] += C[t,j] L[k*i+j, j+k*t] -= C[i,t] L = gaussian_elimination(L)[:k^2-k].T
L = Matrix(Zmod(n), L) M1, M2 = L[:k], L[k:] M = block_matrix(ZZ, [ [1, M1*M2^(-1)], [0, n] ])
from re import findall from subprocess import check_output
defflatter(M): # compile https://github.com/keeganryan/flatter and put it in $PATH z = "[[" + "]\n[".join(" ".join(map(str, row)) for row in M) + "]]" ret = check_output(["flatter"], input=z.encode()) return matrix(M.nrows(), M.ncols(), map(int, findall(b"-?\\d+", ret)))
M = flatter(M)
v = vector(ZZ, M[0]) MM = vector(ZZ, M[1]) for i inrange(-512, 512): key = list(map(abs, (i*v + MM).list())) if(all([0 <= j < 256for j in key])): key = bytes(key) aes = AES.new(key[:32], AES.MODE_CTR, nonce=key[-8:]) flag = aes.decrypt(ct) if(b"hitcon"in flag): print(flag)
defdecode_point(data: bytes): iflen(data) != 2 * field_bytes: raise ValueError("Invalid point encoding") x = int.from_bytes(data[:field_bytes], "big") y = int.from_bytes(data[field_bytes:], "big") return Point(x, y, secp256k1)
defhash_point(pt: Point): h = hashlib.sha256(encode_point(pt)).digest() returnint.from_bytes(h, "big") % q
defhash_points_to_scalars(pts: list[Point], n: int): s = sum([hash_point(pt) for pt in pts]) % q ret = [] for _ inrange(n): ret.append(s) s = (1337 * s + 7331) % q return ret
ProofType = list[tuple[Point, int]]
defprove(x: int, n: int) -> ProofType: rs = [secrets.randbelow(q) for _ inrange(n)] Grs = [G * r for r in rs] cs = hash_points_to_scalars(Grs, n) zs = [(r + c * x) % q for r, c inzip(rs, cs)] returnlist(zip(Grs, zs))
defverify(Y: Point, proof: ProofType): Grs, zs = zip(*proof) n = len(Grs) cs = hash_points_to_scalars(Grs, n) returnall(G * z == Gr + Y * c for Gr, z, c inzip(Grs, zs, cs)) * n
defserialize_proof(proof: ProofType): return json.dumps([(encode_point(pt).hex(), z) for pt, z in proof])
defdeserialize_proof(s: str) -> ProofType: return [(decode_point(bytes.fromhex(pt)), z) for pt, z in json.loads(s)]
defmain(): flag = os.environ.get("FLAG", "flag{test}")
sk = int.from_bytes(hashlib.sha256(flag.encode()).digest(), "big") % q pk = G * sk
print("Hey, I know the flag!") proof = prove(sk, 10) assert verify(pk, proof) == 10, "wtf" print("Here is the proof:") print(serialize_proof(proof)) print("Do you know it too?") proof = deserialize_proof(input("proof:")) n = verify(pk, proof) if n >= 42: print("I am convined :D") print(f"Here is it: {flag}") elif n > 0: print("Hmm, not sure about that... :thinking:") else: print("I think you don't :(")
defhash_point(pt: Point): h = hashlib.sha256(encode_point(pt)).digest() returnint.from_bytes(h, "big") % q
defhash_points_to_scalars(pts: list[Point], n: int): s = sum([hash_point(pt) for pt in pts]) % q ret = [] for _ inrange(n): ret.append(s) s = (1337 * s + 7331) % q return ret
ProofType = list[tuple[Point, int]]
defprove(x: int, n: int) -> ProofType: rs = [secrets.randbelow(q) for _ inrange(n)] Grs = [G * r for r in rs] cs = hash_points_to_scalars(Grs, n) zs = [(r + c * x) % q for r, c inzip(rs, cs)] returnlist(zip(Grs, zs))
from Crypto.Cipher import AES from hashlib import md5
vecs = gift = enc =
vecs_bin = [list(map(int, i)) for i in vecs] vecs_bin = [vector(GF(2), i) for i in vecs_bin]
nonce_bin = [list(map(int, bin(i[0])[2:].zfill(800))) for i in gift] nonce_bin = [vector(GF(2), i) for i in nonce_bin]
A = Matrix(GF(2), nonce_bin).T b = vector(GF(2), [i[1] for i in gift])
v0 = vecs_bin[0] L = Matrix(GF(2), [i - v0 for i in vecs_bin[1:]]) L1 = L.echelon_form()[:12]
v0_ = vector(GF(2), v0.list()*50) L1_ = block_diagonal_matrix([L1 for _ inrange(50)]) x = (L1_*A).solve_left(b - v0_*A)
x_ = [(vector(GF(2), x.list()[12*j:12*j+12])*L1+v0).list() for j inrange(50)] key = "" for i in x_: for j in i: key += str(j) key = int(key, 2) flag = AES.new(key=md5(str(key).encode()).digest(), nonce=b"Tiffany", mode=AES.MODE_CTR).decrypt(enc) print(flag)