#aeroctf2021 #good_challenges_2021
#!/usr/bin/env python3.8 from os import urandom from gmpy2 import next_prime from random import randrange, getrandbits from Crypto.Cipher import AES from fastecdsa.curve import Curve def bytes_to_long(data): return int.from_bytes(data, 'big') def generate_random_point(p): while True: a, x, y = (randrange(0, p) for _ in range(3)) b = (pow(y, 2, p) - pow(x, 3, p) - a * x) % p if (4 * pow(a, 3, p) + 27 * pow(b, 2, p)) % p != 0: break return Curve(None, p, a, b, None, x, y).G class DarkWizard: def __init__(self, age): self.power = int(next_prime(getrandbits(age))) self.magic = generate_random_point(self.power) self.soul = randrange(0, self.power) def create_horcrux(self, location, weakness): # committing a murder murder = self.cast_spell(b'AVADA KEDAVRA') # splitting the soul in half self.soul = self.soul * pow(2, -1, self.power) % self.power # making a horcrux horcrux = (self.soul + murder) * self.magic # nobody should know location and weakness of the horcrux horcrux.x ^= location horcrux.y ^= weakness return horcrux def cast_spell(self, spell_name): spell = bytes_to_long(spell_name) return spell %~ spell # -1 def encrypt(key, plaintext): cipher = AES.new(key=key, mode=AES.MODE_ECB) padding = b'\x00' * (AES.block_size - len(plaintext) % AES.block_size) return cipher.encrypt(plaintext + padding) def main(): wizard_age = 3000 horcruxes_count = 2 wizard = DarkWizard(wizard_age) print(f'Wizard\'s power:\n{hex(wizard.power)}\n') print(f'Wizard\'s magic:\n{wizard.magic}\n') key = urandom(AES.key_size[0]) # 16 horcrux_length = len(key) // horcruxes_count for i in range(horcruxes_count): key_part = key[i * horcrux_length:(i + 1) * horcrux_length] horcrux_location = bytes_to_long(key_part[:horcrux_length // 2]) horcrux_weakness = bytes_to_long(key_part[horcrux_length // 2:]) horcrux = wizard.create_horcrux(horcrux_location, horcrux_weakness) print(f'Horcrux #{i + 1}:\n{horcrux}\n') with open('flag.txt', 'rb') as file: flag = file.read().strip() ciphertext = encrypt(key, flag) print(f'Ciphertext:\n{ciphertext.hex()}') if __name__ == '__main__': main()
やっていることは……
ランダムな曲線のランダムな点 を作る
ランダムなパラメータ (=
soul
)を作るとして
に対して
に対して
として、を求める問題
与えられるパラメータは……
- の4つ
パラメータの大きさ
それぞれ3000bitくらい
32bit くらい
考察(ボツ)
と書いて EllipticCurve の 加法公式 より
とおきつつ
↑で実際には は下位32bitはわからないのでこれを と置き直して計算したい
考察
と
より、
となるので を消して
が成り立つ
- ↑で実際には は下位32bitはわからないのでこれを と置き直して
solution
これで一応解ける……。要するに、未知数は32bitまでで、↑の等式をみても、最大でも未知数は4乗までにしかならないので、それぞれの項を分解して行列に入れると良い
要するに
(は最大でもの未知数)
なのでと置き直して
↑という格子を考えて、lb, ubはとかとかになることを考えるとCVPで解ける(解けるのかと思うかもしれないけど、のエントロピー(知らないbit数の和)は1000bitくらいであるのに対して、は3000bitくらいあるので解ける)
# x1 = (x1 >> 32) << 32 # y1 = (y1 >> 32) << 32 # x2 = (x2 >> 32) << 32 # y2 = (y2 >> 32) << 32 print("[+] Start...") PR.<s1, t1, s2, t2> = PolynomialRing(GF(p)) # (y_g^2 - y_1^2 - x_g^3 + x_1^3)(x_2 - x_1) = (y_2^2 - y_1^2 - x_2^3 + x_1^3)(x_g - x_1) f = (gy^2 - (y1 + t1)^2 - gx^3 + (x1 + s1)^3)*((x2 + s2) - (x1 + s1)) - ((y2 + t2)^2 - (y1 + t1)^2 - (x2 + s2)^3 + (x1 + s1)^3)*(gx - (x1 + s1)) print("[+] Make lattice...") coeffs = f.coefficients() monomials = f.monomials() degrees = [monomial.degree() for monomial in monomials] n = len(monomials) M = matrix(ZZ, n, n) M.set_block(0, 0, matrix.identity(n-1)) M[n-1] = coeffs M[n-1,n-1] = p lb = [0 for _ in range(n)] ub = [0 for _ in range(n)] for i in range(n): lb[i] = -(2^(32*degrees[i])) ub[i] = 2^(32*degrees[i]) lb[-1] = int((-coeffs[-1]) % p) ub[-1] = int((-coeffs[-1]) % p) # target = [(u + l) // 2 for u, l in zip(lb, ub)] # size = max(target) # weights = [] # # for i in range(len(ub)): # w = size // target[i] if target[i] != 0 else size # M[i] *= w # target[i] *= w # weights.append(w) # # print("[+] CVP...") # closest = Babai_CVP(M.transpose(), vector(target)) # # print("[+] done") # print([closest[i] // weights[i] for i in range(len(closest))]) results, weights = solve(M.transpose(), lb, ub) print([results[i] // weights[i] for i in range(len(results))]) s1 = closest[-5] // weights[-5] t1 = closest[-4] // weights[-4] s2 = closest[-3] // weights[-3] t2 = closest[-2] // weights[-2] print(s1, t1, s2, t2)