def gaussian_elimination(self, columns=None, sort=True): """Evaluate the Gaussian eliminations on columns `columns`. :param: `iterable` columns - list or any iterable of columns. :return: Gaussian eliminations evaluated on columns. """ if not columns: columns = tuple(range(self.ncolumns)) else: columns = tuple(col for col in range(self.ncolumns) if col in columns) matrix_rows = tuple(self.copy()) for i, row in enumerate(matrix_rows): for j in columns: if row[j]: for row2 in (v for k, v in enumerate(matrix_rows) if k != i and matrix_rows[k][j]): row2 += row break else: continue if sort: mask = vector.from_support(self.ncolumns, support=columns).value return Matrix( sorted((row.value for row in matrix_rows), key=lambda x: x & mask, reverse=True), self.ncolumns) return Matrix((row.value for row in matrix_rows), self.ncolumns)
def find_permutation(matrix, m): a = matrix.T.solve(vector.from_support_supplement(2**m))[1] removing_num = a.support[0] if len(a.support) else 0 logger.debug(f'removing {removing_num}...') a_rows = [a] for i in range(m + 1): if i != removing_num: a_rows.append(a ^ vector.from_support(m + 1, [i])) a_rows = (mx.from_vectors(a_rows) * matrix)[1:] return mx.permutation([row.value for row in a_rows.T])
def attack(self, generator): rm_subcode_basis = matrix.Matrix() rm_subcode_dim = 0 for i in range(self.r): rm_subcode_dim += self.binomial_coef(self.m, i) while rm_subcode_basis.nrows < rm_subcode_dim: min_weight_codeword = self.min_weight_sample(generator) shortened_g = tools.truncate(generator, min_weight_codeword) inner_sets = self.decompose_inner_sets(shortened_g) f_vecs = [ vector.from_support(2**self.m, min_weight_codeword + s) for s in inner_sets ] rm_subcode_basis = tools.union(rm_subcode_basis, matrix.from_vectors(f_vecs)) return rm_subcode_basis
def find_permutation(self, generator): onev = vector.from_support_supplement(2**m) a = generator.T.solve(onev)[1] removing_num = 0 if len(a.support): removing_num = a.support[0] A_rows = [a] for i in range(0, m + 1): if i != removing_num: A_rows.append(a ^ vector.from_support(m + 1, [i])) ag = matrix.from_vectors(A_rows) * generator A_rows = ag[1:] return matrix.permutation([row.value for row in A_rows.T])
def truncate(generator, columns=None, remove_zeroes=False): """Return generator matrix of truncated code. Truncated code is code obtaining by choose codewords which have coordinates with indexes from `columns` is zero. Unlike the punctured code truncated code is a subcode of original code. NOTE! If remove_zeroes is set to True the truncated codes would not be a subcode of the original code. """ if not columns: columns = [] mask = vector.from_support(generator.ncolumns, columns) trunc = matrix.Matrix( (row.value for row in generator.gaussian_elimination(columns) if not (row * mask).value), generator.ncolumns).echelon_form trunc = matrix.Matrix((row.value for row in trunc if row.value), generator.ncolumns) if remove_zeroes: return trunc.submatrix(columns=(i for i in range(generator.ncolumns) if i not in columns)) return trunc
def attack(self, pub_key): B = matrix.Matrix() B_size = 0 for i in range(self.r): B_size += binom(self.m, i) codeword_support_list = [] while B.nrows < B_size: codeword_support = self \ ._gauss_codeword_support(pub_key, codeword_support_list) codeword_support_list.append(codeword_support) pub_key_truncated = tools.truncate(pub_key, codeword_support) inner_sets = self._decompose_inner_sets(pub_key_truncated) f_vecs = [ vector.from_support(2**self.m, codeword_support + s) for s in inner_sets ] B = tools.union(B, matrix.from_vectors(f_vecs)) return B
def test_make_vector_from_support(self): """Test make vector from support.""" vec = vector.from_support(14, (1, 2, 3, 4, 7, 8, 12)) self.assertEqual(int(vec), 0b01111001100010)