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
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
def get_ccz_equivalent_permutation(l, v0, v1, verbose=False): N = int(log(len(l), 2)) mask = sum(int(1 << i) for i in xrange(0, N)) L = v0 + v1 L = Matrix(GF(2), 2 * N, 2 * N, [tobin(x, 2 * N) for x in L]).transpose() if verbose: print "\n\nrank={}\n{}".format(L.rank(), L.str()) new_l = [[0 for b in xrange(0, 2**N)] for a in xrange(0, 2**N)] for a, b in itertools.product(xrange(0, 2**N), xrange(0, 2**N)): v = apply_bin_mat((a << N) | b, L) a_prime, b_prime = v >> N, v & mask new_l[a][b] = l[a_prime][b_prime] return invert_lat(new_l)