6
$\begingroup$

By definition, branch number

Definition: The branch number of a linear transformation $F$ is $$min_{a\neq0}(W(a) + W(F(a)))$$

Source here (7.3.1)

For AES MixColumns $a \in GF(2^8)^4$ since the input is the four bytes in a column of the state.

Where $W(a)$ is a weight vector i.e. the number of nonzero components of the vector

$$a \in GF(2^m)^4, a = (a_1, \ldots, a_4)\\ W(a) \iff ||a|| = |\{i | a_i\neq 0 \}|, i = 1,\ldots,4$$

In AES uses a pre-defined matrix operations MixColumns. I need prove (like the proof of a theorem) that the branch number of matrix is equal to 5.

Questions:

  1. In the same article (7.3.1) is said

    the output can have at most 4 active bytes

    and

    Hence, the upper bound for the branch number is 5

    In such a way that $W(F(a))$ the maximum can be $4$ (why?) and $W(a) = 1$. Why $W(a) = 1$, because the number of non-zero component can be greater than $1$? Or it is there to pay attention to $min()$?

  2. How to calculate $W(F(a))$, for each $a \in GF(2^m)$ ?

The final answer:

Use theorem No. 2 (on page 4) here

is MDS if and only if every square submatrix of A is nonsingular

Ok, the initial data taken from here.

To test, I wrote a script test.py (see below) that:

  1. Defines all sub-matrices of the original
  2. For each of the sub-matrices calculate the determinant in GF(2^8)
  3. The result is an array of values of the determinant of each submatrix.

test.py

from functools import reduce import sys # ===========================Galois field=========================== # constants used in the multGF2 function mask1 = mask2 = polyred = None def setGF2(degree, irPoly): # Define parameters of binary finite field GF(2^m)/g(x) # - degree: extension degree of binary field # - irPoly: coefficients of irreducible polynomial g(x) def i2P(sInt): # Convert integer into a polynomial return [(sInt >> i) & 1 for i in reversed(range(sInt.bit_length()))] global mask1, mask2, polyred mask1 = mask2 = 1 << degree mask2 -= 1 polyred = reduce(lambda x, y: (x << 1) + y, i2P(irPoly)[1:]) def multGF2(p1, p2): # Multiply two polynomials in GF(2^m)/g(x) p = 0 while p2: if p2 & 1: p ^= p1 p1 <<= 1 if p1 & mask1: p1 ^= polyred p2 >>= 1 return p & mask2 def determinant(matrix, mul): width = len(matrix) if width == 1: return multGF2(mul, matrix[0][0]) else: sign = 1 total = 0 for i in range(width): m = [] for j in range(1, width): buff = [] for k in range(width): if k != i: buff.append(matrix[j][k]) m.append(buff) total = total ^ (multGF2(mul, determinant(m, multGF2(sign, matrix[0][i])))) return total # ===========================All submatrix=========================== import numpy as np def get_all_sub_mat(mat): rows = len(mat) cols = len(mat[0]) def ContinSubSeq(lst): size=len(lst) for start in range(size): for end in range(start+1,size+1): yield (start,end) for start_row,end_row in ContinSubSeq(list(range(rows))): for start_col,end_col in ContinSubSeq(list(range(cols))): yield [i[start_col:end_col] for i in mat[start_row:end_row] ] def swap_cols(arr, frm, to): arr = np.matrix(arr) arr[:,[frm, to]] = arr[:,[to, frm]] return arr.tolist() def swap_rows(arr, frm, to): arr = np.matrix(arr) arr[[frm, to],:] = arr[[to, frm],:] return arr.tolist() def print_matrix(matrix): matrix = np.matrix(matrix) print matrix submatrix = [] def foo(matrix): for i in get_all_sub_mat(matrix): if len(i) == len(i[0]) and len(i) != 1: submatrix.append(i) # Initial matrix matrix = [ [2, 3, 1, 1], [1, 2, 3, 1], [1, 1, 2, 3], [3, 1, 1, 2] ] # All submatrix here for i in [[0,0], [1,2], [1,3], [2,3]]: _matrix = swap_cols(matrix, i[0], i[1]) for j in [[0,0], [1,2], [1,3], [2,3]]: _matrix = swap_rows(matrix, i[0], i[1]) foo(_matrix) # print len(submatrix) # 224 if __name__ == "__main__": setGF2(8, 0b10001) # 0b10001 equal modulo x^4+1 from https://en.wikipedia.org/wiki/Rijndael_mix_columns data = [] N = 2 ** 8 result = [] for m in submatrix: result.append(determinant(m, 1)) print 'Final result: ', result print '0 in result: ', 0 in result 

Thanks @kodlu for the help!

$\endgroup$

1 Answer 1

8
$\begingroup$

The AES MixColumns operator ensures that the 8 bytes (4 in the input column 4 in the output column) form the codewords of an MDS code over $GF(2^8)$, which means the minimum weight of the code, which is 5, equals the number of nonzero bytes.

Any nonzer byte contributes 1 to the minimum weight, by definition of Hamming Weight over $GF(2^8)$. A nonzero symbol has weight 1, regardless of how many bits of the eight is nonzero.

See the answer to this question for more.

Edit: The Singleton bound states that minimum distance is at least $n-k+1.$ Here $n=8, k=4.$ Such a code is MDS and proving MDS depends on the code structure. Look up MDS codes and Reed Solomon codes.

More concretely, a linear code is the nullspace of its parity check matrix. So if that matrix has all its collections of $d-1$ columns linearly independent (over $GF(2^8)$ here) then its minimum weight codeword must be $d$ or more. Moreover a code is MDS if and only if its dual is MDS so we can just consider the generator matrix and observe all collections of 4columns of $[A| I]$ are indeed linearly independent.So, $d\geq 5.$ But by singleton bound $d\leq 5.$ QED.

See the following link for more details:

$\endgroup$
10
  • $\begingroup$ in AES uses a fixed polynomial $$c(x) = 3x^3 + x^2 + x + 2$$ The coefficients have been chosen in such a way that the upper bound is reached. "Any nonzer byte contributes 1 to the minimum weight" - Thank you, well done! "ensures that the 8 bytes" and "See the answer to this question for more" - Yeah, I saw this answer, but still not very well understood, how is the calculation (from a mathematical point of view) $\endgroup$ Commented Jan 4, 2017 at 19:36
  • $\begingroup$ in other words, how to prove "The branch number, which is the minimum weight of the corresponding linear code is 4, in $GF(2^n)$ for all $n$"? $\endgroup$ Commented Jan 4, 2017 at 20:00
  • 2
    $\begingroup$ The branch number is 5 not 4. Also, your definition of the weight uses the bit weight not byte weight., which is wrong. $\endgroup$ Commented Jan 4, 2017 at 20:21
  • $\begingroup$ Do you mind me editing the question since the way the weight is used from the NIST doc is the problem. $\endgroup$ Commented Jan 4, 2017 at 20:26
  • $\begingroup$ Ok, I use byte weight. But I still don't understand why 5? In the documentation of AES is described as a fact. There is no mathematical explanation of why chosen this polynomial (exactly this polynomial allows to obtain a branch number = 5) $\endgroup$ Commented Jan 4, 2017 at 20:28

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.