Frozen

Frozen like there is no sun, yet, we know the Meltdown will be arriving soon!

Files given:

d = 32

def keygen(params, l, d):
	p, r = params
	s = getRandomRange(1, p)
	U = [pow(r, c + 1, p) * s % p for c in range(0,l)]
	V = [int(bin(u)[2:][:-d] + '0' * d, 2) for u in U]
	S = [int(bin(u)[2:][-d:], 2) for u in U]
	privkey, pubkey = S, V
	return pubkey, privkey

def sign(msg, privkey, d):
	msg = msg.encode('utf-8')
	l = len(msg) // 4
	M = [bytes_to_long(msg[4*i:4*(i+1)]) for i in range(l)]
	q = int(next_prime(max(M)))
	sign = [M[i]*privkey[i] % q for i in range(l)]
	return sign

This challenge gives a server with \(4\) options:

| Options: 
|	[S]how the params - gives p,r
|	[P]rint pubkey  - gives pubkey
|	[E]xample signature - gives signature of random 20 char string
|	[F]orge the signature - asks signature of random 20 char string
|	[Q]uit

Looking at the signing function, we can easily recover privkey[i] % q given the message and since \(256^4=2^{32}\), this almost recovers the entire privkey[i], so we only need to add a small multiple of \(q\). Seeing the keygen function, we know that after adding the private and public key together, we should get a geometric series. This will tell us when we are done adding multiples of \(q\). From here the brute force is quite simple.

Solution at solve.py

Flag: CCTF{Lattice_bA5eD_T3cHn1QuE_70_Br34K_LCG!!}