Пример #1
0
    def are_CCZ_equivalent(s1, s2):
        s1, s2 = convert_sboxes(s1, s2)
        assert_equal_sizes(s1, s2)
        lin1 = s1.is_linear()
        lin2 = s2.is_linear()
        if lin1 ^ lin2:
            return False
        if lin1 and lin2:
            return True

        inp, out = s1.n, s1.m
        M1 = matrix(GF(2), 1 + inp + out, 2**inp)
        M2 = matrix(GF(2), 1 + inp + out, 2**inp)
        for x in range(2**inp):
            M1.set_column(
                x,
                Bin.concat(Bin(1, 1) + Bin(x, inp) + Bin(s1[x], out)).tuple)
            M2.set_column(
                x,
                Bin.concat(Bin(1, 1) + Bin(x, inp) + Bin(s2[x], out)).tuple)

        L1 = LinearCode(M1)
        L2 = LinearCode(M2)
        # Annoying: this is not checked in "is_permutation_equivalent" code!
        # raises a TypeError instead
        if L1.generator_matrix().nrows() != L2.generator_matrix().nrows():
            return False
        return L1.is_permutation_equivalent(L2)
Пример #2
0
def mat_field_mul_const(field, c):
    assert field.base_ring() == GF(2)
    d = field.degree()
    m = matrix(GF(2), d, d)
    for i, e in enumerate(reversed(range(d))):
        x = 1 << e
        res = field.fetch_int(x) * field.fetch_int(c)
        res = res.integer_representation()
        m.set_column(i, Bin(res, d).tuple)
    return m
Пример #3
0
def matrix_mult_int_rev(mat, x):
    """
    LSB to MSB vector
    >>> matrix_mult_int_rev( \
        matrix(GF(2), [[1, 0, 1], [1, 0, 0]]), \
        0b110) # read as 6 -> 0,1,1 -> 1,0 -> 1
    1
    """
    assert mat.base_ring() == GF(2)
    n = mat.ncols()
    x = vector(GF(2), Bin(x, n).tuple[::-1])
    y = mat * x
    return Bin(y[::-1]).int
Пример #4
0
 def xor_cmul_ddt(self, F=None):
     if F is None:
         F = GF(self.insize, name='a')
     xcddt = matrix(ZZ, self.insize, self.outsize)
     for x in range(self.insize):
         for dx in range(1, self.insize):
             x2 = x ^ dx
             y = self[x]
             y2 = self[x2]
             dy = (F.fetch_int(y2) * F.fetch_int(y)
                   **(self.outsize - 2)).integer_representation()
             xcddt[dx, dy] += 1
     return xcddt
Пример #5
0
 def cmul_xor_ddt(self, F=None):
     if F is None:
         F = GF(self.insize, name='a')
     cxddt = matrix(ZZ, self.insize, self.outsize)
     for x in range(1, self.insize):
         for dx in range(2, self.insize):
             x2 = (F.fetch_int(x) *
                   F.fetch_int(dx)).integer_representation()
             y = self[x]
             y2 = self[x2]
             dy = y2 ^ y
             cxddt[dx, dy] += 1
     return cxddt
Пример #6
0
def matrix_mult_int(mat, x):
    """
    MSB to LSB vector
    >>> matrix_mult_int( \
        matrix(GF(2), [[1, 0, 1], [1, 0, 0]]), \
        0b110) # read as 6 -> 1,1,0 -> 1,1 -> 3
    3
    """
    assert mat.base_ring() == GF(2)
    n = mat.ncols()
    x = vector(GF(2), Bin(x, n).tuple)
    y = mat * x
    return Bin(y).int
Пример #7
0
    def as_matrix(self):
        assert self.is_linear()

        m = matrix(GF(2), self.output_size(), self.input_size())
        for e in range(self.input_size()):
            vec = Bin(self[2**e], self.output_size()).tuple
            m.set_column(self.input_size() - 1 - e, vec)
        return m
Пример #8
0
 def hdim(self, right_to_left=False):
     """
     hdim[i,j] = i-th output bit contains monomial x1...xn/xj
     """
     res = matrix(GF(2), self.in_bits, self.out_bits)
     anf = mobius(tuple(self))
     for j in range(self.in_bits):
         mask = (1 << self.in_bits) - 1
         mask ^= 1 << (self.in_bits - 1 - j)
         res.set_column(j, Bin(anf[mask], self.out_bits).tuple)
     if right_to_left:
         res = res[::-1, ::-1]
     return res
Пример #9
0
def test():
    from cry.sagestuff import randint, random_matrix, choice, primes

    ps = list(primes(20))
    for itr in range(100):
        fld = GF(choice(ps))
        m = random_matrix(fld, randint(2, 50), randint(2, 50))
        print(f"#{itr}", ":", m.nrows(), "x", m.ncols(), "rank", m.rank())

        def oracle(x):
            nonlocal m
            return m * vector(fld, x)

        A = AffineSystem(oracle, m.ncols(), field=fld)
        x = random_vector(fld, m.ncols())
        y = A.matrix * x

        num = 0
        for x in A.solve(y, all=True):
            assert tuple(oracle(x)) == tuple(y)
            num += 1
            if num > 10:
                break
Пример #10
0
def random_bit_permutation(n):
    return from_matrix(random_permutation_matrix(GF(2), n))
Пример #11
0
def random_linear(n, m=None):
    if m is None:
        m = n
    return from_matrix(random_matrix(GF(2), m, n))
Пример #12
0
def random_linear_permutation(n):
    return from_matrix(random_invertible_matrix(GF(2), n))
Пример #13
0
def all_irreducible_polynomials(N, p=2):
    FR = PolynomialRing(GF(p), names=("X", ))
    for poly in FR.polynomials(of_degree=N):
        if poly.is_irreducible():
            yield poly
Пример #14
0
def mat_from_linear_func(m, n, func):
    mat = matrix(GF(2), n, m)
    for i, e in enumerate(reversed(range(m))):
        x = 1 << e
        mat.set_column(i, Bin(func(x), n).tuple)
    return mat
Пример #15
0
 def get_x(cls, n=None, field=None):
     assert (n is not None) ^ (field is not None)
     field = field or GF(2**n, name='a')
     return PolynomialRing(field, names='x').gen()
Пример #16
0
def power(e, n=None, field=None):
    assert (n is not None) ^ (field is not None)
    field = field or GF(2**n, name='a')
    x = PolynomialRing(field, names='x').gen()
    return SBox2(x**e)
Пример #17
0
from cry.sagestuff import matrix, GF, Permutation

F2 = GF(2)


class Perm:
    def __init__(self, p, n=None):
        self.p = tuple(p)
        self.n = n if n is not None else (max(self.p) + 1)
        self.m = len(self.p)
        assert all(0 <= i < self.n for i in self.p)

    @classmethod
    def from_matrix(cls, m):
        res = [None] * m.nrows()
        for y, x in m.support():
            res[y] = x
        return cls(res, n=m.ncols())

    def to_matrix(self, field=F2):
        m = matrix(Permutation([v + 1 for v in self.p]))
        m = m.transpose().change_ring(field)
        return m

    def complete(self, n):
        assert n >= self.n
        s = set(self.p)
        return self.Perm(self.p + tuple(v for v in range(n) if v not in s))

    def __invert__(self):
        res = [None] * len(self)
Пример #18
0
 def minilat_binary(self, mod=4):
     """minilat % mod and then mod/2 -> 1, 0 -> 0"""
     mat = self.minilat() % 4
     for x in mat.list():
         assert x in (0, mod / 2), "invalid mod for given function"
     return (mat.lift() / (mod / 2)).change_ring(GF(2))
Пример #19
0
def all_fields_of_dimension(N, p=2, name='a'):
    for poly in all_irreducible_polynomials(N, p):
        yield GF(p**N, name=name, modulus=poly)