e = 65537 n = 198148795890507031730221728469492521085435050254010422245429012501864312776356522213014006175424179860455397661479243825590470750385249479224738397071326661046694312629376866307803789411244554424360122317688081850938387121934893846964467922503328604784935624075688440234885261073350247892064806120096887751 A = 1677936292368545917814039483235622978551357499172411081065325777729488793550136568309923513362117687939170753313352485633354858207097035878077942534451467 B = 5687468800624594128838903842767411040727750916115472185196475570099217560998907467291416768835644005325105434981167565207313702286530912332233402467314947 M = 1244793456976456877170839265783035368354692819005211513409129011314633866460250237897970818451591728769403864292158494516440464466254909969383897236264921 c = 48071438195829770851852911364054237976158406255022684617769223046035836237425012457131162001786019505606941050117178190535720928339364199078329207393922570246678871062386142183424414041935978305046280399687623437942986302690599232729065536417757505209285175593543234585659130582659013242346666628394528555
# def brute(interval): # Z = Zmod(M) # P = PolynomialRing(Z, "pp") # pp = P.gen() # qq = pp # for _ in range(interval): # qq = A * qq + B # f = pp * qq - n # return [ZZ(p) for p, e in f.roots()]
# for i in range(1, 1000): # r = brute(i) # print(i, r) # if len(r) > 0 and any(n % p == 0 for p in r): # break
# interval = 272 p = 243910118538351506548384880034426728169248862274637495579956619639346929105044407816656098657792419005522183874367421793338227934532131627126006227183679 q = n // p d = inverse_mod(e, (p - 1) * (q - 1)) print(long_to_bytes(power_mod(c, d, n)))
這題雖然是水題,只是我沒想到居然能拿到 first blood ==
a little easy rsa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
from Crypto.Util.number import *
N = 1024 P = 211 p = getPrime(P) q = getPrime(N-P) n = p*q print(n.bit_length()) d = p e = inverse(d, (p-1)*(q-1)) flag = bytes_to_long(open('flag','rb').read())
n = 73105772487291349396254686006336120330504972930577005514215080357374112681944087577351379895224746578654018931799727417401425288595445982938270373091627341969888521509691373957711162258987876168607165960620322264335724067238920761042033944418867358083783317156429326797580005138985469248465425537931352359757 e = 4537482391838140758438394964043410950504913123892269886065999941390882950665896428937682918187777255481111874006714423664290939580653075257588603498124366669194458116324464062487897262881136123858890202346251370203490050314565294751740805575602781718282190046613532413038947173662685728922451632009556797931 c = 14558936777299241791239306943800914301296723857812043136710252309211457210786844069103093229876701608756952780774067174377636161903673229776614350695222134040119114881027349864098519027057618922872932074441000483969146246381640236171500856974180238934543370727793393492372475990330143750179123498797867932379
q = gcd(power_mod(2, n * e, n) - 2, n) p = n // q m = power_mod(c, p, n)
print(long_to_bytes(m))
這題有趣的地方是 flag 內容說的是 coppersmith,intended
的做法大概是利用 這個事實,取 之後可以用 coppersmith 找 的 small root 吧。(flag 夠短,可以符合 )
whileTrue: io, magic = init() p = next_prime(floor(sqrt((magic << shift) // 2))) print("try prime", p) if (2 * p * p >> shift) == magic andmax(p for p, e in factor(p - 1)) < 2 ** 50: N = 2 * p * p phi = euler_phi(N) Z = Zmod(N) break io.close()
deffind_order(x): o = phi while x ^ o == 1: o //= 2 o *= 2 return o
for i inrange(3, 100): if find_order(Z(i)) == phi: g = Z(i) break
shift = 50 target = product([p for p in primes_first_n(1000) if randint(0, 1) == 1]) m = (target >> shift) << shift
B = 2 ^ shift a = 4 ap = 4 n = 1000 ps = primes_first_n(n) P = product(ps) # R = crt([-m] * n, ps) R = -m % P amp = lambda x: gcd(m + x, P) PR = PolynomialRing(ZZ, "x", 1) x = PR.gen() gs = [P ^ (a - i) * (x - R) ^ i for i inrange(a)] hs = [(x - R) ^ a * x ^ i for i inrange(ap)] polys = Sequence([f.subs(x=B * x) for f in gs + hs]) L, v = polys.coefficient_matrix() print("LLL", L.dimensions()) L = L.dense_matrix().LLL() for w in L * vector(v): print(w.subs(x=x / B).roots()) print(target - m)
defbalancedmod(f,q): g = list(((f[i] + q//2) % q) - q//2for i inrange(n)) return Zx(g) % (x^n-1)
defrandomdpoly(d1, d2): result = d1*[1]+d2*[-1]+(n-d1-d2)*[0] random.shuffle(result) return Zx(result)
definvertmodprime(f,p): T = Zx.change_ring(Integers(p)).quotient(x^n-1) return Zx(lift(1 / T(f)))
definvertmodpowerof2(f,q): assert q.is_power_of(2) g = invertmodprime(f,2) whileTrue: r = balancedmod(convolution(g,f),q) if r == 1: return g g = balancedmod(convolution(g,2 - r),q)
defkeypair(): whileTrue: try: f = randomdpoly(61, 60) f3 = invertmodprime(f,3) fq = invertmodpowerof2(f,q) break except Exception as e: pass g = randomdpoly(20, 20) publickey = balancedmod(3 * convolution(fq,g),q) secretkey = f return publickey, secretkey, g
defencode(val): poly = 0 for i inrange(n): poly += ((val%3)-1) * (x^i) val //= 3 return poly
flag = b2l(open('flag', 'rb').read()) print(encrypt(flag, publickey)) print(publickey)
# generate a lots of random data data = [ random.getrandbits(240) for _ inrange(200)] for random_msg in data: print(l2b(random_msg).hex(), encrypt(random_msg, publickey))