from Crypto.Util.number import * from Crypto.Cipher import AES from tqdm import trange from sage.allimport * from itertools import product, combinations, permutations import multiprocessing as mp
l = len(tmps) M = column_matrix(tmps) Ker = M.left_kernel_matrix() Ker = Ker[:12, :] E = Ker.right_kernel_matrix().T
Es = [] for s1, s2, s3, s4 in product(range(-10, 11), repeat=4): v = E * vector([s1, s2, s3, s4]) ifall(0 <= i <= 255for i in v): Es.append(v)
choices = [*combinations(range(len(Es)), r=3)] t = len(choices) v = vector(tmps) defworker(begin, end): for idx in trange(begin,end): if idx >= len(choices): return e1, e2, e3 = [Es[j] for j in choices[idx]] modulus = gcd(column_matrix([e1, e2, e3]).left_kernel_matrix() * v) if isPrime(modulus) and modulus.bit_length() == 128: p1, p2, p3 = map(int, column_matrix(GF(modulus), [e1, e2, e3]).solve_right(v)) if p1.bit_length() < 128: p1 += modulus if p2.bit_length() < 128: p2 += modulus if p3.bit_length() < 128: p3 += modulus if isPrime(p1) and isPrime(p2) and isPrime(p3): print(p1, p2, p3, modulus, e1, e2, e3)
NUM_PROCESS = 10 gap = t // NUM_PROCESS ps = [] for x inrange(NUM_PROCESS): p = mp.Process(target=worker, args=(gap * x, gap * (x + 1))) p.start() ps.append(p) for p in ps: p.join()
for E in permutations([e1, e2, e3], r=3): print(aes.decrypt(bytes(sum([list(v) for v in E], [])))) # b'skbdg{congrats_you_have_mastered_both_OL_and_LP}'
但是看到 flag 是基于 OL 和 LP,那就很显然计算 e 的方式本意并不是靠爆破,不过这个以后再说了。 (¬‿¬)