Exemplo n.º 1
0
 def time_search_loop(p):
     y = random_vector(F, n)
     g = random_matrix(F, p, n).rows()
     scalars = [[Fstar[randint(0, q - 2)] for i in range(p)]
                for s in range(100)]
     before = process_time()
     for m in scalars:
         e = y - sum(m[i] * g[i] for i in range(p))
     return (process_time() - before) / 100.
Exemplo n.º 2
0
    def random_deformation(self, epsilon=None):
        """
        Return a random deformation

        INPUT:

        - ``epsilon`` -- a number in the base ring.

        OUTPUT:

        A new filtered vector space where the generators of the
        subspaces are moved by ``epsilon`` times a random vector.

        EXAMPLES::

            sage: gens = identity_matrix(3).rows()
            sage: F = FilteredVectorSpace(gens, {0:[0,1,2], 2:[0]});  F
            QQ^3 >= QQ^1 >= QQ^1 >= 0
            sage: F.get_degree(2)
            Vector space of degree 3 and dimension 1 over Rational Field
            Basis matrix:
            [1 0 0]
            sage: G = F.random_deformation(1/50);  G
            QQ^3 >= QQ^1 >= QQ^1 >= 0
            sage: D = G.get_degree(2)
            sage: D.degree()
            3
            sage: v = D.basis_matrix()[0]
            sage: v[0]
            1

            sage: while F.random_deformation(1/50).get_degree(2).matrix() == matrix([1, 0, 0]):
            ....:     pass
        """
        from sage.modules.free_module_element import random_vector
        R = self.base_ring()
        if epsilon is None:
            epsilon = R.one()
        filtration = dict()
        for deg, filt in self._filt[1:]:
            generators = [
                v + epsilon * random_vector(R, self.rank())
                for v in filt.echelonized_basis()
            ]
            filtration[deg] = generators
        return FilteredVectorSpace(filtration, base_ring=R, check=True)
Exemplo n.º 3
0
    def random_deformation(self, epsilon=None):
        """
        Return a random deformation

        INPUT:

        - ``epsilon`` -- a number in the base ring.

        OUTPUT:

        A new filtered vector space where the generators of the
        subspaces are moved by ``epsilon`` times a random vector.

        EXAMPLES::

            sage: gens = identity_matrix(3).rows()
            sage: F = FilteredVectorSpace(gens, {0:[0,1,2], 2:[0]});  F
            QQ^3 >= QQ^1 >= QQ^1 >= 0
            sage: F.get_degree(2)
            Vector space of degree 3 and dimension 1 over Rational Field
            Basis matrix:
            [1 0 0]
            sage: G = F.random_deformation(1/50);  G
            QQ^3 >= QQ^1 >= QQ^1 >= 0
            sage: G.get_degree(2)
            Vector space of degree 3 and dimension 1 over Rational Field
            Basis matrix:
            [      1 -15/304       0]
        """
        from sage.modules.free_module_element import random_vector
        R = self.base_ring()
        if epsilon is None:
            epsilon = R.one()
        filtration = dict()
        for deg, filt in self._filt[1:]:
            generators = [v + epsilon * random_vector(R, self.rank())
                          for v in filt.echelonized_basis()]
            filtration[deg] = generators
        return FilteredVectorSpace(filtration, base_ring=R, check=True)
Exemplo n.º 4
0
Arquivo: lwe.py Projeto: sagemath/sage
    def __init__(self, n, q, D, secret_dist='uniform', m=None):
        r"""
        Construct an LWE oracle in dimension ``n`` over a ring of order
        ``q`` with noise distribution ``D``.

        INPUT:

        - ``n`` - dimension (integer > 0)
        - ``q`` - modulus typically > n (integer > 0)
        - ``D`` - an error distribution such as an instance of
          :class:`DiscreteGaussianDistributionIntegerSampler` or :class:`UniformSampler`
        - ``secret_dist`` - distribution of the secret (default: 'uniform'); one of

          - "uniform" - secret follows the uniform distribution in `\Zmod{q}`
          - "noise" - secret follows the noise distribution
          - ``(lb,ub)`` - the secret is chosen uniformly from ``[lb,...,ub]`` including both endpoints

        - ``m`` - number of allowed samples or ``None`` if no such limit exists
          (default: ``None``)

        EXAMPLES:

        First, we construct a noise distribution with standard deviation 3.0::

            sage: from sage.stats.distributions.discrete_gaussian_integer import DiscreteGaussianDistributionIntegerSampler
            sage: D = DiscreteGaussianDistributionIntegerSampler(3.0)

        Next, we construct our oracle::

            sage: from sage.crypto.lwe import LWE
            sage: lwe = LWE(n=20, q=next_prime(400), D=D); lwe
            LWE(20, 401, Discrete Gaussian sampler over the Integers with sigma = 3.000000 and c = 0, 'uniform', None)

        and sample 1000 samples::

            sage: L = [lwe() for _ in range(1000)]

        To test the oracle, we use the internal secret to evaluate the samples
        in the secret::

            sage: S = [ZZ(a.dot_product(lwe._LWE__s) - c) for (a,c) in L]

        However, while Sage represents finite field elements between 0 and q-1
        we rely on a balanced representation of those elements here. Hence, we
        fix the representation and recover the correct standard deviation of the
        noise::

            sage: sqrt(variance([e if e <= 200 else e-401 for e in S]).n())
            3.0...

        If ``m`` is not ``None`` the number of available samples is restricted::

            sage: from sage.crypto.lwe import LWE
            sage: lwe = LWE(n=20, q=next_prime(400), D=D, m=30)
            sage: _ = [lwe() for _ in range(30)]
            sage: lwe() # 31
            Traceback (most recent call last):
            ...
            IndexError: Number of available samples exhausted.
        """
        self.n  = ZZ(n)
        self.m =  m
        self.__i = 0
        self.K  = IntegerModRing(q)
        self.FM = FreeModule(self.K, n)
        self.D = D

        self.secret_dist = secret_dist
        if secret_dist == 'uniform':
            self.__s = random_vector(self.K, self.n)
        elif secret_dist == 'noise':
            self.__s = vector(self.K, self.n, [self.D() for _ in range(n)])
        else:
            try:
                lb, ub = map(ZZ, secret_dist)
                self.__s = vector(self.K, self.n, [randint(lb,ub) for _ in range(n)])
            except (IndexError, TypeError):
                raise TypeError("Parameter secret_dist=%s not understood."%(secret_dist))
Exemplo n.º 5
0
    def __init__(self, n, q, D, secret_dist='uniform', m=None):
        """
        Construct an LWE oracle in dimension ``n`` over a ring of order
        ``q`` with noise distribution ``D``.

        INPUT:

        - ``n`` - dimension (integer > 0)
        - ``q`` - modulus typically > n (integer > 0)
        - ``D`` - an error distribution such as an instance of
          :class:`DiscreteGaussianSamplerRejection` or :class:`UniformSampler`
        - ``secret_dist`` - distribution of the secret (default: 'uniform'); one of

          - "uniform" - secret follows the uniform distribution in `\Zmod{q}`
          - "noise" - secret follows the noise distribution
          - ``(lb,ub)`` - the secret is chosen uniformly from ``[lb,...,ub]`` including both endpoints

        - ``m`` - number of allowed samples or ``None`` if no such limit exists
          (default: ``None``)

        EXAMPLE:

        First, we construct a noise distribution with standard deviation 3.0::

            sage: from sage.crypto.lwe import DiscreteGaussianSampler
            sage: D = DiscreteGaussianSampler(3.0)

        Next, we construct our oracle::

            sage: from sage.crypto.lwe import LWE
            sage: lwe = LWE(n=20, q=next_prime(400), D=D); lwe
            LWE(20, 401, DiscreteGaussianSamplerRejection(3.000000, 53, 4), 'uniform', None)

        and sample 1000 samples::

            sage: L = [lwe() for _ in range(1000)]

        To test the oracle, we use the internal secret to evaluate the samples
        in the secret::

            sage: S = [ZZ(a.dot_product(lwe._LWE__s) - c) for (a,c) in L]

        However, while Sage represents finite field elements between 0 and q-1
        we rely on a balanced representation of those elements here. Hence, we
        fix the representation and recover the correct standard deviation of the
        noise::

            sage: sqrt(variance([e if e <= 200 else e-401 for e in S]).n())
            3.0...

        If ``m`` is not ``None`` the number of available samples is restricted::

            sage: from sage.crypto.lwe import LWE
            sage: lwe = LWE(n=20, q=next_prime(400), D=D, m=30)
            sage: _ = [lwe() for _ in range(30)]
            sage: lwe() # 31
            Traceback (most recent call last):
            ...
            IndexError: Number of available samples exhausted.
        """
        self.n = ZZ(n)
        self.m = m
        self.__i = 0
        self.K = IntegerModRing(q)
        self.FM = FreeModule(self.K, n)
        self.D = D

        self.secret_dist = secret_dist
        if secret_dist == 'uniform':
            self.__s = random_vector(self.K, self.n)
        elif secret_dist == 'noise':
            self.__s = vector(self.K, self.n, [self.D() for _ in range(n)])
        else:
            try:
                lb, ub = map(ZZ, secret_dist)
                self.__s = vector(self.K, self.n,
                                  [randint(lb, ub) for _ in range(n)])
            except (IndexError, TypeError):
                raise TypeError("Parameter secret_dist=%s not understood." %
                                (secret_dist))