예제 #1
0
 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
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
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
예제 #5
0
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