#Sage #多项式 N = p = q = Q.<x> = Zmod(q)[] P.<y> = Zmod(p)[]
ex = hx =
print('-------decrypt------') qq = x^N-1 pp = y^N-1 hn = [int(x) for x in hx.coefficients()] n = len(hn) A1 = matrix.identity(n) A0 = matrix.zero(n) Aq = matrix.identity(n) * q Ah = matrix(ZZ, [hn[-i:] + hn[:-i] for i inrange(n)]) M = block_matrix([A1,Ah,A0,Aq],nrows=2) L = M.LLL() v = L[0] f = list(v)[:n] g = list(v)[n:] fx = Q(f) fy = P(f) gx = Q(g) Fqx = fx.inverse_mod(qq) Fpy = fy.inverse_mod(pp)
#hxx = (Fqx*gx).mod(x^N-1) #print(hxx==hx)
ax = (fx*ex).mod(qq) an = [int(x) for x in ax.coefficients()] #中心提升(centerlift),使域范围从[0,q)变换到(-q/2,q/2) for i inrange(len(an)): if an[i] > q//2: an[i] -= q ax = P(an) print(ax) out = (Fpy * ax).mod(pp) print(out)
#脚本1-小规模 #Sage from sage.modules.free_module_integer import IntegerLattice
row = column = prime =
ma = res =
W = matrix(ZZ, ma) cc = vector(ZZ, res)
# Babai's Nearest Plane algorithm defBabai_closest_vector(M, G, target): small = target for _ inrange(5): for i inreversed(range(M.nrows())): c = ((small * G[i]) / (G[i] * G[i])).round() small -= M[i] * c return target - small
A1 = matrix.identity(column) Ap = matrix.identity(row) * prime B = block_matrix([[Ap], [W]]) lattice = IntegerLattice(B, lll_reduce=True) print("LLL done") gram = lattice.reduced_basis.gram_schmidt()[0] target = vector(ZZ, res) re = Babai_closest_vector(lattice.reduced_basis, gram, target) print("Closest Vector: {}".format(re))
R = IntegerModRing(prime) M = Matrix(R, ma) M = M.transpose()
#脚本2-大规模 #Sage from sage.modules.free_module_integer import IntegerLattice from random import randint import sys from itertools import starmap from operator import mul
# Babai's Nearest Plane algorithm # from: http://mslc.ctf.su/wp/plaidctf-2016-sexec-crypto-300/ defBabai_closest_vector(M, G, target): small = target for _ inrange(1): for i inreversed(range(M.nrows())): c = ((small * G[i]) / (G[i] * G[i])).round() small -= M[i] * c return target - small
m = n = q =
A_values = b_values =
A = matrix(ZZ, m + n, m) for i inrange(m): A[i, i] = q for x inrange(m): for y inrange(n): A[m + y, x] = A_values[x][y] lattice = IntegerLattice(A, lll_reduce=True) print("LLL done") gram = lattice.reduced_basis.gram_schmidt()[0] target = vector(ZZ, b_values) res = Babai_closest_vector(lattice.reduced_basis, gram, target) print("Closest Vector: {}".format(res))
R = IntegerModRing(q) M = Matrix(R, A_values) ingredients = M.solve_right(res)
print("Ingredients: {}".format(ingredients))
for row, b inzip(A_values, b_values): effect = sum(starmap(mul, zip(map(int, ingredients), row))) % q assert(abs(b - effect) < 2 ** 37)
defallpmones(v): returnlen([vj for vj in v if vj in [-1, 0, 1]]) == len(v)
# We generate the lattice of vectors orthogonal to b modulo x0 deforthoLattice(b, x0): m = b.length() M = Matrix(ZZ, m, m)
for i inrange(1, m): M[i, i] = 1 M[1:m, 0] = -b[1:m] * inverse_mod(b[0], x0) M[0, 0] = x0
for i inrange(1, m): M[i, 0] = mod(M[i, 0], x0)
return M
defallones(v): iflen([vj for vj in v if vj in [0, 1]]) == len(v): return v iflen([vj for vj in v if vj in [0, -1]]) == len(v): return -v returnNone
defrecoverBinary(M5): lv = [allones(vi) for vi in M5 if allones(vi)] n = M5.nrows() for v in lv: for i inrange(n): nv = allones(M5[i] - v) if nv and nv notin lv: lv.append(nv) nv = allones(M5[i] + v) if nv and nv notin lv: lv.append(nv) return Matrix(lv)
defkernelLLL(M): n = M.nrows() m = M.ncols() if m < 2 * n: return M.right_kernel().matrix() K = 2 ^ (m // 2) * M.height()
MB = Matrix(ZZ, m + n, m) MB[:n] = K * M MB[n:] = identity_matrix(m)
MB2 = MB.T.LLL().T
assert MB2[:n, : m - n] == 0 Ke = MB2[n:, : m - n].T
return Ke
defattack(m, n, p, h): # This is the Nguyen-Stern attack, based on BKZ in the second step print("n =", n, "m =", m)
iota = 0.035 nx0 = int(2 * iota * n ^ 2 + n * log(n, 2)) print("nx0 =", nx0)