def __init__(self, d, m, q): """ Initialize a secret key. """ # Public parameters self.d = d self.m = m self.q = q self.hash_function = hashlib.shake_256 slack = 1.1 smooth = 1.28 while (1): try: # Key generation self.A, self.B, invB, self.sq_gs_norm = module_ntru_gen( d, q, m) G = gram(self.B) self.B_fft = [[fft(elt) for elt in row] for row in self.B] self.invB_fft = [[fft(elt) for elt in row] for row in invB] G_fft = [[fft(elt) for elt in row] for row in G] self.T_fft = ffldl_fft(G_fft) self.sigma = smooth * sqrt(self.sq_gs_norm) self.signature_bound = slack * (self.m + 1) * self.d * (self.sigma**2) normalize_tree(self.T_fft, self.sigma) self.rate = bitsize(int(round(self.sigma))) - 2 # print("self.rate =", self.rate) return except ValueError: continue
def __init__(self, n): """Initialize a secret key.""" # Public parameters self.n = n self.sigma = Params[n]["sigma"] self.sigmin = Params[n]["sigmin"] self.signature_bound = Params[n]["sig_bound"] self.sig_bytelen = Params[n]["sig_bytelen"] # Compute NTRU polynomials f, g, F, G verifying fG - gF = q mod Phi self.f, self.g, self.F, self.G = ntru_gen(n) # From f, g, F, G, compute the basis B0 of a NTRU lattice # as well as its Gram matrix and their fft's. B0 = [[self.g, neg(self.f)], [self.G, neg(self.F)]] G0 = gram(B0) self.B0_fft = [[fft(elt) for elt in row] for row in B0] G0_fft = [[fft(elt) for elt in row] for row in G0] self.T_fft = ffldl_fft(G0_fft) # Normalize Falcon tree normalize_tree(self.T_fft, self.sigma) # The public key is a polynomial such that h*f = g mod (Phi,q) self.h = div_zq(self.g, self.f)
def __init__(self, n): """Initialize a secret key.""" """Public parameters""" self.n = n self.q = q self.hash_function = hashlib.shake_256 """Private key part 1: NTRU polynomials f, g, F, G verifying fG - gF = q mod Phi""" self.f, self.g, self.F, self.G = ntru_gen(n) """Private key part 2: fft's of f, g, F, G""" self.f_fft = fft(self.f) self.g_fft = fft(self.g) self.F_fft = fft(self.F) self.G_fft = fft(self.G) """Private key part 3: from f, g, F, G, compute the basis B0 of a NTRU lattice as well as its Gram matrix and their fft's""" self.B0 = [[self.g, neg(self.f)], [self.G, neg(self.F)]] self.G0 = gram(self.B0) self.B0_fft = [[fft(elt) for elt in row] for row in self.B0] self.G0_fft = [[fft(elt) for elt in row] for row in self.G0] # self.T = ffldl(self.G0) self.T_fft = ffldl_fft(self.G0_fft) """Private key part 4: compute sigma and signature bound.""" sq_gs_norm = gs_norm(self.f, self.g, q) self.sigma = 1.28 * sqrt(sq_gs_norm) self.signature_bound = 2 * self.n * (self.sigma**2) """Private key part 5: set leaves of tree to be the standard deviations.""" normalize_tree(self.T_fft, self.sigma) """Public key: h such that h*f = g mod (Phi,q)""" self.h = div_zq(self.g, self.f)
def test_ffnp(d, m, iterations): """Test ffnp. This functions check that: 1. the two versions (coefficient and FFT embeddings) of ffnp are consistent 2. ffnp output lattice vectors close to the targets. """ q = q_12289 A, B, inv_B, sqr_gsnorm = module_ntru_gen(d, q, m) G0 = gram(B) G0_fft = [[fft(elt) for elt in row] for row in G0] T = ffldl(G0) T_fft = ffldl_fft(G0_fft) th_bound = (m + 1) * d * sqr_gsnorm / 4. mn = 0 for i in range(iterations): t = [[random() for coef in range(d)] for poly in range(m + 1)] t_fft = [fft(elt) for elt in t] z = ffnp(t, T) z_fft = ffnp_fft(t_fft, T_fft) zb = [ifft(elt) for elt in z_fft] zb = [[round(coef) for coef in elt] for elt in zb] if z != zb: print("ffnp and ffnp_fft are not consistent") return False diff = [sub(t[i], z[i]) for i in range(m + 1)] diffB = vecmatmul(diff, B) norm_zmc = int(round(sqnorm(diffB))) mn = max(mn, norm_zmc) if mn > th_bound: print("z = {z}".format(z=z)) print("t = {t}".format(t=t)) print("mn = {mn}".format(mn=mn)) print("th_bound = {th_bound}".format(th_bound=th_bound)) print("sqr_gsnorm = {sqr_gsnorm}".format(sqr_gsnorm=sqr_gsnorm)) print("Warning: the algorithm outputs vectors longer than expected") return False else: return True
def test_ffnp(n, iterations): """Test ffnp. This functions check that: 1. the two versions (coefficient and FFT embeddings) of ffnp are consistent 2. ffnp output lattice vectors close to the targets. """ f = sign_KAT[n][0]["f"] g = sign_KAT[n][0]["g"] F = sign_KAT[n][0]["F"] G = sign_KAT[n][0]["G"] B = [[g, neg(f)], [G, neg(F)]] G0 = gram(B) G0_fft = [[fft(elt) for elt in row] for row in G0] T = ffldl(G0) T_fft = ffldl_fft(G0_fft) sqgsnorm = gs_norm(f, g, q) m = 0 for i in range(iterations): t = [[random() for i in range(n)], [random() for i in range(n)]] t_fft = [fft(elt) for elt in t] z = ffnp(t, T) z_fft = ffnp_fft(t_fft, T_fft) zb = [ifft(elt) for elt in z_fft] zb = [[round(coef) for coef in elt] for elt in zb] if z != zb: print("ffnp and ffnp_fft are not consistent") return False diff = [sub(t[0], z[0]), sub(t[1], z[1])] diffB = vecmatmul(diff, B) norm_zmc = int(round(sqnorm(diffB))) m = max(m, norm_zmc) th_bound = (n / 4.) * sqgsnorm if m > th_bound: print("Warning: ffnp does not output vectors as short as expected") return False else: return True