# Permutation Algebra This notebook is a prerequisite to following the DARC tutorial ## Key Generation Parameters - block size: The number of characters we encode in a block. Block size isn't using in this notebook - key height: The alphabet length. If we want to encode bytes, our alphabet length is 256. If we want to encode lowercase letters a-z our alphabet length is 26. NKodes {{ height }} key {{ width }} attribute alphabet is {{ total_attr }}. - key width: The number of bytes an encrypted charter is in our alphabet. ``` height = {{ height }} width = {{ width }} ``` ## Operand Types ### Inner Permutation Key An inner permutation key (inner key for short) is a list of `height` rows, each a random permutation of an identity array of length `width`. ``` i0 = InnerKey.init_matrix(width, height) i1 = InnerKey.init_matrix(width, height) i2 = InnerKey.init_matrix(width, height) i_identity = InnerKey.init_identity_matrix(width, height) i0.matrix: {% for row in i0.matrix -%} {{ row }} {% endfor %} i1.matrix: {% for row in i1.matrix -%} {{ row }} {% endfor %} i2.matrix: {% for row in i2.matrix -%} {{ row }} {% endfor %} i_identity.matrix: {% for row in i_identity.matrix -%} {{ row }} {% endfor %} ``` ### Outer Permutation Key An outer key is a list of `height` columns, each a random permutation of an identity array of length `height`. It is used to permute the rows of inner, substitution and outer keys. ``` o0 = OuterKey.init_matrix(height) o1 = OuterKey.init_matrix(height) o2 = OuterKey.init_matrix(height) o_identity = OuterKey.init_identity_matrix(height) o0.matrix: {{ o0.matrix }} o1.matrix: {{ o1.matrix }} o2.matrix: {{ o2.matrix }} o_identity.matrix: {{ o_identity.matrix }} ``` ### Substitution Key Substitution key is a matrix of `height` rows and `width` columns. Each row is a list of randomly generated bytes. ``` s0 = SubstitutionKey.init_matrix(width, height) s1 = SubstitutionKey.init_matrix(width, height) s2 = SubstitutionKey.init_matrix(width, height) s_identity = SubstitutionKey.init_identity_matrix(width, height) s0.matrix: {% for row in s0.matrix -%} {{ row }} {% endfor %} s1.matrix: {% for row in s1.matrix -%} {{ row }} {% endfor %} s2.matrix: {% for row in s2.matrix -%} {{ row }} {% endfor %} s_identity.matrix: {% for row in s_identity.matrix -%} {{ row }} {% endfor %} ``` ## Operators Types ### < Outer Permutation #### Substitution Key < Outer Key ``` s0_o0 = s0 < o0 ``` | idx |s0|s0| s0_o0 | |-----|-|-|-------| {% for idx in range(height) -%} |{{idx}}|{{ s0.matrix[idx] }}|{{ o0.matrix[0][idx] }}|{{ s0_o0.matrix[idx] }}| {% endfor %} #### Inner Key < Outer Key i0_o0 = i0 < o0 | idx | i0 | o0 | i0_o0 | |-----|----|----|-------| {% for idx in range(height) -%} |{{idx}}|{{ i0.matrix[idx] }}|{{ o0.matrix[0][idx] }}|{{ i0_o0.matrix[idx] }}| {% endfor %} ### << Inner Permutation #### Outer Key << Outer Key o0_o1 = o0 << o1 | idx | o0 | o1 | o0_o1 | |-----|----|----|-------| {% for idx in range(height) -%} |{{idx}}|{{ o0.matrix[0][idx] }}|{{ o1.matrix[0][idx] }}|{{ o0_o1.matrix[0][idx] }}| {% endfor %} #### Inner Key << Inner Key i0_i1 = i0 << i1 | idx | i0 | i1 | i0_i1 | |-----|----------------------------------------------------------|----|-------| {% for idx in range(height) -%} |{{idx}}|{{ i0.matrix[idx] }}|{{ i1.matrix[idx] }}|{{ i0_i1.matrix[idx] }}| {% endfor %} #### Substitution Key << Inner Key s0_i0 = s0 << i0 | idx | s0 | i0 | s0_i0 | |-----|----|----|-------| {% for idx in range(height) -%} |{{idx}}|{{ s0.matrix[idx] }}|{{ i0.matrix[idx] }}|{{ s0_i0.matrix[idx] }}| {% endfor %} ### ~Permutation Inversion #### ~Outer Key inv_o0 = ~o0 | idx | o0 | ~o0 | |-----|----|-----| {% for idx in range(height) -%} |{{idx}}|{{ o0.matrix[0][idx] }}|{{ inv_o0.matrix[0][idx] }}| {% endfor %} #### ~Inner Key inv_i0 = ~i0 | idx | i0 | ~i0 | |-----|----|-----| {% for idx in range(height) -%} |{{idx}}|{{ i0.matrix[idx] }}|{{ inv_i0.matrix[idx] }}| {% endfor %} ### ^ Substitution #### Substitution Key ^ Substitution Key s0_s1 = s0 ^ s1 | idx | s0 | s1 | s0_s1 | |-----|----|----|-------| {% for idx in range(height) -%} |{{idx}}|{{ s0.matrix[idx] }}|{{ s1.matrix[idx] }}|{{ s0_s1.matrix[idx] }}| {% endfor %} ## Substitution Permutation Algebra #### properites: - associative: (a + b) + c = a + (b + c) - commutative: a + b = b + a - identity: a + 0 = a or a * 1 = a - inverse: a + (-a) = 0 or a * 1/a = 1 (for all a ~= 0) - distributive: a(b + c) = ab + ac ### Associative #### Outer Key ``` (o0 << o1 << o2) == ((o0 << o1) << o2) == (o0 << (o1 << o2)) ``` #### Inner Key ``` (i0 << i1 << i2) == ((i0 << i1) << i2) == (i0 << (i1 << i2)) ``` #### Substitution Key ``` (s0 ^ s1 ^ s2) == ((s0 ^ s1) ^ s2) == (s0 ^ (s1 ^ s2)) ``` ### Commutative Property Substitution is the only key type that is commutative #### Substitution Key ``` (s0 ^ s1) == (s1 ^ s0) ``` ### Identity Property #### Outer Key ``` (o0 << o_identity) == o0 ``` #### Inner Key ``` (i0 << i_identity) == i0 ``` #### Substitution Key ``` (s0 ^ s_identity) == s0 ``` ### Inverse Property #### Outer Key ``` (o0 << ~o0) == o_identity ``` #### Inner Key ``` (i0 << ~i0) == i_identity ``` #### Substitution Key ``` (s0 ^ s0) == s_identity ``` ### Distributive #### Inner Key/Outer Key ``` ((i0 << i1) < o0) == ((i0 < o0) << (i1 < o0)) ``` #### Substitution Key/Outer Key ``` ((s0 ^ s1) < o0) == ((s0 < o0) ^ (s1 < o0)) ``` #### Substitution Key/Inner Key ``` ((s0 ^ s1) << i0) == ((s0 << i0) ^ (s1 << i0)) ``` #### Substitution Key/Inner Key/Outer Key ``` ((s0 << i0) < o0) == ((s0 < o0) << (i0 < o0)) ``` ### Other Examples ``` (s0 << (i0 < o0)) == (((s0 < ~o0) << i0) < o0) ((s0 < o0) << i0) == ((s0 << (i0 < ~o0)) < o0) (~(i0 << i1)) == (~i1 << ~i0) (~(o0 << o1)) == (~o1 << ~o0) i0 == ((i0 << i2 << i1) << ~(i2 << i1)) == ((i0 << i2 << i1) << ~i1 << ~i2) ``` ### Becareful about your order of operation ***Always use parenthesis to control the order of operation*** ``` i0 < (o0 << o1 << o2) != (i0 < (o0 << o1 << o2)) # not equal !!!!!! ```