from Crypto.Util.number import * y = [] km = [] possiblem = [] for i inrange(4): y.append(x[i+1]-x[i]) for j inrange(2): km.append(y[j+1]*y[j+1]-y[j]*y[j+2]) if j >= 1: if isPrime(GCD(km[j],km[j-1])): possiblem.append(GCD(km[j],km[j-1]))
x_1 = (x[0] + inverse(a,m)*(x[0]-x[1])) % m print(long_to_bytes(x_1))
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
from Crypto.Util.number import * y = [] km = [] possiblem = [] for i inrange(4): y.append(x[i+1]-x[i]) for j inrange(2): km.append(y[j+1]*y[j+1]-y[j]*y[j+2]) if j >= 1: if isPrime(GCD(km[j],km[j-1])): possiblem.append(GCD(km[j],km[j-1])) m = 17685238729089629081000199791073775580173848219782600577303616658328942786376878589055722139055973814631247947507009292556525580971952751595622172013382374577299734041726162411213993858497140178230251563824957482883763872967881950049985507310408962206729214890421322185752340466578359217999838551622613116097987673746844913920603425686103175874552686869764028906518131374266999714020645422015426801070343771422250037085635856203202935123956520415086942807824199018302630540169113637093488756273183240186533936637562954227188102214396705205042491881526862572569275650908415160529650027016717502470758797514488134766043 a = y[1]*inverse(y[0],m) % m print(a) x_1 = (x[0] + inverse(a,m)*(x[0]-x[1])) % m print(long_to_bytes(x_1))
defSolve_c(): sqrt_N = int(sqrt(N)) C = sqrt_N//g^2 a = 2 b = pow(a,g,N)
for i inrange(2,C): D = (int(sqrt(C)) + 1) * i final = pow(int(b),int(u),int(N)) tmp = 1 gs = pow(int(b), int(D), N) for r in tqdm(range(D)): for s inrange(D): #if powmod(int(b),int(r*D+s),N) == final: if tmp == final: print("r =",r,"s =",s,"i =",i) return r * D + s tmp = (tmp * int(b)) % N c = Solve_c() A = u - c # x * y = u - c
B = v + c * g # x + y = v + c * g
delta = iroot((B * B - 4 * A), 2)[0]
x = (B + delta) // 2
y = (B - delta) // 2
a = x // 2
b = y // 2
p = 2 * g * a + 1
q = 2 * g * b + 1
d = invert(e, (p - 1) * (q - 1))
m = powmod(C, d, N)
print(long_to_bytes(m))
数据处理
简单的求个离散对数
然后这里数字被替换了
直接遍历一遍所有组合,爆破就行了
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
from tqdm import * Z = Zmod(2^512) m = 5084057673176634704877325918195984684237263100965172410645544705367004138917087081637515846739933954602106965103289595670550636402101057955537123475521383 c = 2989443482952171039348896269189568991072039347099986172010150242445491605115276953489889364577445582220903996856271544149424805812495293211539024953331399 new_flag=str(discrete_log(Z(c), Z(m))) lowercase = '0123456789' uppercase = '7***4****5' from itertools import permutations for i in tqdm(permutations("0123689")): up = f"7{''.join(i[:3])}4{''.join(i[3:])}5" table = ''.maketrans(up, lowercase) flag = new_flag.translate(table) try: res = (long_to_bytes(int(flag)).decode()) if res.startswith("H&NCTF"): print(res) except: pass
ez-factor
注意到 其中k是512位,r是248位,r远远小于hint
那么我们有 r是一个小根,使用CopperSmith慢慢调参数即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
R = 2^248# r 的上界 e=0x10001 P.<x> = PolynomialRing(Zmod(N)) f = hint -x f = f.monic() # r = f.small_roots(X=R, beta=0.495, epsilon=0.015)[0] # print("Found r =", r) r = 310384729555967603261671853388867753979360895944109353196595111340924855459 p = gcd(hint - r, N) q = N // p assert p * q == N print("Found p =", p) print("Found q =", q) d = inverse(e,(p-1)*(q-1)) m = pow(c,d,N) print(long_to_bytes(m))
R = 2^252# r 的上界 e=0x10001 P.<x> = PolynomialRing(Zmod(N)) high_bits = 12#爆破高位 X = 2^(rbits - high_bits) - 1
for high in trange(2^high_bits,-1,-1): r_high = high << (rbits - high_bits) # 多项式:hint - (r_high + x) ≡ 0 mod p P.<x> = PolynomialRing(Zmod(N)) f = hint - (r_high + x) f = f.monic() roots = f.small_roots(X, beta=0.495, epsilon=0.03) if roots: r_low = roots[0] r = r_high + r_low print(f"Found r = {r}") break
得到r,后面就没什么了
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
r = 7166351305785506670352015492214713707534657162937963088592442157834795391917 c = "476922b694c764725338cca99d99c7471ec448d6bf60de797eb7cc6e71253221035eb577075f9658ac7f1a40747778ac261787baad21ee567256872fa9400c37" c = bytes.fromhex(c) leak=N*r p = gcd(hint - r, N) q = N // p r_bytes = long_to_bytes(leak) iv = r_bytes[:16] iflen(r_bytes) >= 16else r_bytes + b'\0'*(16-len(r_bytes)) key = sha256(str(p + q + r).encode()).digest()[:16] crypt_sm4 = CryptSM4() crypt_sm4.set_key(key, SM4_DECRYPT) decrypted = crypt_sm4.crypt_cbc(iv, c) flag = unpad(decrypted, 16) print("Flag:", flag.decode())