from Crypto.Util.number import * from hashlib import * from flag import flag import random from gmpy2 import *
file = open("outext.txt", "w")
m = bytes_to_long(flag.encode()) e = 0x10001
p = getPrime(512) q = getPrime(512) r = getPrime(512) s = getRandomRange(2**0, 2**5) n = p * q * r hint_1 = powmod(p, r, n) hint_2 = powmod(r, s - 2, n)
c = powmod(m, e * (s - 1), n) file.write(f"n={n}\n") file.write(f"hint_1={hint_1}\n") file.write(f"hint_2={hint_2}\n") file.write(f"c={c}\n")
# n = 979979396280795025447159604653924698007421096864863532640467914347154790478966309310242938046375382963295576018108365493749631126829441159428446514913045553768462359812141188437867022522642883215617924930162362975118753135307868195989529952635950471650238440782216155187808858076406173123376307233605251322063056796573051571421373804400742814841380628966244338908899920978345766251241466839953205051967073060065807266111902771444846685228931419177071776202794447 # hint_1 = 63829737789015303255616010995430271442615363334005654136790603132124697763248934614727407142426063514798780422988294297457892974476968909011594056992955895743933371737158975962646294428475380486162081880712675820233377927503162194872237855275106302109770193104087596464371630697812485876577638759333868021626793193900551035852971032420289295901322943785198833653840660632317598841581456445704445974646032512822137015643024549120429185146320086905286336984565780 # hint_2 = 811225663987535096929418484923252315039418484176390289011682551835727122657404871203738500127970361216735459526184706907379779604453737161603694233134616612209864675829711293451990923072581678837181277865189990566773712777076953922847187456309194004847987239678695437936130991596979472315709241564675102503547056625609492959906116295807701067076200192520193721233660324426348223046220024274205328004516104292752500294107591971181194232357501832617229377939678909 # c = 554491127748739273581999967419384543160020010465406113035040735016528899552140169583353294062576591579973382955030891201758740151326341677432402990540380379170704264251101185973670282744523850032981933697291881931773848908998356042585230566838554495089166039238470892330078315451993029959200347825405258393357495512040019534150921164118639093729837315213487083882435472600420840995787008748593481029626822135460873446903992348211665228818922931223995184301813181
分析
由 hint_1 = powmod(p, r, n),即
。又因为 n = p * q * r,上式可以写成
n = 979979396280795025447159604653924698007421096864863532640467914347154790478966309310242938046375382963295576018108365493749631126829441159428446514913045553768462359812141188437867022522642883215617924930162362975118753135307868195989529952635950471650238440782216155187808858076406173123376307233605251322063056796573051571421373804400742814841380628966244338908899920978345766251241466839953205051967073060065807266111902771444846685228931419177071776202794447 hint_1 = 63829737789015303255616010995430271442615363334005654136790603132124697763248934614727407142426063514798780422988294297457892974476968909011594056992955895743933371737158975962646294428475380486162081880712675820233377927503162194872237855275106302109770193104087596464371630697812485876577638759333868021626793193900551035852971032420289295901322943785198833653840660632317598841581456445704445974646032512822137015643024549120429185146320086905286336984565780 hint_2 = 811225663987535096929418484923252315039418484176390289011682551835727122657404871203738500127970361216735459526184706907379779604453737161603694233134616612209864675829711293451990923072581678837181277865189990566773712777076953922847187456309194004847987239678695437936130991596979472315709241564675102503547056625609492959906116295807701067076200192520193721233660324426348223046220024274205328004516104292752500294107591971181194232357501832617229377939678909 c = 554491127748739273581999967419384543160020010465406113035040735016528899552140169583353294062576591579973382955030891201758740151326341677432402990540380379170704264251101185973670282744523850032981933697291881931773848908998356042585230566838554495089166039238470892330078315451993029959200347825405258393357495512040019534150921164118639093729837315213487083882435472600420840995787008748593481029626822135460873446903992348211665228818922931223995184301813181 e = 65537
p = gmpy2.gcd(hint_1, n) r = gmpy2.gcd(hint_1 - p, n) // p q = n // p // r s = 0
for i inrange(2, 2**5 + 1): ifpow(r, i - 2, n) == hint_2: s = i break
phi = (p - 1) * (q - 1) * (r - 1) E = e * (s - 1) if gmpy2.gcd(E, phi) == 1: d = gmpy2.invert(E, phi) m = pow(c, d, n) print(long_to_bytes(m)) else: g = gmpy2.gcd(E, phi) E_prime = E // g d = gmpy2.invert(E_prime, phi) m_pow = pow(c, d, n) # 注意 iroot()函数返回的是元组 m, exact = gmpy2.iroot(m_pow, g) print(long_to_bytes(m))
defgaussian_mulmod(x, y, n): return gaussian_mod(gmul(x, y), n)
defgaussian_powmod(x, e, n): x = gaussian_mod(x, n) res = gi(1, 0) while e: if e & 1: res = gaussian_mulmod(res, x, n) x = gaussian_mulmod(x, x, n) e >>= 1 return res
defrandom_prime_1mod4(bits): whileTrue: p = ZZ(random_prime(ZZ(2) ** bits - 1, lbound=ZZ(2) ** (bits - 1))) if p % 4 == 1and gcd(p - 1, E) == 1: return p
defrandom_gaussian_prime(bits): # A Gaussian prime whose norm is a rational prime of the requested bit size. ell = random_prime_1mod4(bits) a, b = two_squares(ell) if random.randrange(2): b = -b return gi(a, b), ell
defbuild_flag(): withopen("flag.txt", "rb") as f: return f.read().strip()
defflag_to_gaussian_poly(flag): half = len(flag) // 2 real = flag[:half] imag = flag[half:] m = gi(0, 0) for i, (a, b) inenumerate(zip(real, imag)): m = gadd(m, gmul(gi(a, b), gi(BASE ** i, 0))) return m
flag = build_flag() assert flag.startswith(b"H&NCTF{") and flag.endswith(b"}") assertlen(flag) == 2 * (K + 2) half = len(flag) // 2
p, np = random_gaussian_prime(PRIME_BITS) q, nq = random_gaussian_prime(PRIME_BITS) while np == nq: q, nq = random_gaussian_prime(PRIME_BITS)
N = gmul(p, q) M = flag_to_gaussian_poly(flag) C = gaussian_powmod(M, E, N)