defeat_cake(): p, q = getPrime(BITS), getPrime(BITS) ph = (p - 1) * (q + 1) N = p * q d = inverse(e, ph) cake = getPrime(BITS >> 1 | BITS) q = getPrime(BITS << 1 | BITS) f = d g = getPrime(size(q) - size(f) - 1) f_inv_q = inverse(f, q) h = f_inv_q * g % q r = getPrime(BITS) c1 = (r * h + cake) % q c2 = pow(cake, 0x10001, N) print(cake) return q, h, c1, N, c2
# In[103]:
defmake_cake(): p, q = getPrime(BITS), getPrime(BITS) N = p * q ph = (p - 1) * (q + 1) d = inverse(e, ph) cake = getPrime(BITS >> 1) q = getPrime(BITS << 1 | BITS) f = d g = getPrime(size(q) - size(f) - 1) f_inv_q = inverse(f, q) h = f_inv_q * g % q r = getPrime(BITS) c1 = (r * h + cake) % q c2 = pow(cake, d, N) return q, h, c1, N, c2
# In[104]:
defrational_to_quotients(x, y): a = x // y quotients = [a] while a * y != x: x, y = y, x - a * y a = x // y quotients.append(a) return quotients
defconvergents_from_quotients(quotients): convergents = [(quotients[0], 1)] for i in range(2, len(quotients) + 1): quotients_partion = quotients[0:i] denom = quotients_partion[-1] # 分母 num = 1 for _ in range(-2, -len(quotients_partion), -1): num, denom = denom, quotients_partion[_] * denom + num num += denom * quotients_partion[0] convergents.append((num, denom)) return convergents
# In[105]:
from tqdm import tqdm
# In[106]:
defcrack_d(): dAndN = [] for i in tqdm(range(15)): q, h, c1, N, c2 = make_cake() quotients = rational_to_quotients(h, q) convergents = convergents_from_quotients(quotients) for (k, f) in convergents: try: g = (f * h) % q f_inv_g = inverse(f, g) cake = (c1 * f % q) * f_inv_g % g if pow(cake, f, N) == c2: dAndN.append((f, N)) break except: pass return dAndN
# In[107]:
dAndN = crack_d()
# In[108]:
defcrack_e(dAndN): ds = [_[0] for _ in dAndN] Ns = [_[1] for _ in dAndN] M = isqrt(max(Ns)) A = Matrix(ZZ, len(dAndN) + 1, len(dAndN) + 1) A[0] = [M] + ds for i in range(len(dAndN)): A[i + 1, i + 1] = -Ns[i] AL = A.LLL() e = AL[0, 0] // M return abs(e)
# In[109]:
guessed_e = crack_e(dAndN)
# In[113]:
deffactor_n(e): q, h, c1, N, c2 = eat_cake() quotients = rational_to_quotients(h, q) convergents = convergents_from_quotients(quotients) for (k, f) in convergents: p = GCD(int(pow(2, f * e - 1, N) - 1), N) if p > 1and p < N: q = N // p d = inverse(0x10001, (p - 1) * (q - 1)) cake = pow(c2, d, N) print(cake) break
import Crypto.Random.random as random import multiprocessing as mp from functools import partial from json import load
defcrack(elements, c, k, r, ID=None): assert(len(elements) > r) n = len(elements) - r # reduce dim -> n forced_zero = list(range(len(elements))) indexes = set(range(len(elements))) coef = ceil(sqrt(n)) itr = 1 whileTrue: t0 = cputime() random.shuffle(forced_zero) zero = set(forced_zero[:r]) # print(zero) reduced_indexes = [elements[i] for i in indexes - zero] A_list = [[coef * c] + [0] * n + [coef * k]] for i, ele in enumerate(reduced_indexes): A_list.append([coef * ele] + [1 * (j == i + 1) for j in range(1, n + 1)] + [coef]) # random.shuffle(A_list) # row shuffle(extremely useful in most cases) A = Matrix(ZZ, A_list) AL = A.BKZ(block_size=22) print("[{}] {} runs, cost {:.3f} s.".format(ID, itr, cputime(t0))) for line in AL: if all(line[i] == 0or line[i] == -1for i in range(n + 2)) or all(line[i] == 0or line[i] == 1for i in range(n + 2)): if-1in line: line = -line print("[{}] {} success! {} {}".format(ID, itr, line[1:-1], zero)) part_sol = line[1:-1] sol = '' j = 0 for i in range(len(elements)): if i in zero: sol += '0' else: sol += str(part_sol[j]) j += 1 print("You got it ===> {}".format(sol)) returnTrue itr += 1
defmain(): CPU_CORE_NUM = 8# 8核 c, elements = load(open("data", "r")) k = 20 r = 15# 15-dim lower crack_ID = partial(crack, elements, c, k, r) # 高阶偏函数 with mp.Pool(CPU_CORE_NUM) as pool: status = pool.imap_unordered(crack_ID, range(1, 1 + CPU_CORE_NUM)) for s in status: if s: pool.terminate() break
import re, string from hashlib import sha256 from sys import argv # from tqdm import tqdm from binascii import hexlify, unhexlify from pwn import * from pwnlib.util.iters import mbruteforce