# get hint tmp_N = 67275889677378946734903321404206582364153218707836044936581311977721676158433934674861722018390091292542128885311842688233567992017423854706617140651934525455990460080562308585391373661331461122947028205118969966760791488914164391921330229025670176008518053339148134137770309365614255463111202481834705060173 cx = 40399377632586118650556149454962332599993544072289982576457293479237148938553095258299197606759611718110458893982875730643146645623512300513916266262798465380752083932871857821720398540072426424439422364690204675516506456125988918985863308292449915493404572808822346197667419207669315093927318993921905479596 pbar = 4877155090632997781879191807827231697420271396210537080241322765167927413977000532975047982026915056 e = 0x10001 for i inrange(3): p = known_hb(tmp_N, pbar, 512, i) if p: q = tmp_N // p print(get_flag(cx, p, q)) break secreteBitNum = 26
# get flag prime = 82321753209337659641812698792368753307257174920293482309329229017641186204037 c = 4327179356609269294409009935591795772603625779675971467878490086808144060225614005300908314649047950861015994603326121468330956776913366179511247457747179889685304469999218104955814145411915021238933150884498316563808220329632240175418452382843973948334446343545955570063628905102384071000832724697885872043017030707897928 N = 43941665823196509154346632368475246193489316520677500866461851257383928558997955146720003171553041820199105630143274308184375615057136594812756966125202091119439909980006181740220827474838356621605513939553184451557022029987518161532780360148932769025277495283357745880781214097057768654158857096614016596756958574010574773 leak1 = 4392924728395269190263639346144303703257730516994610750658 leak2 = 838456777370923849008096179359487752850229097203212
sbits = 64 tbits = 86 rbits = secreteBitNum s = leak1 << sbits t = leak2 << tbits
Fp = Zmod(prime) PR.<s0, t0, r0> = PolynomialRing(Fp) f = r0 * ((s + s0) ^ 2 + 2 * (s + s0)) - (t + t0) roots = small_roots(f, (2^sbits, 2^tbits, 2^rbits), 2) s += int(roots[0][0]) t += int(roots[0][1]) r = int(roots[0][2]) p = nextprime((s*(nextprime(s) * nextprime(r) + t))) if N % p == 0: q = N // p print(get_flag(c, p, q))
defsmall_roots(f, bounds, m=2, d=None): ifnot d: d = f.degree()
R = f.base_ring() N = R.cardinality()
f /= f.coefficients().pop(0) f = f.change_ring(ZZ)
G = Sequence([], f.parent()) for i inrange(m+1): base = N^(m-i) * f^i for shifts in itertools.product(range(d), repeat=f.nvariables()): g = base * prod(map(power, f.variables(), shifts)) G.append(g)
factors = [monomial(*bounds) for monomial in monomials] for i, factor inenumerate(factors): B.rescale_col(i, factor)
B = B.dense_matrix().LLL()
B = B.change_ring(QQ) for i, factor inenumerate(factors): B.rescale_col(i, 1/factor)
H = Sequence([], f.parent().change_ring(QQ)) for h infilter(None, B*monomials): H.append(h) I = H.ideal() if I.dimension() == -1: H.pop() elif I.dimension() == 0: roots = [] for root in I.variety(ring=ZZ): root = tuple(R(root[var]) for var in f.variables()) roots.append(root) return roots
defknown_hb(n, pbar, pbits, bb = 0): # pbar: p's high bits # pbits: p's original bit length # bb: bits for brute-force, default to zero pbar = int(hex(pbar) + '0' * bb, 16) # pbar >> p0bit << p0bit then turn to hex with bb's 0 padding for brute
# brute 4*bb's bits, i.e. 2 ^ (4 * bb) for i in tqdm(range(2 ^ (4 * bb))): tp = pbar + i p0bit = pbits - tp.bit_length() Fn = Zmod(n) PR.<x> = PolynomialRing(Fn) tp <<= p0bit f = tp + x roots = f.small_roots(X=2^p0bit, beta=0.4) if roots: p = tp + int(roots[0]) if n % p == 0: return p return []