Example #1
0
def test_correctness(n=512, c2_vec_num=None, q=251, seed=None):
    """
    Testing LAC PQC submission correctness values
    n = such that ring is x^{n}+1 (not checking for power of 2  though) 
    q = modulus

    Returns number of positions where decrypted message differs from encrypted message
 
 
    """
    if c2_vec_num is None:
        c2_vec_num = n

    if seed is not None:
        from sage.misc.randstate import set_random_seed
        set_random_seed(seed)

    ZZ = IntegerRing()
    ZZ_q = IntegerModRing(q)

    R = ZZ_q['x'].quotient(cyclotomic_polynomial(2 * n, 'x'), 'x')

    #    print("R={0},{1}".format(R,type(R)))
    bar_q = R((q - 1) / 2)

    # Set up public key
    a_pol = R.random_element()

    s_pol = R(sample_noise)
    e_pol = R(sample_noise)

    b_pol = (a_pol * s_pol + e_pol)

    # Set up encryption
    message = sample_message(R.degree())

    r_pol = R(sample_noise)
    e1_pol = R(sample_noise)
    e2_pol = R(sample_noise)

    c1_pol = a_pol * r_pol + e1_pol
    c2_pol = b_pol * r_pol + e2_pol + bar_q * R(message)

    # Set up decryption
    u_pol = R(c1_pol * s_pol)

    noisy_pol = R(c2_pol - u_pol)

    decoded_message = decode_message(R, q, noisy_pol)

    def comp_mess(x, y):
        return 1 if x != y else 0

    mult_message = [
        comp_mess(message[i], decoded_message[i])
        for i in range(len(decoded_message))
    ]
    diff_weight = reduce(lambda x, y: x + y, mult_message)

    return diff_weight
Example #2
0
def samples(m, n, lwe, seed=None, balanced=False, **kwds):
    """
    Return ``m`` LWE samples.

    INPUT:

    - ``m`` - the number of samples (integer > 0)
    - ``n`` - the security parameter (integer > 0)
    - ``lwe`` - either

      - a subclass of :class:`LWE` such as :class:`Regev` or :class:`LindnerPeikert`
      - an instance of :class:`LWE` or any subclass
      - the name of any such class (e.g., "Regev", "LindnerPeikert")

    - ``seed`` - seed to be used for generation or ``None`` if no specific seed
      shall be set (default: ``None``)
    - ``balanced`` - use function :func:`balance_sample` to return balanced
      representations of finite field elements (default: ``False``)
    - ``**kwds`` - passed through to LWE constructor

    EXAMPLE::

        sage: from sage.crypto.lwe import samples, Regev
        sage: samples(2, 20, Regev, seed=1337)
        [((199, 388, 337, 53, 200, 284, 336, 215, 75, 14, 274, 234, 97, 255, 246, 153, 268, 218, 396, 351), 18),
        ((286, 42, 175, 155, 190, 275, 114, 280, 45, 218, 304, 386, 98, 235, 77, 0, 65, 20, 163, 14), 334)]

        sage: from sage.crypto.lwe import samples, Regev
        sage: samples(2, 20, Regev, balanced=True, seed=1337)
        [((199, -13, -64, 53, 200, -117, -65, -186, 75, 14, -127, -167, 97, -146, -155, 153, -133, -183, -5, -50), 18),
        ((-115, 42, 175, 155, 190, -126, 114, -121, 45, -183, -97, -15, 98, -166, 77, 0, 65, 20, 163, 14), -67)]

        sage: from sage.crypto.lwe import samples
        sage: samples(2, 20, 'LindnerPeikert')
        [((1302, 718, 1397, 147, 278, 979, 1185, 133, 902, 1180, 1264, 734, 2029, 314, 428, 18, 707, 2021, 1153, 173), 1127),
        ((2015, 1278, 455, 429, 1391, 186, 149, 1199, 220, 1629, 843, 719, 1744, 1568, 674, 1462, 1549, 972, 248, 1066), 1422)]

    """
    if seed is not None:
        set_random_seed(seed)

    if isinstance(lwe, str):
        lwe = eval(lwe)

    if type(lwe) == type:
        lwe = lwe(n, m=m, **kwds)
    else:
        lwe = lwe
        if lwe.n != n:
            raise ValueError(
                "Passed LWE instance has n=%d, but n=%d was passed to this function."
                % (lwe.n, n))

    if balanced is False:
        f = lambda (a, c): (a, c)
    else:
        f = balance_sample
    return [f(lwe()) for _ in xrange(m)]
Example #3
0
def samples(m, n, lwe, seed=None, balanced=False, **kwds):
    """
    Return ``m`` LWE samples.

    INPUT:

    - ``m`` - the number of samples (integer > 0)
    - ``n`` - the security parameter (integer > 0)
    - ``lwe`` - either

      - a subclass of :class:`LWE` such as :class:`Regev` or :class:`LindnerPeikert`
      - an instance of :class:`LWE` or any subclass
      - the name of any such class (e.g., "Regev", "LindnerPeikert")

    - ``seed`` - seed to be used for generation or ``None`` if no specific seed
      shall be set (default: ``None``)
    - ``balanced`` - use function :func:`balance_sample` to return balanced
      representations of finite field elements (default: ``False``)
    - ``**kwds`` - passed through to LWE constructor

    EXAMPLES::

        sage: from sage.crypto.lwe import samples, Regev
        sage: samples(2, 20, Regev, seed=1337)
        [((199, 388, 337, 53, 200, 284, 336, 215, 75, 14, 274, 234, 97, 255, 246, 153, 268, 218, 396, 351), 15),
         ((365, 227, 333, 165, 76, 328, 288, 206, 286, 42, 175, 155, 190, 275, 114, 280, 45, 218, 304, 386), 143)]

        sage: from sage.crypto.lwe import samples, Regev
        sage: samples(2, 20, Regev, balanced=True, seed=1337)
        [((199, -13, -64, 53, 200, -117, -65, -186, 75, 14, -127, -167, 97, -146, -155, 153, -133, -183, -5, -50), 15),
         ((-36, -174, -68, 165, 76, -73, -113, -195, -115, 42, 175, 155, 190, -126, 114, -121, 45, -183, -97, -15), 143)]

        sage: from sage.crypto.lwe import samples
        sage: samples(2, 20, 'LindnerPeikert')
        [((506, 1205, 398, 0, 337, 106, 836, 75, 1242, 642, 840, 262, 1823, 1798, 1831, 1658, 1084, 915, 1994, 163), 1447),
         ((463, 250, 1226, 1906, 330, 933, 1014, 1061, 1322, 2035, 1849, 285, 1993, 1975, 864, 1341, 41, 1955, 1818, 1357), 312)]

    """
    if seed is not None:
        set_random_seed(seed)

    if isinstance(lwe, str):
        lwe = eval(lwe)

    if isinstance(lwe, type):
        lwe = lwe(n, m=m, **kwds)
    else:
        lwe = lwe
        if lwe.n != n:
            raise ValueError(
                "Passed LWE instance has n=%d, but n=%d was passed to this function."
                % (lwe.n, n))

    if balanced is False:
        f = lambda a_c: a_c
    else:
        f = balance_sample
    return [f(lwe()) for _ in range(m)]
Example #4
0
def samples(m, n, lwe, seed=None, balanced=False, **kwds):
    """
    Return ``m`` LWE samples.

    INPUT:

    - ``m`` - the number of samples (integer > 0)
    - ``n`` - the security parameter (integer > 0)
    - ``lwe`` - either

      - a subclass of :class:`LWE` such as :class:`Regev` or :class:`LindnerPeikert`
      - an instance of :class:`LWE` or any subclass
      - the name of any such class (e.g., "Regev", "LindnerPeikert")

    - ``seed`` - seed to be used for generation or ``None`` if no specific seed
      shall be set (default: ``None``)
    - ``balanced`` - use function :func:`balance_sample` to return balanced
      representations of finite field elements (default: ``False``)
    - ``**kwds`` - passed through to LWE constructor

    EXAMPLE::

        sage: from sage.crypto.lwe import samples, Regev
        sage: samples(2, 20, Regev, seed=1337)
        [((199, 388, 337, 53, 200, 284, 336, 215, 75, 14, 274, 234, 97, 255, 246, 153, 268, 218, 396, 351), 15),
         ((365, 227, 333, 165, 76, 328, 288, 206, 286, 42, 175, 155, 190, 275, 114, 280, 45, 218, 304, 386), 143)]

        sage: from sage.crypto.lwe import samples, Regev
        sage: samples(2, 20, Regev, balanced=True, seed=1337)
        [((199, -13, -64, 53, 200, -117, -65, -186, 75, 14, -127, -167, 97, -146, -155, 153, -133, -183, -5, -50), 15),
         ((-36, -174, -68, 165, 76, -73, -113, -195, -115, 42, 175, 155, 190, -126, 114, -121, 45, -183, -97, -15), 143)]

        sage: from sage.crypto.lwe import samples
        sage: samples(2, 20, 'LindnerPeikert')
        [((506, 1205, 398, 0, 337, 106, 836, 75, 1242, 642, 840, 262, 1823, 1798, 1831, 1658, 1084, 915, 1994, 163), 1447),
         ((463, 250, 1226, 1906, 330, 933, 1014, 1061, 1322, 2035, 1849, 285, 1993, 1975, 864, 1341, 41, 1955, 1818, 1357), 312)]

    """
    if seed is not None:
        set_random_seed(seed)

    if isinstance(lwe, str):
        lwe = eval(lwe)

    if isinstance(lwe, type):
        lwe = lwe(n, m=m, **kwds)
    else:
        lwe = lwe
        if lwe.n != n:
            raise ValueError("Passed LWE instance has n=%d, but n=%d was passed to this function."%(lwe.n, n))

    if balanced is False:
        f = lambda a_c: a_c
    else:
        f = balance_sample
    return [f(lwe()) for _ in xrange(m)]
Example #5
0
File: lwe.py Project: Etn40ff/sage
def samples(m, n, lwe, seed=None, balanced=False, **kwds):
    """
    Return ``m`` LWE samples.

    INPUT:

    - ``m`` - the number of samples (integer > 0)
    - ``n`` - the security parameter (integer > 0)
    - ``lwe`` - either

      - a subclass of :class:`LWE` such as :class:`Regev` or :class:`LindnerPeikert`
      - an instance of :class:`LWE` or any subclass
      - the name of any such class (e.g., "Regev", "LindnerPeikert")

    - ``seed`` - seed to be used for generation or ``None`` if no specific seed
      shall be set (default: ``None``)
    - ``balanced`` - use function :func:`balance_sample` to return balanced
      representations of finite field elements (default: ``False``)
    - ``**kwds`` - passed through to LWE constructor

    EXAMPLE::

        sage: from sage.crypto.lwe import samples, Regev
        sage: samples(2, 20, Regev, seed=1337)
        [((199, 388, 337, 53, 200, 284, 336, 215, 75, 14, 274, 234, 97, 255, 246, 153, 268, 218, 396, 351), 18),
        ((286, 42, 175, 155, 190, 275, 114, 280, 45, 218, 304, 386, 98, 235, 77, 0, 65, 20, 163, 14), 334)]

        sage: from sage.crypto.lwe import samples, Regev
        sage: samples(2, 20, Regev, balanced=True, seed=1337)
        [((199, -13, -64, 53, 200, -117, -65, -186, 75, 14, -127, -167, 97, -146, -155, 153, -133, -183, -5, -50), 18),
        ((-115, 42, 175, 155, 190, -126, 114, -121, 45, -183, -97, -15, 98, -166, 77, 0, 65, 20, 163, 14), -67)]

        sage: from sage.crypto.lwe import samples
        sage: samples(2, 20, 'LindnerPeikert')
        [((1302, 718, 1397, 147, 278, 979, 1185, 133, 902, 1180, 1264, 734, 2029, 314, 428, 18, 707, 2021, 1153, 173), 1127),
        ((2015, 1278, 455, 429, 1391, 186, 149, 1199, 220, 1629, 843, 719, 1744, 1568, 674, 1462, 1549, 972, 248, 1066), 1422)]

    """
    if seed is not None:
        set_random_seed(seed)

    if isinstance(lwe, str):
        lwe = eval(lwe)

    if isinstance(lwe, type):
        lwe = lwe(n, m=m, **kwds)
    else:
        lwe = lwe
        if lwe.n != n:
            raise ValueError("Passed LWE instance has n=%d, but n=%d was passed to this function."%(lwe.n, n))

    if balanced is False:
        f = lambda a_c: a_c
    else:
        f = balance_sample
    return [f(lwe()) for _ in xrange(m)]
Example #6
0
def sample_noise(length, max_hamming = None, seed=None, sample_elem = None):
    """
    Python port of create_spter_vec from Round2 submission

    INPUT:

    - ``length`` - the length of the vector to return
    - ``max_hamming`` - the maximum hamming weight allowed for the response vector; for a given value of ``max_hamming``, exactly (``length``-``max_hamming``) elements of the vector will be set to 0. The other ``max_hamming`` elements will be chosen via the method given in ``sample_elem`` so potentially the actual hamming weight of the output vector could be strictly less than ``max_hamming`` if ``sample_elem`` ever outputs 0
    - ``sample_elem`` - should be in the form ``sample_elem`` = (``sample_func``, ``sample_min_val``, ``sample_max_val``) and samples individual elements
    
    """
    if max_hamming is None or max_hamming < 0 or max_hamming > length:
        max_hamming = length
    if seed is not None:
        from sage.misc.randstate import set_random_seed
        set_random_seed(seed)
    if sample_elem is None or len(sample_elem) != 3:
        # set default as +-1 randomly
        def temp_samp():
            return 2*randrange(0,2)-1
        sample_func=temp_samp
        sample_min_val=-1
        sample_max_val=1
    else:
        sample_func=sample_elem[0]
        sample_min_val = sample_elem[1]
        sample_max_val = sample_elem[2]

    sample_range = sample_max_val - sample_min_val
    # get mask 2^{k}-1
    sample_mask = get_mask(sample_range)
    
    h_arr=[]
    h_arr.extend([sample_func() - sample_min_val for i in range(max_hamming)])
    h_arr.extend([-sample_min_val for i in range(length-max_hamming)])

    rnd_arr = [(randrange(0,1 << 32) & ~sample_mask) ^ (h_arr[i] & sample_mask)    for i in range(length)]
    rnd_arr.sort()

    ret_vec=[(rnd_arr[i] & sample_mask) + sample_min_val for i in range(length)]
    return ret_vec
    
    

    
        
Example #7
0
def gen_lattice(type='modular', n=4, m=8, q=11, seed=None,
                quotient=None, dual=False, ntl=False, lattice=False):
    """
    This function generates different types of integral lattice bases
    of row vectors relevant in cryptography.

    Randomness can be set either with ``seed``, or by using
    :func:`sage.misc.randstate.set_random_seed`.

    INPUT:

    - ``type`` -- one of the following strings
        - ``'modular'`` (default) -- A class of lattices for which
          asymptotic worst-case to average-case connections hold. For
          more refer to [A96]_.
        - ``'random'`` -- Special case of modular (n=1). A dense class
          of lattice used for testing basis reduction algorithms
          proposed by Goldstein and Mayer [GM02]_.
        - ``'ideal'`` -- Special case of modular. Allows for a more
          compact representation proposed by [LM06]_.
        - ``'cyclotomic'`` -- Special case of ideal. Allows for
          efficient processing proposed by [LM06]_.
    - ``n`` -- Determinant size, primal:`det(L) = q^n`, dual:`det(L) = q^{m-n}`.
      For ideal lattices this is also the degree of the quotient polynomial.
    - ``m`` -- Lattice dimension, `L \subseteq Z^m`.
    - ``q`` -- Coefficient size, `q-Z^m \subseteq L`.
    - ``seed`` -- Randomness seed.
    - ``quotient`` -- For the type ideal, this determines the quotient
      polynomial. Ignored for all other types.
    - ``dual`` -- Set this flag if you want a basis for `q-dual(L)`, for example
      for Regev's LWE bases [R05]_.
    - ``ntl`` -- Set this flag if you want the lattice basis in NTL readable
      format.
    - ``lattice`` -- Set this flag if you want a
      :class:`FreeModule_submodule_with_basis_integer` object instead
      of an integer matrix representing the basis.

    OUTPUT: ``B`` a unique size-reduced triangular (primal: lower_left,
      dual: lower_right) basis of row vectors for the lattice in question.

    EXAMPLES:

    Modular basis::

        sage: sage.crypto.gen_lattice(m=10, seed=42)
        [11  0  0  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0  0  0]
        [ 2  4  3  5  1  0  0  0  0  0]
        [ 1 -5 -4  2  0  1  0  0  0  0]
        [-4  3 -1  1  0  0  1  0  0  0]
        [-2 -3 -4 -1  0  0  0  1  0  0]
        [-5 -5  3  3  0  0  0  0  1  0]
        [-4 -3  2 -5  0  0  0  0  0  1]

    Random basis::

        sage: sage.crypto.gen_lattice(type='random', n=1, m=10, q=11^4, seed=42)
        [14641     0     0     0     0     0     0     0     0     0]
        [  431     1     0     0     0     0     0     0     0     0]
        [-4792     0     1     0     0     0     0     0     0     0]
        [ 1015     0     0     1     0     0     0     0     0     0]
        [-3086     0     0     0     1     0     0     0     0     0]
        [-5378     0     0     0     0     1     0     0     0     0]
        [ 4769     0     0     0     0     0     1     0     0     0]
        [-1159     0     0     0     0     0     0     1     0     0]
        [ 3082     0     0     0     0     0     0     0     1     0]
        [-4580     0     0     0     0     0     0     0     0     1]

    Ideal bases with quotient x^n-1, m=2*n are NTRU bases::

        sage: sage.crypto.gen_lattice(type='ideal', seed=42, quotient=x^4-1)
        [11  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0]
        [ 4 -2 -3 -3  1  0  0  0]
        [-3  4 -2 -3  0  1  0  0]
        [-3 -3  4 -2  0  0  1  0]
        [-2 -3 -3  4  0  0  0  1]

    Ideal bases also work with polynomials::

        sage: R.<t> = PolynomialRing(ZZ)
        sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=t^4-1)
        [11  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0]
        [ 4  1  4 -3  1  0  0  0]
        [-3  4  1  4  0  1  0  0]
        [ 4 -3  4  1  0  0  1  0]
        [ 1  4 -3  4  0  0  0  1]

    Cyclotomic bases with n=2^k are SWIFFT bases::

        sage: sage.crypto.gen_lattice(type='cyclotomic', seed=42)
        [11  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0]
        [ 4 -2 -3 -3  1  0  0  0]
        [ 3  4 -2 -3  0  1  0  0]
        [ 3  3  4 -2  0  0  1  0]
        [ 2  3  3  4  0  0  0  1]

    Dual modular bases are related to Regev's famous public-key
    encryption [R05]_::

        sage: sage.crypto.gen_lattice(type='modular', m=10, seed=42, dual=True)
        [ 0  0  0  0  0  0  0  0  0 11]
        [ 0  0  0  0  0  0  0  0 11  0]
        [ 0  0  0  0  0  0  0 11  0  0]
        [ 0  0  0  0  0  0 11  0  0  0]
        [ 0  0  0  0  0 11  0  0  0  0]
        [ 0  0  0  0 11  0  0  0  0  0]
        [ 0  0  0  1 -5 -2 -1  1 -3  5]
        [ 0  0  1  0 -3  4  1  4 -3 -2]
        [ 0  1  0  0 -4  5 -3  3  5  3]
        [ 1  0  0  0 -2 -1  4  2  5  4]

    Relation of primal and dual bases::

        sage: B_primal=sage.crypto.gen_lattice(m=10, q=11, seed=42)
        sage: B_dual=sage.crypto.gen_lattice(m=10, q=11, seed=42, dual=True)
        sage: B_dual_alt=transpose(11*B_primal.inverse()).change_ring(ZZ)
        sage: B_dual_alt.hermite_form() == B_dual.hermite_form()
        True

    TESTS:

    Test some bad quotient polynomials::

        sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=cos(x))
        Traceback (most recent call last):
        ...
        TypeError: unable to convert cos(x) to an integer
        sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=x^23-1)
        Traceback (most recent call last):
        ...
        ValueError: ideal basis requires n = quotient.degree()
        sage: R.<u,v> = ZZ[]
        sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=u+v)
        Traceback (most recent call last):
        ...
        TypeError: quotient should be a univariate polynomial

    We are testing output format choices::

        sage: sage.crypto.gen_lattice(m=10, q=11, seed=42)
        [11  0  0  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0  0  0]
        [ 2  4  3  5  1  0  0  0  0  0]
        [ 1 -5 -4  2  0  1  0  0  0  0]
        [-4  3 -1  1  0  0  1  0  0  0]
        [-2 -3 -4 -1  0  0  0  1  0  0]
        [-5 -5  3  3  0  0  0  0  1  0]
        [-4 -3  2 -5  0  0  0  0  0  1]

        sage: sage.crypto.gen_lattice(m=10, q=11, seed=42, ntl=True)
        [
        [11 0 0 0 0 0 0 0 0 0]
        [0 11 0 0 0 0 0 0 0 0]
        [0 0 11 0 0 0 0 0 0 0]
        [0 0 0 11 0 0 0 0 0 0]
        [2 4 3 5 1 0 0 0 0 0]
        [1 -5 -4 2 0 1 0 0 0 0]
        [-4 3 -1 1 0 0 1 0 0 0]
        [-2 -3 -4 -1 0 0 0 1 0 0]
        [-5 -5 3 3 0 0 0 0 1 0]
        [-4 -3 2 -5 0 0 0 0 0 1]
        ]

        sage: sage.crypto.gen_lattice(m=10, q=11, seed=42, lattice=True)
        Free module of degree 10 and rank 10 over Integer Ring
        User basis matrix:
        [ 0  0  1  1  0 -1 -1 -1  1  0]
        [-1  1  0  1  0  1  1  0  1  1]
        [-1  0  0  0 -1  1  1 -2  0  0]
        [-1 -1  0  1  1  0  0  1  1 -1]
        [ 1  0 -1  0  0  0 -2 -2  0  0]
        [ 2 -1  0  0  1  0  1  0  0 -1]
        [-1  1 -1  0  1 -1  1  0 -1 -2]
        [ 0  0 -1  3  0  0  0 -1 -1 -1]
        [ 0 -1  0 -1  2  0 -1  0  0  2]
        [ 0  1  1  0  1  1 -2  1 -1 -2]

    REFERENCES:

    .. [A96] Miklos Ajtai.
      Generating hard instances of lattice problems (extended abstract).
      STOC, pp. 99--108, ACM, 1996.

    .. [GM02] Daniel Goldstein and Andrew Mayer.
      On the equidistribution of Hecke points.
      Forum Mathematicum, 15:2, pp. 165--189, De Gruyter, 2003.

    .. [LM06] Vadim Lyubashevsky and Daniele Micciancio.
      Generalized compact knapsacks are collision resistant.
      ICALP, pp. 144--155, Springer, 2006.

    .. [R05] Oded Regev.
      On lattices, learning with errors, random linear codes, and cryptography.
      STOC, pp. 84--93, ACM, 2005.
    """
    from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
    from sage.matrix.constructor import identity_matrix, block_matrix
    from sage.matrix.matrix_space import MatrixSpace
    from sage.rings.integer_ring import IntegerRing
    if seed is not None:
        from sage.misc.randstate import set_random_seed
        set_random_seed(seed)

    if type == 'random':
        if n != 1: raise ValueError('random bases require n = 1')

    ZZ = IntegerRing()
    ZZ_q = IntegerModRing(q)
    A = identity_matrix(ZZ_q, n)

    if type == 'random' or type == 'modular':
        R = MatrixSpace(ZZ_q, m-n, n)
        A = A.stack(R.random_element())

    elif type == 'ideal':
        if quotient is None:
            raise ValueError('ideal bases require a quotient polynomial')
        try:
            quotient = quotient.change_ring(ZZ_q)
        except (AttributeError, TypeError):
            quotient = quotient.polynomial(base_ring=ZZ_q)

        P = quotient.parent()
        # P should be a univariate polynomial ring over ZZ_q
        if not is_PolynomialRing(P):
            raise TypeError("quotient should be a univariate polynomial")
        assert P.base_ring() is ZZ_q

        if quotient.degree() != n:
            raise ValueError('ideal basis requires n = quotient.degree()')
        R = P.quotient(quotient)
        for i in range(m//n):
            A = A.stack(R.random_element().matrix())

    elif type == 'cyclotomic':
        from sage.arith.all import euler_phi
        from sage.misc.functional import cyclotomic_polynomial

        # we assume that n+1 <= min( euler_phi^{-1}(n) ) <= 2*n
        found = False
        for k in range(2*n,n,-1):
            if euler_phi(k) == n:
                found = True
                break
        if not found:
            raise ValueError("cyclotomic bases require that n "
                       "is an image of Euler's totient function")

        R = ZZ_q['x'].quotient(cyclotomic_polynomial(k, 'x'), 'x')
        for i in range(m//n):
            A = A.stack(R.random_element().matrix())

    # switch from representatives 0,...,(q-1) to (1-q)/2,....,(q-1)/2
    def minrep(a):
        if abs(a-q) < abs(a): return a-q
        else: return a
    A_prime = A[n:m].lift().apply_map(minrep)

    if not dual:
        B = block_matrix([[ZZ(q), ZZ.zero()], [A_prime, ZZ.one()] ],
                         subdivide=False)
    else:
        B = block_matrix([[ZZ.one(), -A_prime.transpose()],
            [ZZ.zero(), ZZ(q)]], subdivide=False)
        for i in range(m//2):
            B.swap_rows(i,m-i-1)

    if ntl and lattice:
        raise ValueError("Cannot specify ntl=True and lattice=True "
                         "at the same time")

    if ntl:
        return B._ntl_()
    elif lattice:
        from sage.modules.free_module_integer import IntegerLattice
        return IntegerLattice(B)
    else:
        return B
Example #8
0
def gen_lattice(type='modular', n=4, m=8, q=11, seed=None,
                quotient=None, dual=False, ntl=False, lattice=False):
    r"""
    This function generates different types of integral lattice bases
    of row vectors relevant in cryptography.

    Randomness can be set either with ``seed``, or by using
    :func:`sage.misc.randstate.set_random_seed`.

    INPUT:

    - ``type`` -- one of the following strings
        - ``'modular'`` (default) -- A class of lattices for which
          asymptotic worst-case to average-case connections hold. For
          more refer to [Aj1996]_.
        - ``'random'`` -- Special case of modular (n=1). A dense class
          of lattice used for testing basis reduction algorithms
          proposed by Goldstein and Mayer [GM2002]_.
        - ``'ideal'`` -- Special case of modular. Allows for a more
          compact representation proposed by [LM2006]_.
        - ``'cyclotomic'`` -- Special case of ideal. Allows for
          efficient processing proposed by [LM2006]_.
    - ``n`` -- Determinant size, primal:`det(L) = q^n`, dual:`det(L) = q^{m-n}`.
      For ideal lattices this is also the degree of the quotient polynomial.
    - ``m`` -- Lattice dimension, `L \subseteq Z^m`.
    - ``q`` -- Coefficient size, `q-Z^m \subseteq L`.
    - ``seed`` -- Randomness seed.
    - ``quotient`` -- For the type ideal, this determines the quotient
      polynomial. Ignored for all other types.
    - ``dual`` -- Set this flag if you want a basis for `q-dual(L)`, for example
      for Regev's LWE bases [Reg2005]_.
    - ``ntl`` -- Set this flag if you want the lattice basis in NTL readable
      format.
    - ``lattice`` -- Set this flag if you want a
      :class:`FreeModule_submodule_with_basis_integer` object instead
      of an integer matrix representing the basis.

    OUTPUT: ``B`` a unique size-reduced triangular (primal: lower_left,
      dual: lower_right) basis of row vectors for the lattice in question.

    EXAMPLES:

    Modular basis::

        sage: sage.crypto.gen_lattice(m=10, seed=42)
        [11  0  0  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0  0  0]
        [ 2  4  3  5  1  0  0  0  0  0]
        [ 1 -5 -4  2  0  1  0  0  0  0]
        [-4  3 -1  1  0  0  1  0  0  0]
        [-2 -3 -4 -1  0  0  0  1  0  0]
        [-5 -5  3  3  0  0  0  0  1  0]
        [-4 -3  2 -5  0  0  0  0  0  1]

    Random basis::

        sage: sage.crypto.gen_lattice(type='random', n=1, m=10, q=11^4, seed=42)
        [14641     0     0     0     0     0     0     0     0     0]
        [  431     1     0     0     0     0     0     0     0     0]
        [-4792     0     1     0     0     0     0     0     0     0]
        [ 1015     0     0     1     0     0     0     0     0     0]
        [-3086     0     0     0     1     0     0     0     0     0]
        [-5378     0     0     0     0     1     0     0     0     0]
        [ 4769     0     0     0     0     0     1     0     0     0]
        [-1159     0     0     0     0     0     0     1     0     0]
        [ 3082     0     0     0     0     0     0     0     1     0]
        [-4580     0     0     0     0     0     0     0     0     1]

    Ideal bases with quotient x^n-1, m=2*n are NTRU bases::

        sage: sage.crypto.gen_lattice(type='ideal', seed=42, quotient=x^4-1)
        [11  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0]
        [-2 -3 -3  4  1  0  0  0]
        [ 4 -2 -3 -3  0  1  0  0]
        [-3  4 -2 -3  0  0  1  0]
        [-3 -3  4 -2  0  0  0  1]

    Ideal bases also work with polynomials::

        sage: R.<t> = PolynomialRing(ZZ)
        sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=t^4-1)
        [11  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0]
        [ 1  4 -3  3  1  0  0  0]
        [ 3  1  4 -3  0  1  0  0]
        [-3  3  1  4  0  0  1  0]
        [ 4 -3  3  1  0  0  0  1]

    Cyclotomic bases with n=2^k are SWIFFT bases::

        sage: sage.crypto.gen_lattice(type='cyclotomic', seed=42)
        [11  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0]
        [-2 -3 -3  4  1  0  0  0]
        [-4 -2 -3 -3  0  1  0  0]
        [ 3 -4 -2 -3  0  0  1  0]
        [ 3  3 -4 -2  0  0  0  1]

    Dual modular bases are related to Regev's famous public-key
    encryption [Reg2005]_::

        sage: sage.crypto.gen_lattice(type='modular', m=10, seed=42, dual=True)
        [ 0  0  0  0  0  0  0  0  0 11]
        [ 0  0  0  0  0  0  0  0 11  0]
        [ 0  0  0  0  0  0  0 11  0  0]
        [ 0  0  0  0  0  0 11  0  0  0]
        [ 0  0  0  0  0 11  0  0  0  0]
        [ 0  0  0  0 11  0  0  0  0  0]
        [ 0  0  0  1 -5 -2 -1  1 -3  5]
        [ 0  0  1  0 -3  4  1  4 -3 -2]
        [ 0  1  0  0 -4  5 -3  3  5  3]
        [ 1  0  0  0 -2 -1  4  2  5  4]

    Relation of primal and dual bases::

        sage: B_primal=sage.crypto.gen_lattice(m=10, q=11, seed=42)
        sage: B_dual=sage.crypto.gen_lattice(m=10, q=11, seed=42, dual=True)
        sage: B_dual_alt=transpose(11*B_primal.inverse()).change_ring(ZZ)
        sage: B_dual_alt.hermite_form() == B_dual.hermite_form()
        True

    TESTS:

    Test some bad quotient polynomials::

        sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=cos(x))
        Traceback (most recent call last):
        ...
        TypeError: unable to convert cos(x) to an integer
        sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=x^23-1)
        Traceback (most recent call last):
        ...
        ValueError: ideal basis requires n = quotient.degree()
        sage: R.<u,v> = ZZ[]
        sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=u+v)
        Traceback (most recent call last):
        ...
        TypeError: quotient should be a univariate polynomial

    We are testing output format choices::

        sage: sage.crypto.gen_lattice(m=10, q=11, seed=42)
        [11  0  0  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0  0  0]
        [ 2  4  3  5  1  0  0  0  0  0]
        [ 1 -5 -4  2  0  1  0  0  0  0]
        [-4  3 -1  1  0  0  1  0  0  0]
        [-2 -3 -4 -1  0  0  0  1  0  0]
        [-5 -5  3  3  0  0  0  0  1  0]
        [-4 -3  2 -5  0  0  0  0  0  1]

        sage: sage.crypto.gen_lattice(m=10, q=11, seed=42, ntl=True)
        [
        [11 0 0 0 0 0 0 0 0 0]
        [0 11 0 0 0 0 0 0 0 0]
        [0 0 11 0 0 0 0 0 0 0]
        [0 0 0 11 0 0 0 0 0 0]
        [2 4 3 5 1 0 0 0 0 0]
        [1 -5 -4 2 0 1 0 0 0 0]
        [-4 3 -1 1 0 0 1 0 0 0]
        [-2 -3 -4 -1 0 0 0 1 0 0]
        [-5 -5 3 3 0 0 0 0 1 0]
        [-4 -3 2 -5 0 0 0 0 0 1]
        ]

        sage: sage.crypto.gen_lattice(m=10, q=11, seed=42, lattice=True)
        Free module of degree 10 and rank 10 over Integer Ring
        User basis matrix:
        [ 0  0  1  1  0 -1 -1 -1  1  0]
        [-1  1  0  1  0  1  1  0  1  1]
        [-1  0  0  0 -1  1  1 -2  0  0]
        [-1 -1  0  1  1  0  0  1  1 -1]
        [ 1  0 -1  0  0  0 -2 -2  0  0]
        [ 2 -1  0  0  1  0  1  0  0 -1]
        [-1  1 -1  0  1 -1  1  0 -1 -2]
        [ 0  0 -1  3  0  0  0 -1 -1 -1]
        [ 0 -1  0 -1  2  0 -1  0  0  2]
        [ 0  1  1  0  1  1 -2  1 -1 -2]
    """
    from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
    from sage.matrix.constructor import identity_matrix, block_matrix
    from sage.matrix.matrix_space import MatrixSpace
    from sage.rings.integer_ring import IntegerRing
    if seed is not None:
        from sage.misc.randstate import set_random_seed
        set_random_seed(seed)

    if type == 'random':
        if n != 1: raise ValueError('random bases require n = 1')

    ZZ = IntegerRing()
    ZZ_q = IntegerModRing(q)
    A = identity_matrix(ZZ_q, n)

    if type == 'random' or type == 'modular':
        R = MatrixSpace(ZZ_q, m-n, n)
        A = A.stack(R.random_element())

    elif type == 'ideal':
        if quotient is None:
            raise ValueError('ideal bases require a quotient polynomial')
        try:
            quotient = quotient.change_ring(ZZ_q)
        except (AttributeError, TypeError):
            quotient = quotient.polynomial(base_ring=ZZ_q)

        P = quotient.parent()
        # P should be a univariate polynomial ring over ZZ_q
        if not is_PolynomialRing(P):
            raise TypeError("quotient should be a univariate polynomial")
        assert P.base_ring() is ZZ_q

        if quotient.degree() != n:
            raise ValueError('ideal basis requires n = quotient.degree()')
        R = P.quotient(quotient)
        for i in range(m//n):
            A = A.stack(R.random_element().matrix())

    elif type == 'cyclotomic':
        from sage.arith.all import euler_phi
        from sage.misc.functional import cyclotomic_polynomial

        # we assume that n+1 <= min( euler_phi^{-1}(n) ) <= 2*n
        found = False
        for k in range(2*n,n,-1):
            if euler_phi(k) == n:
                found = True
                break
        if not found:
            raise ValueError("cyclotomic bases require that n "
                       "is an image of Euler's totient function")

        R = ZZ_q['x'].quotient(cyclotomic_polynomial(k, 'x'), 'x')
        for i in range(m//n):
            A = A.stack(R.random_element().matrix())

    # switch from representatives 0,...,(q-1) to (1-q)/2,....,(q-1)/2
    def minrep(a):
        if abs(a-q) < abs(a): return a-q
        else: return a
    A_prime = A[n:m].lift().apply_map(minrep)

    if not dual:
        B = block_matrix([[ZZ(q), ZZ.zero()], [A_prime, ZZ.one()] ],
                         subdivide=False)
    else:
        B = block_matrix([[ZZ.one(), -A_prime.transpose()],
            [ZZ.zero(), ZZ(q)]], subdivide=False)
        for i in range(m//2):
            B.swap_rows(i,m-i-1)

    if ntl and lattice:
        raise ValueError("Cannot specify ntl=True and lattice=True "
                         "at the same time")

    if ntl:
        return B._ntl_()
    elif lattice:
        from sage.modules.free_module_integer import IntegerLattice
        return IntegerLattice(B)
    else:
        return B
Example #9
0
def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, \
                quotient=None, dual=False, ntl=False):
    """
    This function generates different types of integral lattice bases
    of row vectors relevant in cryptography.

    Randomness can be set either with ``seed``, or by using
    :func:`sage.misc.randstate.set_random_seed`.

    INPUT:

    * ``type`` - one of the following strings
        * ``'modular'`` (default). A class of lattices for which
          asymptotic worst-case to average-case connections hold. For
          more refer to [A96]_.
        * ``'random'`` - Special case of modular (n=1). A dense class
          of lattice used for testing basis reduction algorithms
          proposed by Goldstein and Mayer [GM02]_.
        * ``'ideal'`` - Special case of modular. Allows for a more
          compact representation proposed by [LM06]_.
        * ``'cyclotomic'`` - Special case of ideal. Allows for
          efficient processing proposed by [LM06]_.
    * ``n`` - Determinant size, primal:`det(L) = q^n`, dual:`det(L) = q^{m-n}`.
      For ideal lattices this is also the degree of the quotient polynomial.
    * ``m`` - Lattice dimension, `L \subseteq Z^m`.
    * ``q`` - Coefficent size, `q*Z^m \subseteq L`.
    * ``seed`` - Randomness seed.
    * ``quotient`` - For the type ideal, this determines the quotient
      polynomial. Ignored for all other types.
    * ``dual`` - Set this flag if you want a basis for `q*dual(L)`, for example
      for Regev's LWE bases [R05]_.
    * ``ntl`` - Set this flag if you want the lattice basis in NTL readable
      format.

    OUTPUT: ``B`` a unique size-reduced triangular (primal: lower_left, 
      dual: lower_right) basis of row vectors for the lattice in question.

    EXAMPLES:

    * Modular basis ::

        sage: sage.crypto.gen_lattice(m=10, seed=42)
        [11  0  0  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0  0  0]
        [ 2  4  3  5  1  0  0  0  0  0]
        [ 1 -5 -4  2  0  1  0  0  0  0]
        [-4  3 -1  1  0  0  1  0  0  0]
        [-2 -3 -4 -1  0  0  0  1  0  0]
        [-5 -5  3  3  0  0  0  0  1  0]
        [-4 -3  2 -5  0  0  0  0  0  1]

    * Random basis ::

        sage: sage.crypto.gen_lattice(type='random', n=1, m=10, q=11^4, seed=42)
        [14641     0     0     0     0     0     0     0     0     0]
        [  431     1     0     0     0     0     0     0     0     0]
        [-4792     0     1     0     0     0     0     0     0     0]
        [ 1015     0     0     1     0     0     0     0     0     0]
        [-3086     0     0     0     1     0     0     0     0     0]
        [-5378     0     0     0     0     1     0     0     0     0]
        [ 4769     0     0     0     0     0     1     0     0     0]
        [-1159     0     0     0     0     0     0     1     0     0]
        [ 3082     0     0     0     0     0     0     0     1     0]
        [-4580     0     0     0     0     0     0     0     0     1]

    * Ideal bases with quotient x^n-1, m=2*n are NTRU bases ::

        sage: sage.crypto.gen_lattice(type='ideal', seed=42, quotient=x^4-1)
        [11  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0]
        [ 4 -2 -3 -3  1  0  0  0]
        [-3  4 -2 -3  0  1  0  0]
        [-3 -3  4 -2  0  0  1  0]
        [-2 -3 -3  4  0  0  0  1]

    * Cyclotomic bases with n=2^k are SWIFFT bases ::

        sage: sage.crypto.gen_lattice(type='cyclotomic', seed=42)
        [11  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0]
        [ 4 -2 -3 -3  1  0  0  0]
        [ 3  4 -2 -3  0  1  0  0]
        [ 3  3  4 -2  0  0  1  0]
        [ 2  3  3  4  0  0  0  1]

    * Dual modular bases are related to Regev's famous public-key
      encryption [R05]_ ::

        sage: sage.crypto.gen_lattice(type='modular', m=10, seed=42, dual=True)
        [ 0  0  0  0  0  0  0  0  0 11]
        [ 0  0  0  0  0  0  0  0 11  0]
        [ 0  0  0  0  0  0  0 11  0  0]
        [ 0  0  0  0  0  0 11  0  0  0]
        [ 0  0  0  0  0 11  0  0  0  0]
        [ 0  0  0  0 11  0  0  0  0  0]
        [ 0  0  0  1 -5 -2 -1  1 -3  5]
        [ 0  0  1  0 -3  4  1  4 -3 -2]
        [ 0  1  0  0 -4  5 -3  3  5  3]
        [ 1  0  0  0 -2 -1  4  2  5  4]

    * Relation of primal and dual bases ::

        sage: B_primal=sage.crypto.gen_lattice(m=10, q=11, seed=42)
        sage: B_dual=sage.crypto.gen_lattice(m=10, q=11, seed=42, dual=True)
        sage: B_dual_alt=transpose(11*B_primal.inverse()).change_ring(ZZ)
        sage: B_dual_alt.hermite_form() == B_dual.hermite_form()
        True

    REFERENCES:

.. [A96] Miklos Ajtai.
   Generating hard instances of lattice problems (extended abstract).
   STOC, pp. 99--108, ACM, 1996.

.. [GM02] Daniel Goldstein and Andrew Mayer.
   On the equidistribution of Hecke points.
   Forum Mathematicum, 15:2, pp. 165--189, De Gruyter, 2003.

.. [LM06] Vadim Lyubashevsky and Daniele Micciancio.
   Generalized compact knapsacks are collision resistant.
   ICALP, pp. 144--155, Springer, 2006.

.. [R05] Oded Regev.
   On lattices, learning with errors, random linear codes, and cryptography.
   STOC, pp. 84--93, ACM, 2005.
    """
    from sage.rings.finite_rings.integer_mod_ring \
        import IntegerModRing
    from sage.matrix.constructor import matrix, \
        identity_matrix, block_matrix
    from sage.matrix.matrix_space import MatrixSpace
    from sage.rings.integer_ring import IntegerRing
    if seed != None:
        from sage.misc.randstate import set_random_seed
        set_random_seed(seed)

    if type == 'random':
        if n != 1: raise ValueError('random bases require n = 1')

    ZZ = IntegerRing()
    ZZ_q = IntegerModRing(q)
    A = identity_matrix(ZZ_q, n)

    if type == 'random' or type == 'modular':
        R = MatrixSpace(ZZ_q, m-n, n)
        A = A.stack(R.random_element())

    elif type == 'ideal':
        if quotient == None: raise \
            ValueError('ideal bases require a quotient polynomial')
        x = quotient.default_variable()
        if n != quotient.degree(x): raise \
            ValueError('ideal bases require n  = quotient.degree()')
        R = ZZ_q[x].quotient(quotient, x)
        for i in range(m//n):
            A = A.stack(R.random_element().matrix())

    elif type == 'cyclotomic':
        from sage.rings.arith import euler_phi
        from sage.misc.functional import cyclotomic_polynomial

        # we assume that n+1 <= min( euler_phi^{-1}(n) ) <= 2*n
        found = False
        for k in range(2*n,n,-1):
            if euler_phi(k) == n:
                found = True
                break
        if not found: raise \
            ValueError('cyclotomic bases require that n is an image of' + \
                       'Euler\'s totient function')

        R = ZZ_q['x'].quotient(cyclotomic_polynomial(k, 'x'), 'x')
        for i in range(m//n):
            A = A.stack(R.random_element().matrix())

    # switch from representatives 0,...,(q-1) to (1-q)/2,....,(q-1)/2
    def minrep(a):
        if abs(a-q) < abs(a): return a-q
        else: return a
    A_prime = A[n:m].lift().apply_map(minrep)

    if not dual:
        B = block_matrix([[ZZ(q), ZZ.zero()], [A_prime, ZZ.one()] ], \
                         subdivide=False)
    else:
        B = block_matrix([[ZZ.one(), -A_prime.transpose()], [ZZ.zero(), \
                         ZZ(q)]], subdivide=False)
        for i in range(m//2): B.swap_rows(i,m-i-1)

    if not ntl:
        return B
    else:
        return B._ntl_()
Example #10
0
 def run_one_test(self, test, compileflags, out):
     if self._reset_random_seed:
         randstate.set_random_seed(long(0))
     OrigDocTestRunner.run_one_test(self, test, compileflags, out)
Example #11
0
def linear_elimination(self, filename='', limit=10, seed=0, step=2):
    """
    Recursively subsitutes linear variables in the DeforSys

    using find_linear_equation search for a suitable variable
    then apply linear_simplify_sys_one_step

    limit is an int which specify the maximal number of steps. By default 10
    
    step is the maximal acceptable jump in degree when performing one step

    Returns a DeforSystem
    """
    log = False
    if filename != '':
        try:
            logfile = open(filename, 'w')
            log = True
        except IOError:
            print """
############## Attention ################
      The log file is not valid
#########################################
                    """

    [eqs_ori, ineqs_ori, proj_ori] = [self.eqs, self.ineqs, self.proj]
    sys_treated = []

    compteur = 0  #Pour donner des infos
    set_random_seed(seed)  # pour la reproductibilité
    while (compteur < limit):
        compteur += 1

        #Feedback
        print "Etape %i" % compteur
        print "    Le degré est %i" % max(pol.degree() for pol in self.eqs)
        print "    Le nombre d'équations est %i" % len(self.eqs)

        if log:
            logfile.write("""
Step %i
            
    The degree is %i.
    The number of equations is %i
                
            """ % (compteur, max(pol.degree()
                                 for pol in self.eqs), len(self.eqs)))

        #We search a linear substitution
        fle = self._find_lin_eq(step=step)

        if fle[1] == -1:  # If none, we are done

            #Feedback
            print "No possibilities without augmenting the degree"

            if log:
                logfile.write("""
    No further possible substitutions without augmenting
    too much the degree
                    
                """)
            break  #We exit the while loop

        else:  # if there is a substitution, we apply it.

            self._linear_elim_step(fle)

            #Logging
            if log:
                #Details in another file
                with open(filename + "_subs_%i" % compteur, 'w') as sublogfile:
                    sublogfile.write("""
#substituted variable
%s
                    
#Polynomial used
%s
                    """ % (fle[1], fle[0]))
                #We advert this in the main file
                logfile.write("""
    We made a substitution, see file %s
                
                """ % (filename + "_subs_%i" % compteur))

        #Feedback
        new_deg = max(pol.degree() for pol in self.eqs)
        new_number = len(self.eqs)
        print "Fin de l'étape %i" % compteur
        print "    Le degré est %i" % new_deg
        print "    Le nombre d'équations est %i" % new_number
        print ""

        if log:
            logfile.write("""
Fin de l'étape %i
    Le degré est %i
    Le nombre d'équations est %i

            """ % (compteur, new_deg, new_number))

    #At the end, we close the log file
    if log:
        logfile.close()
Example #12
0
 def run_one_test(self, test, compileflags, out):
     if self._reset_random_seed:
         randstate.set_random_seed(long(0))
     OrigDocTestRunner.run_one_test(self, test, compileflags, out)
Example #13
0
        [ 0  0  0  1 -5 -2 -1  1 -3  5]
        [ 0  0  1  0 -3  4  1  4 -3 -2]
        [ 0  1  0  0 -4  5 -3  3  5  3]
        [ 1  0  0  0 -2 -1  4  2  5  4]
 
 
    """
    from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
    from sage.matrix.constructor import identity_matrix, block_matrix
    from sage.matrix.matrix_space import MatrixSpace
    from sage.rings.integer_ring import IntegerRing
    from sage.modules.free_module_integer import IntegerLattice
       
    if seed is not None:
        from sage.misc.randstate import set_random_seed
        set_random_seed(seed)
 
 
    m=n+1
    ZZ = IntegerRing()
    ZZ_q = IntegerModRing(q)
 
 
 
    from sage.arith.all import euler_phi
    from sage.misc.functional import cyclotomic_polynomial
 
    # we assume that n+1 <= min( euler_phi^{-1}(n) ) <= 2*n
    found = False
    for k in range(2*n,n,-1):
        if euler_phi(k) == n:
Example #14
0
def my_gen_lattice2(n=4, q=11, seed=None,
                quotient=None, dual=False, ntl=False, lattice=False, GuessStuff=True):
    """
    This is a modification of the code for the gen_lattice function from Sage
 
    Randomness can be set either with ``seed``, or by using
    :func:`sage.misc.randstate.set_random_seed`.
 
    INPUT:
 
    - ``type`` -- one of the following strings
        - ``'cyclotomic'`` -- Special case of ideal. Allows for
          efficient processing proposed by [LM2006]_.
    - ``n`` -- Determinant size, primal:`det(L) = q^n`, dual:`det(L) = q^{m-n}`.
      For ideal lattices this is also the degree of the quotient polynomial.
    - ``m`` -- Lattice dimension, `L \subseteq Z^m`.
    - ``q`` -- Coefficient size, `q-Z^m \subseteq L`.
    - ``t`` -- BKZ Block Size
    - ``seed`` -- Randomness seed.
    - ``quotient`` -- For the type ideal, this determines the quotient
      polynomial. Ignored for all other types.
    - ``dual`` -- Set this flag if you want a basis for `q-dual(L)`, for example
      for Regev's LWE bases [Reg2005]_.
    - ``ntl`` -- Set this flag if you want the lattice basis in NTL readable
      format.
    - ``lattice`` -- Set this flag if you want a
      :class:`FreeModule_submodule_with_basis_integer` object instead
      of an integer matrix representing the basis.
 
    OUTPUT: ``B`` a unique size-reduced triangular (primal: lower_left,
      dual: lower_right) basis of row vectors for the lattice in question.
 
    EXAMPLES:
 
 
 
    Cyclotomic bases with n=2^k are SWIFFT bases::
 
        sage: sage.crypto.gen_lattice(type='cyclotomic', seed=42)
        [11  0  0  0  0  0  0  0]
        [ 0 11  0  0  0  0  0  0]
        [ 0  0 11  0  0  0  0  0]
        [ 0  0  0 11  0  0  0  0]
        [ 4 -2 -3 -3  1  0  0  0]
        [ 3  4 -2 -3  0  1  0  0]
        [ 3  3  4 -2  0  0  1  0]
        [ 2  3  3  4  0  0  0  1]
 
    Dual modular bases are related to Regev's famous public-key
    encryption [Reg2005]_::
 
        sage: sage.crypto.gen_lattice(type='modular', m=10, seed=42, dual=True)
        [ 0  0  0  0  0  0  0  0  0 11]
        [ 0  0  0  0  0  0  0  0 11  0]
        [ 0  0  0  0  0  0  0 11  0  0]
        [ 0  0  0  0  0  0 11  0  0  0]
        [ 0  0  0  0  0 11  0  0  0  0]
        [ 0  0  0  0 11  0  0  0  0  0]
        [ 0  0  0  1 -5 -2 -1  1 -3  5]
        [ 0  0  1  0 -3  4  1  4 -3 -2]
        [ 0  1  0  0 -4  5 -3  3  5  3]
        [ 1  0  0  0 -2 -1  4  2  5  4]
 
 
    """
    from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
    from sage.matrix.constructor import identity_matrix, block_matrix
    from sage.matrix.matrix_space import MatrixSpace
    from sage.rings.integer_ring import IntegerRing
    from sage.modules.free_module_integer import IntegerLattice
       
    if seed is not None:
        from sage.misc.randstate import set_random_seed
        set_random_seed(seed)
 
 
    m=n+1
    ZZ = IntegerRing()
    ZZ_q = IntegerModRing(q)
 
 
 
    from sage.arith.all import euler_phi
    from sage.misc.functional import cyclotomic_polynomial
 
    # we assume that n+1 <= min( euler_phi^{-1}(n) ) <= 2*n
    found = False
    for k in range(2*n,n,-1):
        if euler_phi(k) == n:
            found = True
            break
        if not found:
            raise ValueError("cyclotomic bases require that n "
                                 "is an image of Euler's totient function")
    R = ZZ_q['x'].quotient(cyclotomic_polynomial(2*n, 'x'), 'x')
    g=x**(n/2)+1
    T=ZZ_q['x'].quotient(x**(n/2)+1)
 
   
    a_pol=R.random_element()

    s_pol=sample_noise(R)
    e_pol=sample_noise(R)
 
    s_pol2=T((s_pol))
    e_pol2=T((e_pol))
    print("s={0},e={1}".format(T(s_pol),T(e_pol)))

    
    Z_mat=e_pol2.matrix().augment(s_pol2.matrix())
    Z_mattop=Z_mat[0:1].augment(matrix(1,1,[ZZ.one()*-1]))
  
  
    b_pol=(a_pol*s_pol+e_pol)
    print("s_pol={0}\ne_pol={1}".format((s_pol2).list(),(e_pol2).list()))
    # Does a linear mapping change the shortest vector size for the rest?/
    a_pol=a_pol#*x_pol
    b_pol=b_pol#*x_pol

    a_pol2 = T(a_pol.list())# % S(g.list())
    b_pol2 = T((b_pol).list())# % S(g.list())
#    print("a={0}\nb={1}".format(a_pol2,b_pol2))
    A=identity_matrix(ZZ_q,n/2)
    A=A.stack(a_pol2.matrix())
    
    
    b_prime=b_pol2.matrix()[0:1]
    b_prime=b_prime - 11*A[8:9]
    A=A.stack(b_pol2.matrix()[0:1])

    
    
#    print("X=\n{0}".format(X))

#    A = A.stack(identity_matrix(ZZ_q, n/2))
 
    print("A=\n{0}\n".format(A))
    # switch from representatives 0,...,(q-1) to (1-q)/2,....,(q-1)/2
    def minrepnegative(a):
        if abs(a-q) < abs(a): return (a-q)*-1
        else: return a*-1
    def minrep(a):
        if abs(a-q) < abs(a): return (a-q)
        else: return a
    A_prime = A[(n/2):(n+1)].lift().apply_map(minrep)
#    b_neg= A[(n):(n+1)].lift().apply_map(minrepnegative)
    Z_fixed=Z_mattop.lift().apply_map(minrep)
    print("Z_fixed={0}\n||Z_fixed||={1}".format(Z_fixed,float(Z_fixed[0].norm())))
    print('Z_fixed*A={0}\n\n'.format(Z_fixed*A))

    print("z_fixed[0].norm()={0}".format(float(Z_fixed[0].norm())))
#    B=block_matrix([[ZZ(q),ZZ.zero()],[A_neg,ZZ.one()]], subdivide=False)
#    B = block_matrix([[ZZ.one(), -A_prime.transpose()],
#                     [ZZ.zero(), ZZ(q)]], subdivide=False)
    B = block_matrix([[ZZ(q), ZZ.zero()], [-A_prime, ZZ.one()]], subdivide=False)
#    for i in range(m//2):
#        B.swap_rows(i,m-i-1)
    #    print("{0}\n".format(A_neg))
 #   B=block_matrix([[ZZ(q), ZZ.zero(),ZZ.zero()],[ZZ.one(),A_neg,ZZ.zero() ],[ZZ.zero(),b_neg,ZZ.one()]],
                     #  subdivide=False)
    #print("B=\n{0}".format(B))
    print("B*A=\n{0}\n\n".format(B*A))
    #print("A=\n{0}\n".format(A))
    def remap(x):
        return minrep((x*251)%251)
    BL=B.BKZ(block_size=n/2.)
    y=(BL.solve_left(Z_fixed))#.apply_map(remap))

#   print("y*B={0}".format(y*B))
    print("y:=B.solve_left(Z_fixed)={0}".format(y))
#    BL=B.BKZ(block_size=n/2.)
    print(BL[0])
    print("shortest norm={0}".format(float(BL[0].norm())))
#    L = IntegerLattice(B)
#    p
#    v=L.shortest_vector()
#    print("L.shortest_vector={0}, norm={1}".format(v,float(v.norm())))
    if ntl and lattice:
        raise ValueError("Cannot specify ntl=True and lattice=True ")
    if ntl:
        return B._ntl_()
    elif lattice:
        from sage.modules.free_module_integer import IntegerLattice
        return IntegerLattice(B)
    else:
        return B