예제 #1
0
def extract_basis(v, N):
    """Returns a subset of v such that the span of these elements is at
    least as big as v. In particular, if v is a vector space, it returns a
    base.

    """
    dim = rank_of_vector_set(v, N)
    i = 0
    basis = []
    while i < len(v) and v[i] == 0:
        i += 1
    if i == len(v):
        return []
    basis.append(v[i])
    if dim == 1:
        return basis
    i += 1
    r = Matrix(GF(2), 1, N, [tobin(x, N) for x in basis]).rank()
    while r < dim and i < len(v):
        new_basis = basis + [v[i]]
        new_r = Matrix(GF(2), len(new_basis), N,
                       [tobin(x, N) for x in new_basis]).rank()
        if new_r == dim:
            return new_basis
        elif new_r > r:
            basis = new_basis
            r = new_r
        i += 1
    return []
예제 #2
0
def poly_to_set(E, v):
    q = E.base_field().order()
    deg = v.degree()
    e = 1
    R = PolynomialRing(GF(q), 'x')
    f = R(v)
    roots = f.roots()
    while len(roots) != deg:
        e += 1
        s = q**e
        R = PolynomialRing(GF(s), 'x')
        f = R(v)
        roots = f.roots()
    roots = [r[0] for r in roots]
    ext_E = extend_field(E, e)

    ee = 1
    while True:
        Y = False
        for c in roots:
            if not ext_E.is_x_coord(c):
                Y = True
                break

        if Y:
            ee += 1
            s = ee * e
            R = PolynomialRing(GF(q**(s)), 'x')
            f = R(v)
            roots = [r[0] for r in f.roots()]
            ext_E = extend_field(E, s)
        else:
            break

    return roots, ext_E
예제 #3
0
    def encap(cls, pk, seed=None):
        """IND-CCA encapsulation sans compression or extra hash

        :param cls: Kyber class, inherit and change constants to change defaults
        :param pk: public key
        :param seed: seed used for random sampling if provided

        .. note :: Resembles Algorithm 4 of the Kyber paper.

        """
        n = cls.n

        if seed is not None:
            set_random_seed(seed)

        m = random_vector(GF(2), n)
        m.set_immutable()
        set_random_seed(hash(m))  # NOTE: this is obviously not faithful

        K_ = random_vector(GF(2), n)
        K_.set_immutable()
        r = ZZ.random_element(0, 2**n-1)

        c = cls.enc(pk, m, r)

        K = hash((K_, c))  # NOTE: this obviously isn't a cryptographic hash
        return c, K
예제 #4
0
def tu_decomposition(s, v, verbose=False):
    """Using the knowledge that v is a subspace of Z_s of dimension n, a
    TU-decomposition (as defined in [Perrin17]) of s is performed and T
    and U are returned.

    """
    N = int(log(len(s), 2))
    # building B
    basis = extract_basis(v[0], N)
    t = len(basis)
    basis = complete_basis(basis, N)
    B = Matrix(GF(2), N, N, [tobin(x, N) for x in reversed(basis)])
    if verbose:
        print "B=  (rank={})\n{}".format(B.rank(), B.str())
    # building A
    basis = complete_basis(extract_basis(v[1], N), N)
    A = Matrix(GF(2), N, N, [tobin(x, N) for x in reversed(basis)])
    if verbose:
        print "A=  (rank={})\n{}".format(A.rank(), A.str())
    # building linear equivalent s_prime
    s_prime = [
        apply_bin_mat(s[apply_bin_mat(x, A.inverse())], B)
        for x in xrange(0, 2**N)
    ]
    # TU decomposition of s'
    T, U = get_tu_open(s_prime, t)
    if verbose:
        print "T=["
        for i in xrange(0, 2**(N - t)):
            print "  {} {}".format(T[i], is_permutation(T[i]))
        print "]\nU=["
        for i in xrange(0, 2**t):
            print "  {} {}".format(U[i], is_permutation(U[i]))
        print "]"
    return T, U
예제 #5
0
    def test_diagonal_locations(self):
        # tests the helper function `diagonal_locations` which identifies where
        # the diagonal elements or blocks occur in the H matrix
        H = Matrix(GF(2), [[0, 0, 0], [0, 0, 0], [0, 0, 0]])
        index_one, index_B = diagonal_locations(H)
        self.assertEqual(index_one, 3)
        self.assertEqual(index_B, -1)

        H = Matrix(GF(2), [[1, 0, 0], [0, 0, 0], [0, 0, 0]])
        index_one, index_B = diagonal_locations(H)
        self.assertEqual(index_one, 0)
        self.assertEqual(index_B, -1)

        H = Matrix(GF(2), [[0, 1, 0], [1, 0, 0], [0, 0, 0]])
        index_one, index_B = diagonal_locations(H)
        self.assertEqual(index_one, 3)
        self.assertEqual(index_B, 0)

        H = Matrix(GF(2), [[0, 1, 0], [1, 0, 0], [0, 0, 1]])
        index_one, index_B = diagonal_locations(H)
        self.assertEqual(index_one, 2)
        self.assertEqual(index_B, 0)

        H = Matrix(GF(2), [[1, 0, 0], [0, 0, 1], [0, 1, 0]])
        index_one, index_B = diagonal_locations(H)
        self.assertEqual(index_one, 0)
        self.assertEqual(index_B, 1)
예제 #6
0
파일: main.py 프로젝트: staalezh/curves
    def make_base_field(self):
        if self.args.base_field != None:
            F = GF(self.args.base_field, 'F')
            self.field_traits.check(F)
            return F

        p = next_prime(2**self.args.num_bits)
        while not self.field_traits.check(GF(p, 'F'), nothrow=True):
            p = next_prime(p)

        return GF(p, 'F')
예제 #7
0
def attack(p, x1, y1, x2, y2):
    """
    Recovers the a and b parameters from an elliptic curve when two points are known.
    :param p: the prime of the curve base ring
    :param x1: the x coordinate of the first point
    :param y1: the y coordinate of the first point
    :param x2: the x coordinate of the second point
    :param y2: the y coordinate of the second point
    :return: a tuple containing the a and b parameters of the elliptic curve
    """
    m = Matrix(GF(p), [[x1, 1], [x2, 1]])
    v = vector(GF(p), [y1**2 - x1**3, y2**2 - x2**3])
    a, b = m.solve_right(v)
    return int(a), int(b)
예제 #8
0
def test_skipper_cpa_enc(skipper=Skipper4, kyber=Kyber, t=128, l=None, exhaustive=False):
    if not exhaustive:
        for i in range(t):
            pk, sk = kyber.key_gen(seed=i)
            m0 = random_vector(GF(2), kyber.n)
            c = skipper.enc(kyber, pk, m0, seed=i, l=l)
            m1 = kyber.dec(sk, c)
            assert(m0 == m1)
    else:
        # exhaustive test
        for i in range(16):
            pk, sk = kyber.key_gen(seed=i)
            for m0 in FreeModule(GF(2), kyber.n):
                c = skipper.enc(kyber, pk, m0, seed=i, l=l)
                m1 = kyber.dec(sk, c)
                assert(m0 == m1)
예제 #9
0
def irreps(p, q):
    """
    Returns the irreducible representations of the cyclic group C_p
    over the field F_q, where p and q are distinct primes.

    Each representation is given by a matrix over F_q giving the
    action of the preferred generator of C_p.

       sage: [M.nrows() for M in irreps(3, 7)]
       [1, 1, 1]
       sage: [M.nrows() for M in irreps(7, 11)]
       [1, 3, 3]
       sage: sum(M.nrows() for M in irreps(157, 13))
       157
    """
    p, q = ZZ(p), ZZ(q)
    assert p.is_prime() and q.is_prime() and p != q
    R = PolynomialRing(GF(q), 'x')
    x = R.gen()
    polys = [f for f, e in (x**p - 1).factor()]
    polys.sort(key=lambda f: (f.degree(), -f.constant_coefficient()))
    reps = [poly_to_rep(f) for f in polys]
    assert all(A**p == 1 for A in reps)
    assert reps[0] == 1
    return reps
예제 #10
0
파일: ccz.py 프로젝트: adelapie/sboxU
def delta_rank(f):
    """Returns the Gamma-rank of the function with LUT f.

    The Gamma-rank is the rank of the 2^{2n} \times 2^{2n} binary
    matrix M defined by

    M[x][y] = 1 if and only if x + y \in \Delta,

    where \Delta is defined as

    \Delta = \{ (a, b), DDT_f[a][b] == 2  \} ~.

    """
    n = int(log(len(f), 2))
    dim = 2**(2 * n)
    d = ddt(f)
    gamma = [(a << n) | b
             for a, b in itertools.product(xrange(1, 2**n), xrange(0, 2**n))
             if d[a][b] == 2]
    mat_content = []
    for x in xrange(0, dim):
        row = [0 for j in xrange(0, dim)]
        for y in gamma:
            row[oplus(x, y)] = 1
        mat_content.append(row)
    mat_gf2 = Matrix(GF(2), dim, dim, mat_content)
    return mat_gf2.rank()
예제 #11
0
파일: analyse.py 프로젝트: unjambonakap/ctf
def try_solve(lst):
  from sage.all import GF, MatrixSpace, VectorSpace, matrix
  A = []
  B = []
  NK = 32

  R = GF(2)
  for uu in lst:
    A.append(bin2vec(uu[0], NK))
    B.append(bin2vec(uu[1], NK))

  A = matrix(R, A)
  print('rank is >> ', A.rank())
  B = matrix(R, B)
  try:
    X = A.solve_right(B)
  except:
    return 0
  print(A.str())
  print()
  print(B.str())
  print()
  print(X)
  print()
  print((A * X - B).str())
  print()
  return 1
def make_reductions(nf, ell, verbose=False):
    """Input: A newform nf and a prime ell

    Output: a list of all the associated reducton maps

    Method: depends on the Hecke field.  Trivial if it is QQ,
    otherwise construct the Hecke order's ZZ-basis (betas) depending
    on the type of basis stored in the newform.

    """
    K = nf.hecke_field
    if verbose:
        print("Making reduction mod ell={}".format(ell))
    if K==QQ:
        nf.betas = [[1]] # for consistency, not actually used
        Fl = GF(ell)
        return [Fl(1)]
    
    try:
        betas = nf.betas # we'll have them already if the data came from a file
    except AttributeError:
        if not nf.hecke_ring_numerators:#nf.hecke_ring_power_basis:
            a = K.gen()
            betas = [a**i for i in range(K.degree())]
        else: # generic
            betas = [K(c)/d for c,d in zip(nf.hecke_ring_numerators, nf.hecke_ring_denominators)]
        nf.betas = betas
    return reduction_maps(betas, ell, verbose)
예제 #13
0
def apoly(manifold, rational_coeff=False, method='sage'):
    """
    Computes the SL(2, C) version of the A-polynomial starting from
    the extended Ptolemy variety.

    By default, uses Sage (which is to say Singular) to eliminate
    variables.  Surprisingly, Macaulay2 is *much* slower.

    sage: M = Manifold('m003')
    sage: I = apoly(M)
    sage: I.gens()
    [M^4*L^2 + M^3*L^2 - M*L^4 - 2*M^2*L^2 - M^3 + M*L^2 + L^2]
    """
    I = extended_ptolemy_equations(manifold)
    R = I.ring()
    if rational_coeff == False:
        F = GF(31991)
        R = R.change_ring(F)
        I = I.change_ring(R)
    to_elim = [R(x) for x in R.variable_names() if x not in ['M', 'L']]
    if method == 'sage':
        return I.elimination_ideal(to_elim)
    elif method == 'M2':
        from sage.all import macaulay2
        I_m2 = macaulay2(I)
        return I_m2.eliminate('{' + repr(to_elim)[1:-1] + '}').to_sage()
    else:
        raise ValueError("method flag should be in ['sage', 'M2']")
예제 #14
0
def test_semi_stable_frobenius_polynomial():

    # test that we indeed have a 73 isogeny mod p
    for p in 2, 3, 5, 7, 11, 19:
        for pp, e in (p * K).factor():
            f = semi_stable_frobenius_polynomial(E, pp)
            assert not f.change_ring(GF(73)).is_irreducible()
예제 #15
0
    def decap(cls, sk, pk, c):
        """IND-CCA decapsulation

        :param cls: Kyber class, inherit and change constants to change defaults
        :param sk: secret key
        :param pk: public key
        :param c: ciphertext

        .. note :: Resembles Algorithm 5 of the Kyber paper.

        """
        n = cls.n

        m = cls.dec(sk, c)
        m.set_immutable()
        set_random_seed(hash(m))  # NOTE: this is obviously not faithful

        K_ = random_vector(GF(2), n)
        K_.set_immutable()
        r = ZZ.random_element(0, 2**n-1)

        c_ = cls.enc(pk, m, r)

        if c == c_:
            return hash((K_, c))  # NOTE: this obviously isn't a cryptographic hash
        else:
            return hash(c)  # NOTE ignoring z
예제 #16
0
def generate_reference_columns(k):
    global eqn_row, result_dictionary, reference_dictionary, num_vars, iteration_size
    b = map_enumerations(map_subset(bsets[0]))
    for aset in asets:
        a = map_enumerations(map_subset(aset))
        if matrix(GF(p[0]), a + b, sparse=False).rank() < len(p):
            continue
        # j = enumerate_permutation(a+b)
        eqn_row = eqn_row + 1
        iteration_size = iteration_size + 1
        # result_dictionary[(j, eqn_row)] = 1
        # for i in range(k):
        # a_generated = [vector_mod_subtract(a[i1], a[i], p) for i1 in range(k)]
        # a_generated[i] = a[i]
        # calculate_column_values(a_generated, b, k, i, a)

    # reference_dictionary = {}
    # items = sorted(result_dictionary.items())
    # for key, val in items:
    #     if val != 0:
    #         column, row = key
    #         # print(row,column, val)
    #         if column in reference_dictionary:
    #             reference_dictionary[column].append((row,val))
    #         else:
    #             reference_dictionary[column] = [(row,val)]
    # print(reference_dictionary)
    result_dictionary = {}
    eqn_row = 0
예제 #17
0
    def is_independent(self, v):
        """
        Return True if the Hecke operators in v are independent.

        INPUT:

            - `v` -- four elements of the Hecke algebra mod 2 (represented as matrices)

        OUTPUT:

            - bool

        EXAMPLES::

            sage: from mdsage import *
            sage: C = KamiennyCriterion(29)
            sage: C.is_independent([C.T(1), C.T(2), C.T(3), C.T(4)])
            True
            sage: C.is_independent([C.T(1), C.T(2), C.T(3), C.T(1)+C.T(3)])
            False        
        """
#        X = matrix(GF(2), 4, sum([a.list() for a in v], []))
#        c = sage.matrix.matrix_modn_dense.Matrix_modn_dense(X.parent(),X.list(),False,True)
#        return c.rank() == 4

        # This crashes!  See http://trac.sagemath.org/sage_trac/ticket/8301
        return matrix(GF(2), len(v), sum([a.list() for a in v], [])).rank() == len(v)
        raise NotImplementedError
예제 #18
0
    def key_gen(cls, seed=None):
        """Generate a new public/secret key pair

        :param cls: Kyber class, inherit and change constants to change defaults
        :param seed: seed used for random sampling if provided

        .. note :: Resembles Algorithm 1 of the Kyber paper.

        """
        n, q, eta, k, D = cls.n, cls.q, cls.eta, cls.k, cls.D

        if seed is not None:
            set_random_seed(seed)

        R, x = PolynomialRing(ZZ, "x").objgen()
        Rq = PolynomialRing(GF(q), "x")
        f = R(cls.f)

        A = matrix(Rq, k, k,
                   [Rq.random_element(degree=n - 1) for _ in range(k * k)])
        s = vector(R, k, [R([(D(eta)) for _ in range(n)]) for _ in range(k)])
        e = vector(R, k, [R([(D(eta)) for _ in range(n)]) for _ in range(k)])
        t = (A * s + e) % f  # NOTE ignoring compression

        return (A, t), s
예제 #19
0
    def integral_basis_of_unramified_subfield(self, precision=5):
        r"""
        Return an (approximate) integral basis of the maximal unramified subfield.

        INPUT:

        - ``precison`` -- a positive integer

        OUTPUT:

        A list `\alpha=(\alpha_0,\ldots,\alpha_{m-1})` of elements of `K_0`
        which approximate (with precision `p^N` an integral basis of the
        maximal unramified subfield.

        """
        if not hasattr(self, "_integral_basis_of_unramified_subfield") or precision > 5:
            m = self.inertia_degree()
            if m == 1:
                return [QQ.one()]

            p = self.p()
            fb = GF(p**m, 'zeta').polynomial()
            f = fb.change_ring(self.number_field())
            fx = f.derivative()
            vK = self.valuation()
            k = vK.residue_field()
            zetab = fb.change_ring(k).roots()[0][0]
            assert fb(zetab) == 0
            zeta = vK.lift(zetab)
            while vK(f(zeta)) <= precision:
                zeta = zeta - f(zeta)/fx(zeta)
                zeta = self.reduce(zeta, precision +1)
            # now zeta is an approximate generator of the maximal unramified subfield
            self._integral_basis_of_unramified_subfield = [self.reduce(zeta**i, precision +1) for i in range(m)]
        return self._integral_basis_of_unramified_subfield
예제 #20
0
def iterate_permutations(k):
    global eqn_row, result_string, array_result
    # bigger than required array
    array_result = [[] for i in range((len(asets) * len(bsets)) + 1)]
    # iteration_chunk = iteration_size
    # eqn_chunk = 0
    for bset in bsets:
        b = map_enumerations(map_subset(bset))
        # initial_row = iteration_chunk*eqn_chunk
        for aset in asets:

            a = map_enumerations(map_subset(aset))
            if matrix(GF(p[0]), a + b, sparse=False).rank() < len(p):
                continue
            # print(a+b)
            eqn_row = eqn_row + 1
            j = enumerate_permutation(a + b)
            result_dictionary[(eqn_row, j)] = 1
            for i in range(k):
                a_generated = [
                    vector_mod_subtract(a[i1], a[i], p) for i1 in range(k)
                ]
                a_generated[i] = a[i]
                # print(a_generated)
                # calculate_column_values(a_generated, b, k, i, a)
                calculate_column_values_dynamic(a_generated, b, i)
예제 #21
0
def challenge():
    # Define the curve
    p = 0xA15C4FB663A578D8B2496D3151A946119EE42695E18E13E90600192B1D0ABDBB6F787F90C8D102FF88E284DD4526F5F6B6C980BF88F1D0490714B67E8A2A2B77
    a = 0x5E009506FCC7EFF573BC960D88638FE25E76A9B6C7CAEEA072A27DCD1FA46ABB15B7B6210CF90CABA982893EE2779669BAC06E267013486B22FF3E24ABAE2D42
    b = 0x2CE7D1CA4493B0977F088F6D30D9241F8048FDEA112CC385B793BCE953998CAAE680864A7D3AA437EA3FFD1441CA3FB352B0B710BB3F053E980E503BE9A7FECE
    E = EllipticCurve(GF(p), [a, b])

    # generator's public key
    G = E.point((
        0x39F15E024D44228FD11C58A71C312FD64167C7D249D5677DA0DFB4B9C3ED0F90701837A5E77B5A2B74433D7FBE027CD0C73B5AA7B300F7384521AF0DC283DC6D,
        0x5F3636A89167A6FBB7B7D1AD97D11C70756835B5F1273E20C06D9E022D74648EC22A3F92C378196D137C3F2027A67381BE79E1C0D65CD9B61211A77A3842C8B2,
    ))

    # alice's public key
    A = E.point((
        0x5AA8B5CF3124C552881BA67C14C863BB2FF30D960FE41B61123D2025CDDDF0EA75E92D76326BE9FB09B9A32373FC278AC8D5CF5CA83B9E517CE347C6879BEF51,
        0x2E3DDEC1B35930B1039351B2814252186B30CE27CE15EDA4351428868AE8593AB8C61C034BA10041CCE205D7F7102C292F30AC5F3D2A2C2F3A463D837DF070CD,
    ))

    # bob's public key
    B = E.point((
        0x7F0489E4EFE6905F039476DB54F9B6EAC654C780342169155344ABC5AC90167ADC6B8DABACEC643CBE420ABFFE9760CBC3E8A2B508D24779461C19B20E242A38,
        0xDD04134E747354E5B9618D8CB3F60E03A74A709D4956641B234DAA8A65D43DF34E18D00A59C070801178D198E8905EF670118C15B0906D3A00A662D3A2736BF,
    ))

    # Ciphertext
    iv = "719700b2470525781cc844db1febd994"
    encrypted_flag = "335470f413c225b705db2e930b9d460d3947b3836059fb890b044e46cbb343f0"
    n = smart_attack(E, G, A, p, a, b)
    secret = (n * B).xy()[0]
    print(decrypt_flag(secret, iv, encrypted_flag))
예제 #22
0
    def _to_relaxed_matrix_bp(self, graph):
        # convert graph to a topological sorting of the vertices
        nodes = nx.topological_sort(graph.graph)
        # the accept vertex must be last
        a = nodes.index(('acc', graph.num))
        b = nodes.index(('rej', graph.num))
        if a < b:
            nodes[b], nodes[a] = nodes[a], nodes[b]
        # the source vertex must be first
        src = nodes.index(('src', graph.num))
        nodes[0], nodes[src] = nodes[src], nodes[0]

        mapping = dict(zip(nodes, range(self.size)))
        g = nx.relabel_nodes(graph.graph, mapping)
        # convert graph to relaxed matrix BP
        self.bp = []
        G = MatrixSpace(GF(2), self.size)
        for layer in xrange(self.nlayers):
            zero = copy(G.one())
            one = copy(G.one())
            for edge in g.edges_iter():
                e = g[edge[0]][edge[1]]
                assert e['label'] in (0, 1)
                if g.node[edge[0]]['layer'] == layer:
                    if e['label'] == 0:
                        zero[edge[0], edge[1]] = 1
                    else:
                        one[edge[0], edge[1]] = 1
            self.bp.append(Layer(graph.inp(layer), zero, one))
        self.zero = G.one()
예제 #23
0
def diagonal_locations(H):
    r"""Returns the indices of the last `1` along the diagonal and the first block
    along the diagonal of `H`.

    Parameters
    ----------
    H : symmetric GF(2) matrix
        Contains either 1's along the diagonal or anti-symmetric blocks.

    Returns
    -------
    index_one : integer
        The last occurrence of a `1` along the diagonal of `H`. Equal to `g`
        if there are no ones along the diagonal.
    index_B : integer
        The first occurrence of a block along the diagonal of `H`. Equal to
        `-1` if there are no blocks along the diagonal.

    """
    g = H.nrows()
    B = Matrix(GF(2),[[0,1],[1,0]])
    try:
        index_one = min(j for j in range(g) if H[j,j] == 1)
    except ValueError:
        index_one = g

    try:
        index_B = max(j for j in range(g-1) if H[j:(j+2),j:(j+2)] == B)
    except ValueError:
        index_B = -1

    return index_one, index_B
예제 #24
0
    def rank(self, field_size):
        """ Returns rank of u_mat U gamma_set """
        rank = 0
        # If nothing in gamma_set yet, use u_vector
        if len(self.gamma_set) == 0:
            for val in self.u_vector:
                if val != 0:
                    rank += 1
            return rank

        # Get Rank of C
        C = np.append(self.u_mat, self.gamma_set)
        C_list = []
        if len(self.u_mat) == 0:
            for i in range(0, len(self.gamma_set)):
                C_list.append([])
        else:
            for row in self.u_mat:
                C_list.append(row.tolist())
        for i in range(0, len(self.gamma_set)):
            for j in range(0, len(self.gamma_set[i])):
                C_list[i].append(self.gamma_set[i][j])

        C = matrix(GF(field_size), C_list)
        return C.rank()
예제 #25
0
    def decode(m, q, n):
        """Decode vector `m` to `\{0,1\}^n` depending on distance to `q/2`

        :param m: a vector of length `\leq n`
        :param q: modulus

        """
        return vector(GF(2), n, [abs(e)>q/ZZ(4) for e in m] + [0 for _ in range(n-len(m))])
예제 #26
0
파일: ccz.py 프로젝트: adelapie/sboxU
def test_ea_permutations():
    for N in [4, 5]:
        F = GF(2**N, name="a")
        inv = [(F.fetch_int(x)**(2**N - 2)).integer_representation()
               for x in xrange(0, 2**N)]
        print("== " + str(N))
        for L in ea_equivalent_permutation_mappings(inv):
            print(L.str() + "\n")
예제 #27
0
def get_ccz_equivalent_permutation_cartesian(s, v0, v1, verbose=False):
    """Takes as input two vector spaces v0 and v1 of the set of zeroes in
    the LAT of s, each being the cartesian product of two spaces, and
    returns a permutation CCZ equivalent to s obtained using these CCZ
    spaces.

    """
    N = int(log(len(s), 2))
    # building B
    e1 = extract_basis(v0[0], N)
    t = len(e1)
    e2 = extract_basis(v1[0], N)
    B = Matrix(GF(2), N, N, [tobin(x, N) for x in e1 + e2])
    if verbose:
        print "B=  (rank={})\n{}".format(B.rank(), B.str())
    # building A
    e1 = extract_basis(v0[1], N)
    e2 = extract_basis(v1[1], N)
    A = Matrix(GF(2), N, N, [tobin(x, N) for x in e1 + e2])
    if verbose:
        print "A=  (rank={})\n{}".format(A.rank(), A.str())
    # building linear equivalent s_prime
    s_prime = [
        apply_bin_mat(s[apply_bin_mat(x, A.inverse())], B)
        for x in xrange(0, 2**N)
    ]
    # TU decomposition of s'
    T_inv, U = get_tu_closed(s_prime, t)
    if verbose:
        print "T_inv=["
        for i in xrange(0, 2**t):
            print "  {} {}".format(T_inv[i], is_permutation(T_inv[i]))
        print "]\nU=["
        for i in xrange(0, 2**t):
            print "  {} {}".format(U[i], is_permutation(U[i]))
        print "]"
    # TU-unfolding
    T = [inverse(row) for row in T_inv]
    result = [0 for x in xrange(0, 2**N)]
    for l in xrange(0, 2**t):
        for r in xrange(0, 2**(N - t)):
            x = (l << (N - t)) | r
            y_r = T[r][l]
            y_l = U[y_r][r]
            result[x] = (y_l << (t)) | y_r
    return result
예제 #28
0
def matrix_from_masks(basis, N):
    """Returns an NxN binary matrix M such that M*(1 << i) = basis[i] for
    all i < len(basis).

    """
    b = basis + [0] * (N - len(basis))
    return Matrix(GF(2), N, N, [[(b[i] >> j) & 1
                                 for j in reversed(range(0, N))]
                                for i in range(0, N)]).transpose()
예제 #29
0
def F_2t_to_space(basis, n):
    """Returns the matrix corresponding to a permutation of (F_2)^n such
    that F_2^t (i.e. the set of integers < 2^t) is mapped to the space
    with the given basis using the function apply_bin_mat()

    """
    full_basis = complete_basis(basis, n)
    return Matrix(GF(2), n, n, [[(v >> (n - 1 - j)) & 1 for j in xrange(0, n)]
                                for v in reversed(full_basis)]).transpose()
예제 #30
0
def get_generating_matrix(basis, N):
    """Returns an NxN binary matrix M such that M*(1 << i) = basis[i] for
    all i < len(basis) and such that M has full rank.

    """
    b = complete_basis(basis, N)
    return Matrix(GF(2), N, N, [[(b[i] >> j) & 1
                                 for j in reversed(xrange(0, N))]
                                for i in xrange(0, N)]).transpose()