M = (N - 1) // (2 * g) u = M // (2 * g) v = M - 2 * g * u GF = Zmod(N) x = GF.random_element() y = x ^ (2 * g) # c的范围大概与N^(0.5-2*gamma)很接近 c = bsgs(y, y ^ u, (2**(cbits-1), 2**(cbits+1)), operation='*') #(a, b, bounds, operation='*', identity=None, inverse=None, op=None) ab = u - c apb = v + 2 * g * c P.<x> = ZZ[] f = x ^ 2 - apb * x + ab a = f.roots() if a: a, b = a[0][0], a[1][0] p = 2 * g * a + 1 q = 2 * g * b + 1 assert p * q == N
from Crypto.Util.number import * print(long_to_bytes(int(pow(enc,inverse(e,(p-1)*(q-1)),N))))
Harr = #复制题目中给出的数据 n,e = (73566307488763122580179867626252642940955298748752818919017828624963832700766915409125057515624347299603944790342215380220728964393071261454143348878369192979087090394858108255421841966688982884778999786076287493231499536762158941790933738200959195185310223268630105090119593363464568858268074382723204344819, 65537) c = 30332590230153809507216298771130058954523332140754441956121305005101434036857592445870499808003492282406658682811671092885592290410570348283122359319554197485624784590315564056341976355615543224373344781813890901916269854242660708815123152440620383035798542275833361820196294814385622613621016771854846491244
vh=Matrix(ZZ,Harr[:10]).T E100=Matrix(ZZ,[[i==j for j inrange(10)]for i inrange(10)]) L1=block_matrix([vh,E100],ncols=2) L1=list(L1) L1.append([0]*10+[n]) L1=Matrix(ZZ,L1) V=L1.LLL()
brute = 2 for i inrange(2**brute): for j inrange(2**brute): L = Matrix(ZZ, [ [1,0,0,2**brute*c1], [0,1,0,2**brute*c2], [0,0,2**(512-brute),c1*i+c2*j-c1*c2], [0,0,0,n3] ]) L[:,-1:] *= n3 res = L.LLL()[0]
p = 2**brute*abs(res[0])+i if(n3 % p == 0): print(p)
import time from subprocess import check_output from multiprocessing import Pool
defflatter(M): # compile https://github.com/keeganryan/flatter and put it in $PATH z = "[[" + "]\n[".join(" ".join(map(str, row)) for row in M) + "]]" ret = check_output(["flatter"], input=z.encode()) from re import findall return matrix(M.nrows(), M.ncols(), map(int, findall(b"-?\\d+", ret)))
# 显示有用矢量的统计数据 defhelpful_vectors(BB, modulus): nothelpful = 0 for ii inrange(BB.dimensions()[0]): if BB[ii,ii] >= modulus: nothelpful += 1
print (nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")
# 显示带有 0 和 X 的矩阵 defmatrix_overview(BB, bound): for ii inrange(BB.dimensions()[0]): a = ('%02d ' % ii) for jj inrange(BB.dimensions()[1]): a += '0'if BB[ii,jj] == 0else'X' if BB.dimensions()[0] < 60: a += ' ' if BB[ii, ii] >= bound: a += '~' #print (a)
# x-移位 gg = [] for kk inrange(mm + 1): for ii inrange(mm - kk + 1): xshift = x^ii * modulus^(mm - kk) * polZ(u, x, y)^kk gg.append(xshift) gg.sort()
# 单项式 x 移位列表 monomials = [] for polynomial in gg: for monomial in polynomial.monomials(): #对于多项式中的单项式。单项式(): if monomial notin monomials: # 如果单项不在单项中 monomials.append(monomial) monomials.sort()
# y-移位 for jj inrange(1, tt + 1): for kk inrange(floor(mm/tt) * jj, mm + 1): yshift = y^jj * polZ(u, x, y)^kk * modulus^(mm - kk) yshift = Q(yshift).lift() gg.append(yshift) # substitution
# 单项式 y 移位列表 for jj inrange(1, tt + 1): for kk inrange(floor(mm/tt) * jj, mm + 1): monomials.append(u^kk * y^jj)
# 构造格 B nn = len(monomials) BB = Matrix(ZZ, nn) for ii inrange(nn): BB[ii, 0] = gg[ii](0, 0, 0) for jj inrange(1, ii + 1): if monomials[jj] in gg[ii].monomials(): BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](UU,XX,YY)
#约化格的原型 if helpful_only: # #自动删除 BB = remove_unhelpful(BB, monomials, modulus^mm, nn-1) # 重置维度 nn = BB.dimensions()[0] if nn == 0: print ("failure") return0,0
# 检查向量是否有帮助 if debug: helpful_vectors(BB, modulus^mm)
# 检查行列式是否正确界定 det = BB.det() bound = modulus^(mm*nn) if det >= bound: if debug: diff = (log(det) - log(bound)) / log(2) print ("size det(L) - size e^(m*n) = ", floor(diff)) if strict: return -1, -1 else: print ("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")
# display the lattice basis if debug: matrix_overview(BB, modulus^mm)
# LLL if debug: print ("optimizing basis of the lattice via LLL, this can take a long time")
#BB = BB.BKZ(block_size=25) BB = flatter(BB)
if debug: print ("LLL is done!")
# 替换向量 i 和 j ->多项式 1 和 2 if debug: print ("在格中寻找线性无关向量") found_polynomials = False
size=512#The size of p; size=1024 in Tables 10 length_N = 2*size s=70; #s is the number of MSBs exhaustion, which can be chosen as we need. nw=3#2^nw windows delta = 0.292
N = 107892573713246099817538936816485851035053538530228178586297516104462355899705036416845549988000543254717342505493461294554541098637839010844819316344397595836466293908827352240852019945855020602201742694540642287347823025883131162483705106324646432257707195307227627208850506071985510840207212074649893852289; e = 106026779355993573435326995058838659695563314723896436315704944869047461810171317853485834578907922477225219563648678852066399786593146779733369104463848604460901829459576565561299893410357693816050012889075185831684944657633027210516389798278082334754603104594287285628025433146548664548308055805258965566543; c = 74801258971353592087655273561994005413765184821038662179717923534370360999501931581907306714940348903440446458261785275314423770475637996343903355116249112854972152857616186571871846360852766323423533588570164035716759526288174656142706806500076294386681134096440267098094279442917447969106043371238327287569; # The parameters (N, e) can be chosen as we need. m = 12# 格大小(越大越好/越慢) #guess=100 # you need to be a lattice master to tweak these t = round(((1-2*delta) * m)) # 来自 Herrmann 和 May 的优化 X = floor(N^delta) # Y = 2*floor(N^(1/2)/2^s) # 如果 p、 q 大小相同,则正确
p0=pM*2^(size-s)+2^(size-s-1); q0=qM*2^(size-s)+2^(size-s-1) #qM=int(q0/2^(size-s)) A = N + 1-pM*2^(size-s)-qM*2^(size-s); P.<x,y> = PolynomialRing(ZZ) pol = 1 + x * (A + y) #构建的方程 if debug: ##print ("=== running algorithm ===") start_time = time.time()
solx, soly = boneh_durfee(pol, e, m, t, X, Y)
if solx > 0: #print ("=== solution found ===") ifFalse: print ("x:", solx) print ("y:", soly)
det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found) === solution found === p的高比特为: 895381917907042032873 q的高比特为: 934258518638868635029 d= 686044856631363471654750621230244587429581968036750428251137157884014229839209884769622191 225.63660335540771
import gmpy2 import random import binascii from hashlib import sha256 from sympy import nextprime from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Util.number import long_to_bytes from FLAG import flag #flag = 'wdflag{123}'
p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f a = 0 b = 7 xG = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 yG = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 G = (xG, yG) n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 h = 1 zero = (0,0)
dA = nextprime(random.randint(0, n))
if dA > n: print("warning!!")
defaddition(t1, t2): if t1 == zero: return t2 if t2 == zero: return t2 (m1, n1) = t1 (m2, n2) = t2 if m1 == m2: if n1 == 0or n1 != n2: return zero else: k = (3 * m1 * m1 + a) % p * gmpy2.invert(2 * n1 , p) % p else: k = (n2 - n1 + p) % p * gmpy2.invert((m2 - m1 + p) % p, p) % p m3 = (k * k % p - m1 - m2 + p * 2) % p n3 = (k * (m1 - m3) % p - n1 + p) % p return (int(m3),int(n3))
defmultiplication(x, k): ans = zero t = 1 while(t <= k): if (k &t )>0: ans = addition(ans, x) x = addition(x, x) t <<= 1 return ans
defgetrs(z, k): (xp, yp) = P r = xp s = (z + r * dA % n) % n * gmpy2.invert(k, n) % n return r,s
z1 = random.randint(0, p) z2 = random.randint(0, p) k = random.randint(0, n) P = multiplication(G, k) hA = multiplication(G, dA) r1, s1 = getrs(z1, k) r2, s2 = getrs(z2, k)
p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f a = 0 b = 7 xG = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 yG = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 h = 1 E=EllipticCurve(GF(p),[a,b]) G = E(xG, yG)
from hashlib import sha256 key = sha256(long_to_bytes(dA)).digest()
# In[5]:
from Crypto.Util.Padding import pad from Crypto.Util.number import long_to_bytes from Crypto.Cipher import AES encFlagHex='6c201c3c4e8b0a2cdd0eca11e7101d45d7b33147d27ad1b9d57e3d1e20c7b3c2e36b8da3142dfd5abe335a604ce7018878b9f157099211a7bbda56ef5285ec0b' ivHex,ciph1=encFlagHex[:32],encFlagHex[32:] cipher = AES.new(key, AES.MODE_CBC,iv=bytes.fromhex(ivHex)) cipher.decrypt(bytes.fromhex(ciph1))