Algebraic Cryptanalysis of Round Reduced Versions of CSA and the LED Family of Block Ciphers Bachelor-Thesis von Julian Wälde Januar 2013 Computer Science CDC Algebraic Cryptanalysis of Round Reduced Versions of CSA and the LED Family of Block Ciphers Vorgelegte Bachelor-Thesis von Julian Wälde 1. Gutachten: Prof. Dr. Johannes Buchmann 2. Gutachten: Dr. Stanislav Bulygin 3. Gutachten: Tag der Einreichung: Bitte zitieren Sie dieses Dokument als: URN: urn:nbn:de:tuda-tuprintsURL: http://tuprints.ulb.tu-darmstadt.de/ Dieses Dokument wird bereitgestellt von tuprints, E-Publishing-Service der TU Darmstadt http://tuprints.ulb.tu-darmstadt.de [email protected] Die Veröffentlichung steht unter folgender Creative Commons Lizenz: Namensnennung – Keine kommerzielle Nutzung – Keine Bearbeitung 2.0 Deutschland http://creativecommons.org/licenses/by-nc-nd/2.0/de/ Erklärung zur Bachelor-Thesis Hiermit versichere ich, die vorliegende Bachelor-Thesis ohne Hilfe Dritter nur mit den angegebenen Quellen und Hilfsmitteln angefertigt zu haben. Alle Stellen, die aus Quellen entnommen wurden, sind als solche kenntlich gemacht. Diese Arbeit hat in gleicher oder ähnlicher Form noch keiner Prüfungsbehörde vorgelegen. Darmstadt, den January 28, 2013 (Julian Wälde) 1 Abstract Lightweigt cryptograhy aims to achieve high security while at the same time reducing complexity of computation by relying on simpler building blocks. This work analyses the security of two lightweight block ciphers (LED and CSA) against algebraic cryptanalysis. We describe an algebraic attack on 3 round LED64 and a simple generic attack on 8 round LED80/LED128. Using side channel information we were able to break full round LED. In regards to CSA we found an attack on up to 15 rounds that is faster than a corresponding generic attack as well as algebraic side channel attacks on the full round CSA. 2 Contents 1. Introduction 1.1. Definitions . . . . . . . . . . . . . . . . . . . . 1.2. Symmetric encryption . . . . . . . . . . . . . 1.2.1. Block cipher . . . . . . . . . . . . . . . 1.2.2. Iterated block ciphers . . . . . . . . . 1.2.3. Modes of operation . . . . . . . . . . 1.2.4. Cryptanalysis . . . . . . . . . . . . . . 1.2.5. The Satisfiability problem . . . . . . 1.2.6. Algebra . . . . . . . . . . . . . . . . . . 1.3. Side channel cryptanalysis . . . . . . . . . . . 1.4. Algebraic cryptanalysis . . . . . . . . . . . . . 1.4.1. Algebraic representation of a cipher 1.4.2. Solving methods . . . . . . . . . . . . 1.4.3. SAT solvers . . . . . . . . . . . . . . . 1.4.4. Measuring attack costs . . . . . . . . 1.4.5. Algebraic side channel cryptanalysis 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.0.6. Key schedule . . . . . . . . . . . . . . . . . . . . . 2.0.7. Round function . . . . . . . . . . . . . . . . . . . . Previous cryptanalysis of LED . . . . . . . . . . . . . . . . Generic attack on 8 rounds of LED80 and LED128 . . . An algebraic attack on 3 rounds of LED64 . . . . . . . . 2.3.1. A note on reduced variants of LED . . . . . . . . 2.3.2. An algebraic model for the LED round function 2.3.3. Performance of the attack . . . . . . . . . . . . . A side channel attack on the full round LED cipher . . . 2.4.1. Modeling side channel information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. The LED Family of Block Ciphers 2.1. 2.2. 2.3. 2.4. 4 4 4 4 5 5 5 6 7 7 7 7 7 8 8 9 3. The CSA block cipher 3.1. DVBCSA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2. The design of the CSA block cipher . . . . . . . . . . . . . . . 3.2.1. Key schedule . . . . . . . . . . . . . . . . . . . . . . . . 3.2.2. The round function . . . . . . . . . . . . . . . . . . . . 3.3. Previous cryptanalysis of CSA . . . . . . . . . . . . . . . . . . . 3.4. A Meet in the Middle Attack on up to 15 rounds of CSA . . 3.5. An algebraic cryptanalysis of the CSA block cipher . . . . . . 3.5.1. An algebraic description of the CSA round function . 3.6. Key bit guessing strategy . . . . . . . . . . . . . . . . . . . . . . 3.6.1. Experimental data on the speed of the attack . . . . 3.7. A algebraic side channel analysis of the CSA block cipher . 9 9 11 11 12 12 12 13 14 14 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 16 16 17 18 19 19 19 19 20 20 4. Conclusion 21 A. Appendix 24 3 1 Introduction In many communication applications cryptography is the most resource demanding part of the communication. The up-coming of RFID and wireless sensor networks and chip cards resulted in the need for lightweight cryptography to make secure communication in restricted environments possible. In this work we will analyse the LED and CSA block cipher regarding their security against algebraic cryptanalysis. 1.1 Definitions In this section we will establish various concepts that we will later call upon to explain what we’ve been working on. 1.2 Symmetric encryption Symmetric encryption deals with the problem of securing the confidentiality of communication. The usual approach to this is to create an algorithm that given an arbitrary message and a secret key scrambles a message in a manner that makes knowledge of the secret key mandatory for anyone seeking knowledge of the messages content. 1.2.1 Block cipher A block cipher is a cipher that operates on blocks of fixed size. Formally it can be viewed as a tuple (P, C, K, E, D). P being the set of plain texts and C being the set of cipher-texts. K is the set of keys and E and D are functions for encryption and decryption with Ek : P → C Dk : C → P Ek ◦ Dk = id for any k ∈ K . E x is supposed to be indistinguishable from a bijective random function f r and om : P → C if x is selected at random. Usually P = C can be assumed, making E a family of so called pseudo random permutations (PRP). 1.2.2 Iterated block ciphers Iterated block ciphers are a concept for the construction of secure block ciphers; it follows the idea that a simple transformation is applied to the plain-text in an iterated fashion to create a complex relation between plain- and cipher-text and a key. This simple transformation is often referred to as a round function; and its iterations are referred to as round. The keys that are used to obscure the intermediate cipher-text are called round keys. The round keys are created by expanding the actual secret key using another function referred to as the key schedule. Confusion Confusion is the concept of creating a very complex relationship between plain- and cipher-text. To create a compact function for a large domain and range often a complex function is applied locally. Often this is implemented by using a lookup table that is referred to as an S-Box; the S-Box implements a 4 very non-linear function but its lookup table requires memory that is exponential in the size of its input domain. Due to this the S-Box usually operates on small parts of the intermediate cipher-text. Most popular choices for the size of the S-Box are 4 and 8 bit. Diffusion Diffusion is the property of the cipher that every bit of its output depends on any bit of the input in a complex way. Such that even a small change on the input results in a change in the output that appears completely random. 1.2.3 Modes of operation Since a block cipher encrypts “blocks” of fixed size (in many cases shorter than the message that needs encryption) one needs to find a way to encrypt a large message using block ciphers. CBC CBC (Cipher Block Chaining) operates by xoring any plain-text block with the previous cipher-text block (i.e. repeating plain-text blocks do not result in repeating cipher-text blocks). An initialization vector IV is used to randomize the encryption of the first block; such that repeating messages result in apparent random cipher-texts. A message m := p0 ||p1 || . . . ||pn is encrypted as E(m) := c0 ||c1 || . . . ||cn : c0 = Ek (p0 ⊕ I V ) and 0 ≤ I V ≤ 2n ci = Ek (pi ⊕ ci−1 ) with n being the block size in bits. 1.2.4 Cryptanalysis In general cryptanalysis is the effort to break a crypto-system under certain assumptions faster then brute force. There are only a few crypto-systems that are provably secure against this effort. Exhaustive search The most generic attack thinkable on any cipher that is not information theoretically secure would be to try out every k ∈ K until the right key is found. This technique is known as “brute force” or “exhaustive search”. In order for the attack to work an attack requires some way to recognize the “right” key or likewise discard “wrong” keys. E.g. in case of a block cipher a couple of plain-text cipher-text pairs (pi , ci ) with Ek (pi ) = ci would suffice to test any given k for being the key actually used. 1.2.5 The Satisfiability problem The satisfiability problem (SAT) is the problem of determining whether there exists a setting for logical variables that satisfies a given logical formula or whether there exists no such setting. We will refer to these as SAT and UNSAT respectively. SAT is a NP-complete problem. SAT solvers are programs that are used to solve instances of the SAT problem. Example: (v 1 ∨ ¬v 2 ) ∧ (v 2 ∨ v 3 ) ∧ (v 1 ∨ v 3 ∨ v 4 ) is satisfied if v 1 and v 3 are set to true. While there exists no satisfying setting for this formula: v 1 ∧ (v 2 ∨ ¬v 1 ) ∧ ¬v 2 5 1.2.6 Algebra In this part we will recall a few basic facts about algebra that are required to understand the rest of this work. Polynomial In algebra a polynomial p in the variable X over a field F is the sum of products of coefficients ai ∈ F and powers of X . These summands are referred to monomials. Polynomials in more than one variable are referred to as multivariate polynomials. The degree of a monomial is the sum of exponents of the variables that appear in it; the degree of a polynomial is the maximum degree of its monomials. The polynomials in a given field F and n variables form the ring of polynomials (F[X 0 , . . . , X n ]). Pn p := i=0 ai X i . A multivariate Polynomial with variables in X := {x 1 , x 2 , . . . , x n } has the form: Pn p(x 1 , x 2 , . . . , x n ) := i=0 mi With monomials mi of degree d e g(mi ) = d being products of the form mi = ai · Qd j=1 x j and x j ∈ X. ANF The Algebraic Normal Form of a polynomial is the sum of its monomials (that can be any product of available variables) e.g.: [[p(x,y,z) = xyz+xy+z ]] CNF In order to run a system of equations through a SAT solver one needs a description of the system that sat solvers can work with. The Conjunctive Normal Form (CNF) is a format to write down equations in boolean logic using only a conjunction of disjunctions (or clauses). The format is relatively simple. The formula (v 1 ∨ ¬v 2 ) ∧ (v 2 ∨ v 3 ) ∧ (v 1 ∨ v 3 ∨ v 4 ) would be encoded as: c p 1 2 1 t h i s i s a comment cnf 4 3 −2 0 3 0 3 4 0 ANF to CNF conversion Another problem concerning the modeling of a cipher for the purpose of applying algebraic cryptanalysis is, that given a system of polynomials over GF(2) one must convert them into a CNF to be able to apply a sat solvers to it. There are many different CNF that satisfy a given polynomial system; among which a system that only consists of one clause per variable. 6 1.3 Side channel cryptanalysis Modern ciphers are especially hardened against conventional cryptanalysis e.g. linear [17] and differential cryptanalysis [5]. While conventional cryptanalysis aims at identifying weaknesses in algorithms side channel analysis relies on information leakage in implementations of cryptographic algorithms; i.e. the implementation of an otherwise secure algorithm might still leak enough information to recover the key used. This leaked information is considered to be side channel information. A variety of things like timing behaviour [4], power consumption [6], electro magnetic radiation, and sound [2] can be used as side channel information. Using this information alone the key in many cases can be recovered within neglectable time. However this method imposes additional assumptions on the attacker. 1.4 Algebraic cryptanalysis Algebraic cryptanalysis [3] aims at breaking a primitive by finding and solving a suitable algebraic description of the primitive. An algebraic description is a system of equations that models the cipher such that the equation system describes the encryption function algebraically. Solving this system with known variables set is now equivalent to learning the unknown variables (e.g. the key of a cipher). If solving the system right ahead is infeasible one can guess the value of some of the variables to further simplify the problem. Any symmetric cipher has (at least) two inputs: the key and the plain-text; and the cipher-text output. If and attacker has a suitable algebraic description (i.e. one which allows fast determination of its satisfiability) of the primitive of interest and enough plain-/cipher-text pairs to limit the number of satisfying keys to a single key, that key can be recovered. 1.4.1 Algebraic representation of a cipher When applying algebraic cryptanalysis to a cipher it is important to find a “good” algebraic description of the cipher. Since it is hard to model the cipher directly one has to model the structure of the cipher and create equation systems for every part of the cipher. These partial systems are chained using intermediate variables to create a single bigger system that fully describes the cipher. The intermediate variables are also useful when it comes to keeping the size of the actual equations small. It is very important, that the system specifies the cipher (meaning that every solving constellation of variables would also work with the cipher). In this work all modeling is done using polynomials in GF (2)[x 0 , x 1 , . . .] or logical equations in CNF(Conjunktive Normal Form) created from the truth table that models the function of interest. 1.4.2 Solving methods Given an algebraic representation (ANF or CNF) of a cipher and a sufficient number of known plain/cipher-text pairs in order to recover the secret key the known information is added to the system. Now the secret key can be found by finding a solution to the system. If it is not possible to solve the system right away one can guess a number of key bits to help the solving algorithms by reducing the number of unknowns. Guessing key bits requires exponentially (in the number of guessed key bits) many runs of the solving algorithm. 1.4.3 SAT solvers A SAT solver is a program that gets a logical formula written as CNF as input and determines whether the formula is satisfiable; the sat solver proves this by producing a satisfying setting for all variables in the formula. Most SAT solvers today work with variants of the DPLL algorithm originally introduced by 7 [10]. In our experiments we used Cryptominisat[16], a sat solver that extends the DPLL algorithm to make use of linear equations (XOR clauses) in the system. Cryptominisat Cryptominisat [16] is a SAT solver that uses a variant of DPLL. It extracts linear equations from the CNF and uses Gaussian Elimination to solve them; these solutions are then used to aid the DPLL algorithm. Also cryptominisat allows to directly write down XOR clauses (that define the xor of all their variables) in CNF. Such XOR clauses look like this: x 2340 is equivalent to the linear equation x2 + x3 + x4 = 0 1.4.4 Measuring attack costs Since in algebraic cryptanalysis there is no notion of an access to an encryption or decryption oracle, it’s not possible to directly compare an algebraic attack to brute force. We are going to compare the estimated run time of our attacks with the estimated time for an brute force. If no key bits are guessed this time T is simply the average time to determine satisfiability TSAT for the given system. If n key bits are guessed there are 2n different settings of which only one is correct; now the average time to recover the key is Tav g = 2n−1 ∗ TU N SAT . In worst case all 2n settings have to be processed puting the worst case time for key recovery Tworst = 2n ∗ TU N SAT . The time required to brute force the key is estimated using the average time required to do one encryption on the same hardware as the SAT solver is running. This time is Tbrut e f or ce = Tenc ∗ 2l−1 on average; l is the key size in bits and Tenc is the time required to test a single key. 1.4.5 Algebraic side channel cryptanalysis The concepts of algebraic and side channel cryptanalysis can be combined by adding side channel information to the equation system or CNF. Adding side channel information can have interesting effects on SAT solving (e.g. UNSAT might be easier to determine than SAT due to conflicts between guessed key bits and known Hamming weights). In this work we present an algebraic attack on a full round version of the CSA block cipher that is using side channel information. 8 2 The LED Family of Block Ciphers The LED family of block ciphers introduced in [13] has a design very similar to that of the Rijndael [18] Algorithm that was choosen as the Advanced Encryption Standard (AES) in 2010. The major differences are a smaller 4-bit S-Box (that originates from the PRESENT [8] cipher) and a very simplistic key schedule. Every four rounds a roundkey is XORed into the state then the state is transformed using the not keyed round function for another four rounds. After the final transformation the last roundkey is XORed into the state. 2.0.6 Key schedule LED [13] employs a very minimalistic key schedule. While LED64 uses the same key for every step the other variants split a bigger key into two pieces and (if necessary) pad the smaller piece to 64 bit length these two 64bit round keys are then being used in an alternating fashion; padding is done by appending a prefix of the first key with suitable length. LED80 uses the first 64 bits for the first key and last 16 bits padded with the first 48 bits for the second key. LED128 just splits the 128 bit long key into two 64 bit keys. Figure 2.1.: LED encryption function [13] LED64: LED80/96/128: A key schedule that is this simple would directly lead to instances of slide attacks [7].However, the design of the round function (mainly the AddConstants part) turns every round into a different permutation and thus prevents such attacks from working on LED. 2.0.7 Round function LED operates on a state that consists of 16 4-bit cells. The 16 4-bit cells are arranged in 4 columns and 4 rows. This only matters for the description of the round function since parts of it operate on single cells, rows, and columns of the state. A one dimensional array s would be arranged like this: s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 The LED round function has many similarities to that of the AES block cipher. It consists of four parts AddConstants, SubCells, ShiftRows, and MixColumns. 9 Figure 2.2.: LED round function [13] AddConstants The AddConstants part of the round function serves to prevent slide attacks [7] that would threaten the cipher due to its very simple key schedule. At the begin of every round different constants are being XORed into the state. The constants follow this scheme: 0 1 2 3 (r c5 ||r c4 ||r c3 ) (r c2 ||r c1 ||r c0 ) (r c5 ||r c4 ||r c3 ) (r c2 ||r c1 ||r c0 ) 0 0 0 0 0 0 0 0 with r c being a six bit wide linear feedback shift register with r c5 ⊕ r c4 ⊕ 1 as its feedback function. The initial value of the r c is all six bits zero. The values of r c are: round rc 0 01 1 03 2 07 3 0f 4 1f 5 3e 6 3d 7 3b 8 37 9 2f 10 1e 11 3c round rc 12 39 13 33 14 27 15 0e 16 1d 17 3a 18 35 19 2b 20 16 21 2c 22 18 23 30 round rc 24 21 25 02 26 05 27 0b 28 17 29 2e 30 1c 31 38 32 31 33 23 34 06 35 0d round rc 36 1b 37 36 38 2d 39 1a 40 34 41 29 42 12 43 24 44 08 45 11 46 22 47 04 SubCells The SubCells step of the LED round function substitutes every nibble according to this Sbox: 0 12 1 5 2 6 3 11 4 9 5 0 6 10 7 13 8 3 9 14 10 15 11 8 12 4 13 7 14 1 15 2 The S-Box is identical to the one being used in PRESENT [8]. It also is the only source of non-linearity in the cipher so that without it one could easily break LED using Gaussian elimination. ShiftRows Shift Rows operates on the rows of the state and works exactly like its counterpart in AES [18]. Every row is rotated left by its index minus one. s1 s2 s3 s4 s1 s2 s3 s4 s5 s6 s7 s8 s s7 s8 s5 → 6 s9 s10 s11 s12 s11 s12 s9 s10 s13 s14 s15 s16 s16 s13 s14 s15 10 Even though this part of the round function is very simple, it becomes a powerful diffusion layer for the cipher in combination with MixColumns. MixColoumns Just like AES [18] LED uses a maximum distance separable code to transform the columns of its state. And just as in AES [18] this step is called “MixColumns”. This step consists of multiplying every column of the state with a fixed matrix that has the maximum distance sparse property. LED uses a matrix A over the extension field (G F )(2)[X ]/(X 4 + X + 1): 4 4 1 2 2 0 1 0 0 8 6 5 6 0 0 1 0 A= = . 11 14 10 9 0 0 0 1 2 2 15 11 4 1 2 2 While the SubCells part of the round function delivers all the non-linearity (confusion) for the cipher, diffusion is achieved by MixColumns and ShiftRows; every cell in the output column depends on every cell in the input column. 2.1 Previous cryptanalysis of LED In 2012 Abed, Forler, List, Lucks, and Wenzel published the first attack on full round LED64 and LED128 [1] using independent bitcliques and requiring 263.34 and 2127.23 encryptions respectively. A similar attack [14] was proposed by Jeong, Kang, Lee, Sung, and Hong int the same year. Also in 2012 Jovanovic, Kreuzer, and Polian published a fault attack on LED64 [15] requiring only a single fault injection. In his Bachelor Thesis [12] Michael Dollichon attempted to break LED using Gröbner bases. 2.2 Generic attack on 8 rounds of LED80 and LED128 All variants of the LED block cipher that use more then 64 bits of key are susceptible to an generic attack on up to 8 rounds. These reduced variants can be written as: LE Dk1 ,k2 (x) := g( f (x ⊕ k1 ) ⊕ k2 ) ⊕ k1 where f and g are four rounds of the cipher that are not keyed. And k1 and k2 are the corresponding 64bit keys. The key recovery attack on these reduced versions of LED need 2 pairs of known plain/cipher-text namely (p0 , c0 ) and (p1 , c1 ). Given the knowledge of k1 one can easily compute k2 as follows: k2 = g −1 (c0 ⊕ k1 ) ⊕ f (p0 ⊕ k1 ) An attacker now simply searches for the correct value of k1 , computes a candidate for k2 , and tests this candidate against the second plain-/cipher-text pair. Attacks as suggested above are commonly known as “Meet in the Middle Attack” originally introduced by [11]. The complexity for this attack is in average equivalent 264 8 round LED encryptions and needs a neglectable amount of memory. As for comparison a brute force attack needs in average 2127 and 279 trial decryptions respectively; and 2 pairs of plain-/cipher-text as well. 11 2.3 An algebraic attack on 3 rounds of LED64 2.3.1 A note on reduced variants of LED The 3 round variant of LED we are looking at is one key injection followed by three unkeyed transformations of the state and one more key injection. Seeing that LED has 32 or 48 rounds; breaking only 3 rounds suggests that LED is rather resistant against this type of attack. 2.3.2 An algebraic model for the LED round function AddConstants AddConstants only inverts certain bits in the state. That is modeled by inverting the variables that correspond to these bits of the state. SubCells For the PRESENT [8] Sbox there exists a quadratic system of 4 equations describing the SBox: x 1 · x 2 + x 0 + x 1 + x 3 + y3 = 0 x 0 · x 2 + x 3 · y0 + x 0 + x 1 + y1 + 1 = 0 x 0 · x 1 + x 3 · y2 + x 1 + x 2 + y1 + y2 + 1 = 0 x 0 · x 1 + x 0 · x 2 + x 0 + x 1 + y0 + y2 + y3 + 1 = 0 It turned out however, that the interpolation polynomials yield a CNF more suited for cryptominisat [16] to solve: y3 = x 1 · x 2 + x 0 + x 1 + x 3 y2 = x 0 · x 1 · x 3 + x 0 · x 2 · x 3 + x 1 · x 2 · x 3 + x 0 · x 1 + x 0 · x 2 + x 0 + x 2 y1 = x 0 · x 1 · x 3 + x 0 · x 2 · x 3 + x 0 · x 2 + x 0 · x 3 + x 2 · x 3 + x 0 + x 1 + 1 y0 = x 0 · x 1 · x 3 + x 0 · x 2 · x 3 + x 1 · x 2 · x 3 + x 1 · x 2 + x 0 + x 2 + x 3 + 1 ShiftRows Shift Rows can be viewed as an operation that only swaps cells in the state. One can simply apply ShiftRows to an array of variables prior to the MixColumns step to achieve the desired permutation of the inputs for the MixColumns part. MixColumns Since we are trying to construct a system of polynomials in GF (2)[X 1 , X 2 , . . . , X n ] that specifies LED one has to model multiplication in the extension field that is used by LED for GF (2)[X ]. That can easily be done by modeling a multiplication with X as a matrix-vector multiplication with: 0 0 1 1 1 0 0 0 0 1 0 0 0 0 1 0 With this technique and ⊕ as addition one can adapt a “square and multiply” alike algorithm for arbitary multiplications in LEDs extension field. The simplest way to model the complete MixColumns 12 step now would be to simply use the linear polynomials that will be created by multiplying A with a vector of state variables resulting in these polynomials for every column: y0 = x 2 + x 4 + x 9 + x 13 y1 = x 0 + x 3 + x 5 + x 10 + x 14 y2 = x 0 + x 1 + x 6 + x 8 + x 11 + x 12 + x 15 y3 = x 1 + x 7 + x 8 + x 12 y4 = x 0 + x 3 + x 5 + x 6 + x 8 + x 10 + x 13 + x 14 y5 = x 0 + x 1 + x 4 + x 6 + x 7 + x 8 + x 9 + x 11 + x 12 + x 14 + x 15 y6 = x 1 + x 2 + x 5 + x 7 + x 8 + x 9 + x 10 + x 13 + x 15 y7 = x 2 + x 4 + x 5 + x 9 + x 11 + x 12 + x 13 y8 = x 1 + x 3 + x 4 + x 5 + x 6 + x 7 + x 8 + x 9 + x 11 + x 15 y9 = x 0 + x 2 + x 5 + x 6 + x 7 + x 8 + x 9 + x 10 + x 12 y10 = x 0 + x 1 + x 3 + x 6 + x 7 + x 8 + x 9 + x 10 + x 11 + x 13 y11 = x 0 + x 2 + x 3 + x 4 + x 5 + x 6 + x 8 + x 10 + x 14 + x 15 y12 = x 1 + x 5 + x 9 + x 10 + x 11 + x 13 + x 15 y13 = x 2 + x 6 + x 10 + x 11 + x 12 + x 14 y14 = x 0 + x 3 + x 4 + x 7 + x 11 + x 12 + x 13 + x 15 y15 = x 0 + x 4 + x 8 + x 9 + x 10 + x 11 + x 12 + x 14 + x 15 Experiments with cryptominisat [16] however, have shown on average four times shorter time to decide the satisfiability of the system with a MixColumn layer being modeled as for four matrix multiplications with intermediate state variables giving us four times four systems every round of this form: y0 = x 4 y1 = x 5 y2 = x 6 y3 = x 7 y4 = x 8 y5 = x 9 y6 = x 10 y7 = x 11 y8 = x 12 y9 = x 13 y10 = x 14 y11 = x 15 y12 = x 2 + x 4 + x 9 + x 13 y13 = x 0 + x 3 + x 5 + x 10 + x 14 y14 = x 0 + x 1 + x 6 + x 8 + x 11 + x 12 + x 15 y15 = x 1 + x 7 + x 8 + x 12 2.3.3 Performance of the attack To conduct the attack one has to test 231 guesses for the key bits on average. The effort to test a guess is the time needed to determine the satisfiability of the one CNF. In our experiments we used cryptominisat[16]. We measured the time needed to determine unsatisfiability of 1000 systems with random settings for plain-text/cipher-text and guessed keybits. In the following table we summerize the results of the conducted experiments as the number of rounds, number of guessed key bits, the empirical average of our measurements, their maximum and minimum, the empiric stdandard deviation and the upper bound of the 99% confidence interval of the average for this unknown distribution. 13 # rounds # bits avg. max. min. std. deviation upper bound 2 16 19 37.7 13.19 4.13 21.11 3 32 20.30 35.78 10.86 3.75 22.82 4 48 20.11 85.5 11.34 4.49 23.39 32 48 445.14 604.51 289.67 34.90 944.99 Using an optimized implementation we measured the average time for 232 encryptions. Based on these experiments we estimate the time required to conduct the attacks described above using brute force instead of a SAT solver. # rounds guessed key bits estimated average 2 16 2516582.40 3 32 57.79 4 32 78.52 32 48 18.98 Starting with four rounds brute force is faster then our attack. 2.4 A side channel attack on the full round LED cipher If the Hamming weight of the state (per cell) can be accessed as side channel information, it is possible to stage a key recovery attack against full round versions. It was possible to recover the used key within seconds if either 2 consecutive rounds of the first/last step are available or 7 consecutive rounds anywhere in the cipher. The Hamming weights are extracted after the SubCells part of their round. The side channel information is then integrated into the encoder described above. In the following we describe two algorithms that can be used to encode Hamming weights. 2.4.1 Modeling side channel information Extracted side channel information is the Hamming weight of every single cell of the state right after a SubCells step. Since every cell has 4-bit the Hamming weight of a cell can be any number from 0 to 4. in ANF For the task of encoding Hamming weights in ANF we used an algorithm that uses two simple observations. If x out of n variables are set to 1 there exists only one monomial m with deg(m) = x that evaluates to 1 in any such setting (i.e. the sum of all monomial with degree x is 1). If less then x variables are set to 1 all these monomial evaluate to 0. Also at least one monomial m with deg(m) = x + 1 will evaluate to 1 if more then x variables are set to 1. A Hamming weight w of the four variables x 0,1,2,3 would be encoded as: w = 0 → x 0 = 0, x 1 = 0, x 2 = 0, x 3 = 0 w = 1 → x 0 + x 1 + x 2 + x 3 = 1, x 0 x 1 = 0, x 0 x 2 = 0, x 0 x 3 = 0x 1 x 2 = 0, x 1 x 3 = 0 w = 2 → x 0 x 1 + x 0 x 2 + x 0 x 3 + x 1 x 2 + x 1 x 3 = 1, x 0 x 1 x 2 = 0, x 1 x 2 x 3 = 0, x 0 x 2 x 3 = 0, x 0 x 1 x 3 = 0 w = 3 → x 0 x 1 x 2 + x 1 x 2 x 3 + x 0 x 2 x 3 + x 0 x 1 x 3 = 1, x 0 x 1 x 2 x 3 = 0 w = 4 → x0 x1 x2 x3 = 1 14 in CNF Simpler (and thus easier to solve) equations can be generated by directly encoding the Hamming weight in CNF. The idea behind this algorithm is that if out of k bits exactly n < k are zero any disjunction of n + 1 bits will be true. Also any conjunction of ((k − n) + 1) will be zero (a fact that can be rewritten as an disjunction of inverted bits). This concept yields a CNF without having to encode the information as polynomials beforehand. Also the CNF produced has good properties as it yields only a few relatively short clauses. The Hamming weight w of (x 0 , x 1 , x 2 , x 3 ) would be encoded like this: w = 0 → ¬x 0 ∧ ¬x 1 ∧ ¬x 2 ∧ ¬x 3 w = 1 → (¬x 0 ∨ ¬x 1 )∧ (¬x 0 ∨ ¬x 2 )∧ (¬x 0 ∨ ¬x 3 )∧ (¬x 1 ∨ ¬x 2 )∧ (¬x 1 ∨ ¬x 3 )∧ (¬x 2 ∨ ¬x 3 )∧ x0 ∨ x1 ∨ x2 ∨ x3 w = 2 → (¬x 0 ∨ ¬x 1 ∨ ¬x 2 )∧ (¬x 0 ∨ ¬x 1 ∨ ¬x 3 )∧ (¬x 0 ∨ ¬x 2 ∨ ¬x 3 )∧ (¬x 1 ∨ ¬x 2 ∨ ¬x 3 )∧ (x 0 ∨ x 1 ∨ x 2 )∧ (x 0 ∨ x 1 ∨ x 3 )∧ (x 0 ∨ x 2 ∨ x 3 )∧ (x 1 ∨ x 2 ∨ x 3 ) w = 3 → (¬x 0 ∨ ¬x 1 ∨ ¬x 2 ∨ ¬x 3 )∧ (x 0 ∨ x 1 )∧ (x 0 ∨ x 2 )∧ (x 0 ∨ x 3 )∧ (x 1 ∨ x 2 )∧ (x 1 ∨ x 3 )∧ (x 2 ∨ x 3 ) w = 4 → x0 ∧ x1 ∧ x2 ∧ x3 We conducted 1000 experiments to determine the average time to recover the key with side channel information in form of the Hamming weights of 7 consecutive rounds. On average it took 14.68 seconds to recover the key; with a minimum of 1.38 seconds and a maximum of 129.38 seconds. 15 3 The CSA block cipher In this chapter we will explain our attacks on the DVBCSA block cipher. First we will give a description of the encryption process. Then we will describe our algebraic description of the cipher. After that we will describe our attacks on the cipher. As in the previous chapter we will first consider a pure algebraic attack on a reduced round version and then add side channel information to the equation system. 3.1 DVBCSA The DVBCSA (Digital Video Broadcasting Common Scrambling Algorithm) encryption standard was standardized by the ETSI in 1994 but most details about the standard remained secret. In 2002 a software implementation of DVB-CSA appeared on the internet and was reverse engeneered giving a complete description of the cipher. The block cipher used in DVBCSA operates with 64-bit keys on 64-bit blocks. It consists of 56 identical rounds that use eight bit round keys. In DVBCSA the block cipher is used to encrypt up to 23 64-bit blocks using the CBC mode in reverse block order (starting with the last block). The first block then is used as IV for the CSA stream cipher to all but the first block of the intermediate ciphertext. This scheme is completely deterministic and does not expand (padding IV) the message when encrypted. However in many cases it was observed that DVBCSA is used with 48-bit keys with 2 bytes of checksum padding the key to 64-bit. Figure 3.1.: DVB-CSA encryption process [19] Block 1 Block 2 Block 3 Block... ⊕ ⊕ ⊕ ⊕ E E E E E Block 1 Block 2 Block 3 Block... Block 23 K Block 1 ⊕ Stream cipher Block 2 ⊕ Block 3 ⊕ Block 23 Block... ⊕ Block 23 Keystream 3.2 The design of the CSA block cipher 3.2.1 Key schedule The Key schedule of the CSA block cipher makes use of a fixed bit index permutation (permute_block()) that operates on 64-bit words. The key schedule expands a 64 bit key into 56 8bit round keys. Since 16 permute_block() like all bit permutations is completely linear the key schedule is linear; i.e. every bit of every round key depends on exactly one bit of the original key. w i = per mut e_ bl ock(w i+1 ⊕ 0x0101010101010101 ∗ (i + 1)) ⊕ (0x0101010101010101 ∗ i) w6 = K ⊕ 0x0606060606060606 The 56 eight bit round keys are w0 ||w1 ||w2 ||w3 ||w4 ||w5 ||w6 (starting with the first roundkey). Table 3.1.: per mut e_ block(X ) permutes the bits in X as in this table (octal notation): 0 1 2 3 4 5 6 7 00 19 27 55 46 1 15 36 22 10 56 61 39 21 54 58 50 28 20 7 29 51 6 33 35 20 16 30 47 30 32 63 10 11 4 38 40 62 26 40 18 12 52 37 53 50 23 59 41 17 31 0 25 43 60 44 14 2 13 45 48 3 60 70 49 8 34 5 9 42 57 24 3.2.2 The round function The CSA block cipher is made up of 56 identical rounds of which each uses a 8-bit round key. The round function consists of six XOR operations on application of a fixed S-Box and fixed bit permutation. Figure 3.2.: DVB-CSA block cipher round function [19] b0,i-1 b1,i-1 b2,i-1 b3,i-1 b4,i-1 b5,i-1 b6,i-1 b7,i-1 KS[i] S-Box P b0,i b1,i b2,i b3,i b4,i b5,i b6,i b7,i 17 S-Box 00 10 20 30 40 50 60 70 80 90 a0 b0 c0 d0 e0 f0 Table 3.2.: (the lower nibble indexes the columns, hexadecimal notation) 0 1 2 3 4 5 6 7 8 9 a b c d e 3a ea 68 fe 33 e9 88 1a 83 cf e1 7f ba e2 38 e8 27 61 95 0c 36 e5 70 a2 06 82 7c 17 a3 26 be 7a 6d 47 c1 51 8f f3 cc 5b 67 bd cd 18 08 ff 69 ef 03 4e 48 4a 84 3f b4 10 04 dc f5 5c 16 ab ac 4c f1 6a 2f 3c 3b d4 d5 94 d0 c4 63 71 a1 f9 4f 2e aa c5 56 e3 39 93 ce 65 64 e4 6c 19 42 79 dd ee 96 f6 8a ec 1e 85 53 45 de 7e 0a 9a 13 2a 9d c2 5e 5a 1f 32 35 9c a8 73 29 3d e7 92 87 1b 2b 4b a5 57 97 40 15 e6 bc eb c3 34 2d b8 44 25 a4 1c c7 23 ed 90 6e 50 99 9e 4d d9 da 8d 6f 5f 3e d7 21 74 86 df 6b 8e 5d 37 11 d2 28 75 d6 a7 77 24 bf f0 b0 02 f8 fc 81 09 b1 01 76 91 7d 0f c8 a0 f2 cb 78 d1 f7 e0 b5 98 22 b3 20 1d a6 db 7b 59 9f ae fb d3 b6 ca 43 72 07 f4 d8 41 14 55 0d 54 8b ad 46 0b af 80 52 2c fa 8c 89 66 fd b2 a9 9b f 12 49 c9 c6 62 58 bb 30 0e 00 05 b7 60 31 b9 c0 PBox The P function is a bit index permutation. 0 1 2 3 4 5 6 7 P= . 1 7 5 4 2 6 0 3 Like all other steps of the CSA round function except the S-Box it is linear. 3.3 Previous cryptanalysis of CSA In 2011 Tews, Weiner, and Wälde presented a time memory trade-off [19] to break DVBCSA within the average lifetime of a key (7 seconds). However this attack uses some assumptions about how DVBCSA is used. Most importantly the attack exploits the fact that in almost all its applications DVBCSA is used with a 48 bit key space (checksums within the key) and that repeating all zero messages in plain text of tv stations can be observed; as well as the fact that DVBCSA is completely deterministic meaning that the same key and message will always result in the same cipher-text. In 2004 Weinmann and Wirt found a practical attack [20] on the DVB stream cipher that exploits very short cycle length in the stream ciphers output. A first analysis of the block cipher was done by Weinmann and Wirt in 2004 in which they ruled out straight forward linear and differential cryptanalysis. They also ruled out algebraic cryptanalysis based on the high degree and density of all possible interpolations of the S-Box. In 2005 Wirt published a fault attack [21] on the block cipher. 18 3.4 A Meet in the Middle Attack on up to 15 rounds of CSA The key schedule of the CSA block cipher produces 57 8-bit round keys r0..56 . Also every bit of a round key depends on only one bit of the actual key. Another Observation is that ri∗8..(i+1)∗8 is a bit permutation of the 64-bit key XOR the constant 0x iiiiiiii . Therefore it is very easy to stage a Meet in the Middle attack on the first eight rounds using only 232 trial encryptions to recover the key. One decrypts four rounds of the cipher-text with all possible round keys for these four rounds and stores these intermediate values and their corresponding round keys in a sorted table or other data structure that allows efficient lookups. The memory consumption of this table is about 12 ∗ 232 byte (i.e. 48 GB) and can be precomputed. To recover the key one now encrypts the plain-text with all possible round keys for the first four rounds. Once an intermediate cipher-text is produced that is also in the table a key is found that will encrypt the plain-text to the cipher-text. The same attack can be applied to 15 rounds of the cipher by guessing the last seven round keys leaving only eight unknown bits for the first eight rounds. These bits are: 5 9 26 32 44 54 55 60 The cost of this attack are worth approximately 260 trial encryptions. We are going to compare any attacks against CSA for less then 15 rounds against this generic attack since it is faster than brute force. The memory consumption in this case is only a few bytes since the memory trade-off is used only to recover the 8 remaining unknown bits of the key. 3.5 An algebraic cryptanalysis of the CSA block cipher In this section we are going to present an algebraic attack on up to 15 rounds of the block cipher. The attack does not exploit potentially present checksums within the key and recovers the 64-bit key faster then brute force or the previously presented algebraic attack. The attack guesses the first 4 round keys (and therewith 32 bit of the original key). After that the remaining 32 bits of the key are being determined (if possible) by applying cryptominisat [16]. 3.5.1 An algebraic description of the CSA round function In order to apply algebraic cryptanalysis to this cipher one must find a suitable algebraic description of it. Most parts of the round function are purely linear and will result in linear combinations of the input variables. The only nonlinear part is the S-Box. Modeling the S-Box algebraically is done by reading a CNF from its truth table. An unoptimized truth table CNF for an 8 bit S-Box has exactly 2048 clauses each having a length of 9. Using the PoLyBoRi [9] encoder we used the interpolation polynomials from the S-Box and obtained a system of 916 clauses that gives a slight speedup compared to the trivial system of clauses. The equation generator that is used can be found in the appendix. 3.6 Key bit guessing strategy To aid cryptominisat by providing material that is easily propagated throughout the equation system we choose to guess the key bits corresponding to the first 4 round keys. These key bits (starting at index 0) have the indices: 17 56 49 7 8 52 41 30 55 18 4 10 46 1 37 58 33 44 15 48 59 13 61 28 22 53 24 26 16 42 23 47 Having guessed these four round keys one can encrypt the plain-text to an intermediate cipher text after the 4th round. Thus reducing the attack to one that attacks 4 rounds less. 19 3.6.1 Experimental data on the speed of the attack In order to compare the attack to brute force we created and solved 1000 random systems for 15 and 16 rounds of the cipher. Since the attack guesses 32-bits of the key all but one system will be in NSAT. We were interested in the average time cryptominisat [16] needs to determine that a system is unsolvable (UNSAT). Therefore the 1000 systems were created with random keys and plain-texts and random guesses for the first 4 round keys. The average time to prove UNSAT for a system with the optimized set of clauses (and having the fist 4 round keys guessed) for the S-Box is 12.31s. This puts the time for an successful attack to 52876928281 seconds (1677 years). To run the attack in near real time would require excessive amounts of resources and totally outweight the gain (remember CSA is mostly used for paytv DRM in a setting that changes the key about every 7 seconds). To estimate the time required for brute force we conducted similar experiments with optimized software implementations of the CSA block cipher. In these experiments the average time to do a single encryption was 0.06184µs. The estimate for a successful brute force attack is 36176 years. 3.7 A algebraic side channel analysis of the CSA block cipher We observed that we were not able to recover the key (using SAT solvers) even if we add the Hamming weights of every S-Box output to the equation system. However once the Hamming weights of the S-Box input bytes were available as well cryptominisat [16] was able to solve systems for the full cipher within a minute. This observation is interesting since the side channel information for the first 10 rounds (20 Hamming weights) seems to suffice to recover the key while when only using the Hamming weight after the S-Box 56 Hamming weights do not suffice to recover the key in acceptable time. If less Hamming weights are available they can be used to support an algebraic attack on full round CSA. In our experiments adding the same side channel information as in the previous section except only for 5 rounds (rounds 3 to 7 inclusive) enabled cryptominisat to determine UNSAT within 412ms on average. We conducted 1000 experiments the maximum time required to determine UNSAT was 500ms while the minimum was 300ms. On average an attacker will have to process 231 systems until a fiting key is found. The time to do this would be 1024.03 days (2.8 years) on a single core. All experiments were conducted on a 2.3 GHz AMD Opteron CPU. 20 4 Conclusion In this work we attempted to break the security of the LED and CSA block ciphers. We found attacks on both primitives; however these attacks use strong assumptions (i.e. the availability of side channel information). When attempting to break these ciphers without the use of side channel informations we were able to attack reduced versions of both ciphers. Even though the attacks presented in this work do not pose a direct threat to users of these ciphers, they do discourage the use of both ciphers in a setting in which side channel information can be obtained by an attacker. Since counter measures against side channel attacks consume space in hardware implementations these attacks hurt the value of both ciphers in lightweight cryptography application. Future work could focus on reducing assumptions and increasing the performance of the attacks. 21 Bibliography [1] F. Abed, C. Forler, E. List, S. Lucks, and J. Wenzel. Biclique Cryptanalysis of the PRESENT and LED Lightweight Ciphers. Technical report, Cryptology ePrint Archive, Report 2012/591, 2012. [2] D. Asonov and R. Agrawal. Keyboard acoustic emanations. In Security and Privacy, 2004. Proceedings. 2004 IEEE Symposium on, pages 3–11. IEEE, 2004. [3] G.V. Bard. Algebraic cryptanalysis. Springer, 2009. [4] D.J. Bernstein. Cache-timing attacks on aes. 20050414. pdf, 2005. URL: http://cr. yp. to/antiforgery/cachetiming- [5] E. Biham and A. Shamir. Differential cryptanalysis of DES-like cryptosystems. Journal of CRYPTOLOGY, 4(1):3–72, 1991. [6] E. Biham and A. Shamir. Power analysis of the key scheduling of the AES candidates. In Proceedings of the second AES Candidate Conference, pages 115–121, 1999. [7] A. Biryukov and D. Wagner. Slide Attacks. In Fast Software Encryption, pages 245–259. Springer, 1999. [8] A. Bogdanov, L. Knudsen, G. Leander, C. Paar, A. Poschmann, M. Robshaw, Y. Seurin, and C. Vikkelsoe. PRESENT: An ultra-lightweight block cipher. Cryptographic Hardware and Embedded SystemsCHES 2007, pages 450–466, 2007. [9] M. Brickenstein and A. Dreyer. POLYBORI: A Gröbner basis framework for Boolean polynomials. Keywords: Gröbner basis, formal verification, Boolean polynomials, algebraic cryptoanalysis, satisfiability, 23, 2007. [10] M. Davis and H. Putnam. A computing procedure for quantification theory. Journal of the ACM (JACM), 7(3):201–215, 1960. [11] W. Diffie and M.E. Hellman. Special Feature Exhaustive Cryptanalysis of the NBS Data Encryption Standard. Computer, 10(6):74–84, 1977. [12] Michael Dollichon. Kryptanalyse der Blockciffre Light Encryption Device (LED), 2012. [13] J. Guo, T. Peyrin, A. Poschmann, and M. Robshaw. The LED block cipher. Cryptographic Hardware and Embedded Systems–CHES 2011, pages 326–341, 2011. [14] K. Jeong, H.C. Kang, C. Lee, J. Sung, and S. Hong. Biclique Cryptanalysis of Lightweight Block Ciphers PRESENT, Piccolo and LED. [15] K. Jeong and C. Lee. Differential Fault Analysis on Block Cipher LED-64. Future Information Technology, Application, and Service, pages 747–755, 2012. [16] Karsten Nohl Mate Soos and Claude Castelluccia. Extending SAT Solvers to Cryptographic Problems. 2009. [17] M. Matsui. Linear cryptanalysis method for DES cipher. In Advances in Cryptology—EUROCRYPT’93, pages 386–397. Springer, 1994. [18] F.P.U.B. NIST. 197,Advanced Encryption Standard (AES), november 2001. 22 [19] E. Tews, J. Wälde, and M. Weiner. Breaking DVB-CSA. WEWoRC West European Workshop on Reasearch in Cryptography 2011, pages 41–45, 2011. [20] R.P. Weinmann and K. Wirt. Analysis of the DVB (Common Scrambling Algorithm). In Communications and Multimedia Security, pages 195–207. Springer, 2005. [21] K. Wirt. Fault attack on the DVB common scrambling algorithm. Computational Science and Its Applications–ICCSA 2005, pages 511–577, 2005. 23 A Appendix 1 3 5 7 from sage . s a t . c o n v e r t e r s . p o l y b o r i import CNFEncoder from sage . s a t . s o l v e r s . dimacs import DIMACS import i t e r t o o l s import g e t o p t import f u n c t o o l s import s y s import random 9 11 R=BooleanPolynomialRing (40000 , " x " ) V=R^4 # 4 t u p l e o f p o l y n o m i a l s 13 SBOX=mq . SBox (12 , 5 , 6 , 11 , 9 , 0 , 10 , 13 , 3 , 14 , 15 , 8 , 4 , 7 , 1 , 2) # t h e p r e s e n t sbox 15 RC=(0x01 , 0x03 , 0x07 , 0x0F , 0x1F , 0x3E , 0x3D , 0x3B , 0x37 , 0x2F , 0x1E , 0x3C , 0x39 , 0x33 , 0x27 , 0x0E , 0x1D , 0x3A , 0x35 , 0x2B , 0x16 , 0x2C , 0x18 , 0x30 , 0x21 , 0x02 , 0x05 , 0x0B , 0x17 , 0x2E , 0x1C , 0x38 , 0x31 , 0x23 , 0x06 , 0x0D , 0x1B , 0x36 , 0x2D , 0x1A , 0x34 , 0x29 , 0x12 , 0x24 , 0x08 , 0x11 , 0x22 , 0x04 ) 17 19 21 23 25 27 29 GF16MUL2=m a t r i x (R , 4 , 4 ) # t h i s m a t r i x m u l t i p l i e s an element i n GF( 2 ) [ x ] / x ** 4 + x + 1 with (0 ,0 ,1 ,0) GF16MUL2[0]=(0 ,0 ,1 ,1) GF16MUL2[1]=(1 ,0 ,0 ,0) GF16MUL2[2]=(0 ,1 ,0 ,0) GF16MUL2[3]=(0 ,0 ,1 ,0) d e f b4 ( x ) : l = l i s t (map( lambda i : ( x>>i ) & 1 , ( 0 , 1 , 2 , 3 ) ) ) l . reverse () return tuple ( l ) 31 33 35 37 39 41 43 45 47 49 51 53 d e f b64 ( x ) : l = l i s t (map( lambda i : ( x>>i ) &1 , range (64) ) ) l . reverse () return tuple ( l ) d e f hamming ( v , n ) : x0 , x1 , x2 , x3 = v i f n == 0 : r e t u r n [ x0 , x1 , x2 , x3 ] e l i f n == 1 : r e t u r n [ x0 + x1 + x2 + x3 + 1 , x0 * x1 , x0 * x2 , x0 * x3 , x1 * x2 , x1 * x3 , x2 * x3 ] e l i f n == 2 : r e t u r n [ x0 * x1+x0 * x2+x0 * x3+x1 * x2+x1 * x3+x2 * x3+ 1 , x0 * x1 * x2 , x1 * x2 * x3 , x0 * x2 * x3 , x0 * x1 * x3 ] e l i f n == 3 : r e t u r n [ x0 * x1 * x2 + x1 * x2 * x3 + x0 * x2 * x3 + x0 * x1 * x3 + 1 , x0 * x1 * x2 * x3 ] e l i f n == 4 : 24 55 57 59 61 63 65 67 r e t u r n [ x0 * x1 * x2 * x3 + 1] else : return [] d e f lessthenhamming ( v ,w) : v = l i s t (map( lambda x : i n t ( g e t i d x ( x ) ) , v ) ) r = set ([]) n = len (v) f o r c i n i t e r t o o l s . c o m b i n a t i o n s ( v ,w+1) : r . add ( ( " " . j o i n (map( lambda x : s t r (− x ) , c ) ) )+" 0\n " ) f o r c i n i t e r t o o l s . c o m b i n a t i o n s ( v , ( n−w)+1) : r . add ( ( " " . j o i n (map( lambda x : s t r ( x ) , c ) ) )+" 0\n " ) return " " . join ( l i s t ( r ) ) 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 101 103 105 107 109 111 113 d e f mul ( v , n ) : m = GF16MUL2 b = V((0 ,0 ,0 ,0) ) while n > 0: i f ( n%2) == 1 : b=b+v v = v *m n >>= 1 return b d e f vecprod ( u , v ) : l = l i s t (map( lambda x , y : mul ( x , y ) , u , v ) ) r e t u r n f u n c t o o l s . reduce ( lambda x , y : x+y , l ) def addconsts ( state , r ) : s t a t e [ 4] = s t a t e [ 4] s t a t e [ 8] = s t a t e [ 8] s t a t e [12] = s t a t e [12] tmp = (RC[ r ]>>3)&7 v = V( b4 ( tmp ) ) s t a t e [ 1] = s t a t e [ 1] s t a t e [ 9] = s t a t e [ 9] tmp = RC[ r ]&7 v = V( b4 ( tmp ) ) s t a t e [ 5] = s t a t e [ 5] s t a t e [13] = s t a t e [13] return state + V((0 ,0 ,0 ,1) ) + V((0 ,0 ,1 ,0) ) + V((0 ,0 ,1 ,1) ) + v + v + v + v def s h i f t r o w s ( s t a t e ) : def s h i f t ( x ) : tmp = s t a t e [ x * 4 : x *4+4] tmp = tmp [ x :4]+tmp [ 0 : x ] f o r i i n range ( 4 ) : s t a t e [ x*4+ i ] = tmp [ i ] for i in (1 ,2 ,3) : shift ( i ) return state d e f mix ( v ) : mcol = ( ( 4 , 1 , 2 , 2 ) , ( 8 , 6 , 5 , 6 ) , ( 0 xb , 0 xe , 0 xa , 9 ) , ( 2 , 2 , 0 xf , 0 xb ) ) r e t u r n t u p l e (map( lambda i : vecprod ( v , mcol [ i ] ) , ( 0 , 1 , 2 , 3 ) ) ) d e f mix4th ( v ) : mcol = ( ( 0 , 1 , 0 , 0 ) , ( 0 , 0 , 1 , 0 ) , ( 0 , 0 , 0 , 1 ) , ( 4 , 1 , 2 , 2 ) ) 25 115 r e t u r n t u p l e (map( lambda i : vecprod ( v , mcol [ i ] ) , ( 0 , 1 , 2 , 3 ) ) ) 117 119 121 123 125 127 129 131 133 d e f m i x c o l ( s t a t e , s m a l l=F a l s e ) : def g e t c o l ( x ) : r e t u r n l i s t (map( lambda i : s t a t e [ x+i * 4 ] , range ( 4 ) ) ) def s e t c o l ( c , x ) : f o r i i n range ( 4 ) : s t a t e [ x+i * 4] = c [ i ] f o r i i n range ( 4 ) : i f small : s e t c o l ( mix4th ( g e t c o l ( i ) ) , i ) else : s e t c o l ( mix ( g e t c o l ( i ) ) , i ) return state def l i n s t e p ( s t a t e ) : state = shiftrows ( state ) s t a t e = mixcol ( s t a t e ) return state 135 137 d e f i n j e c t k e y ( s t a t e , key ) : f o r i i n range (16) : s t a t e [ i ] = s t a t e [ i ] + key [ i ] 139 141 143 def p r i n t s ( s ) : print ( s [0:4]) print ( s [4:8]) print ( s [8:12]) p r i n t ( s [12:16]) 145 147 d e f pack4 ( s ) : r e t u r n l i s t (map( lambda i : V( t u p l e ( s [ i * 4 : i * 4+4]) ) , range (16) ) ) 149 151 153 155 157 159 def getequations ( o l d s t a t e , newstate ) : l = [] f o r i i n range (16) : x0 , x1 , x2 , x3 = o l d s t a t e [ i ] x4 , x5 , x6 , x7 = n e w s t a t e [ i ] l = l + [ x1 * x2 + x0 + x1 + x3 + x7 , x0 * x1 * x3 + x0 * x2 * x3 + x1 * x2 * x3 + x0 * x1 + x0 * x2 + x0 + x2 + x6 , x0 * x1 * x3 + x0 * x2 * x3 + x0 * x2 + x0 * x3 + x2 * x3 + x0 + x1 + x5 + 1 , x0 * x1 * x3 + x0 * x2 * x3 + x1 * x2 * x3 + x1 * x2 + x0 + x2 + x3 + x4 + 1] return l 161 163 165 167 169 171 173 d e f e n c r y p t ( p , k , rounds =32, s i d e c h a n n l e=None ) : hamming = [ ] key = pack4 ( b64 ( k ) ) p l a i n = pack4 ( b64 ( p ) ) f o r r i n range ( rounds ) : i f ( r % 4) == 0 : i n j e c t k e y ( p l a i n , key ) plain = addconsts ( plain , r ) p l a i n = l i s t (map( lambda x : V(SBOX( t u p l e ( x ) ) ) , p l a i n ) ) # we have t o b r i n g e v e r y t h i n g back t o GF( 2 )^4 a f t e r t h e sbox i f r in sidechannle : hamming += [ [ r , l i s t (map( lambda x : t u p l e ( x ) . count ( 1 ) , p l a i n ) ) ] ] plain = linstep ( plain ) 26 175 177 i n j e c t k e y ( p l a i n , key ) c t e x t = l i s t ( reduce ( lambda x , y : l i s t ( x )+ l i s t ( y ) , p l a i n ) ) c t e x t = reduce ( lambda x , y : i n t ( x ) * 2 + i n t ( y ) , c t e x t ) r e t u r n ( c t e x t , hamming ) 179 181 183 185 187 189 d e f p o l y c u t ( poly , v , n ) : r = [] pt = l i s t ( tuple (( poly ) ) ) while len ( pt ) > n : t v = v . pop ( 0 ) r . i n s e r t ( 0 , sum( p t [ 0 : n]+[ t v ] ) ) pt = pt [n : ] pt . i n s e r t (0 , tv ) i f len ( pt ) > 0: r . i n s e r t ( 0 , sum( p t ) ) return r 191 193 def getidx (p) : v i = p . vars_as_monomial ( ) . v a r i a b l e s ( ) [ 0 ] . index ( )+1 return vi 195 197 199 201 203 205 207 209 211 213 215 217 219 221 223 225 227 229 231 233 d e f g e t c n f ( s , ns ) : r = "" x0 , x1 , x2 , x3 = map( lambda x : s t r ( g e t i d x ( x ) ) , s [ i ] ) y0 , y1 , y2 , y3 = map( lambda x : s t r ( g e t i d x ( x ) ) , ns [ i ] ) clausels = [ [ y0 , y1 , y2 , x0 ] , [ y0 , y2 , y3 , x0 ] , [ y0 , y2 , x0 , x1 ] , [ y0 , y1 , y3 , x2 ] , [ y0 , y2 , y3 , x2 ] , [ y1 , y2 , y3 , x2 ] , [ y0 , y2 , x0 , x2 ] , [ y1 , y2 , x0 , x2 ] , [ y1 , y3 , x0 , x2 ] , [ y0 , y2 , x1 , x2 ] , [ y1 , y2 , x1 , x2 ] , [ y0 , y3 , x1 , x2 ] , [ y1 , y3 , x0 , x3 ] , [ y2 , y3 , x0 , x3 ] , [ y3 , x0 , x1 , x3 ] , [ y0 , y2 , x2 , x3 ] , [ y1 , y2 , x2 , x3 ] , [ y2 , y3 , x2 , x3 ] , [ y2 , x0 , x2 , x3 ] , [ y2 , x1 , x2 , x3 ] , [ y1 , y2 , x2 , − y0 ] , [ y1 , x0 , x2 , − y0 ] , [ y2 , y3 , x3 , − y0 ] , [ y3 , x0 , x3 , − y0 ] , [ x0 , x2 , x3 , − y0 ] , [ y0 , y2 , x1 , − y1 ] , [ y0 , y3 , x1 , − y1 ] , [ y0 , x0 , x1 , − y1 ] , [ y0 , y2 , x2 , − y1 ] , [ y2 , y3 , x3 , − y1 ] , [ x1 , x3 , − y1 ] , [ y0 , x1 , x3 , − y1 ] , 27 235 237 239 241 243 245 247 249 251 253 255 257 259 [ y2 , x1 , x3 , − y1 ] , [ y3 , x1 , x3 , − y1 ] , [ x0 , x1 , x3 , − y1 ] , [ x1 , x2 , x3 , − y1 ] , [ y3 , x3 , − y0 , − y1 ] , [ x0 , x3 , − y0 , − y1 ] , [ x1 , x3 , − y0 , − y1 ] , [ y1 , x0 , − y0 , − y2 ] , [ y3 , x0 , − y0 , − y2 ] , [ x0 , x1 , − y0 , − y2 ] , [ x0 , x3 , − y0 , − y2 ] , [ x0 , x1 , − y1 , − y2 ] , [ x1 , x3 , − y1 , − y2 ] , [ x3 , − y0 , − y1 , − y2 ] , [ y0 , y2 , x1 , − y3 ] , [ y2 , x0 , x2 , − y3 ] , [ y2 , x1 , x2 , − y3 ] , [ y1 , x2 , − y0 , − y3 ] , [ x1 , x2 , − y0 , − y3 ] , [ y2 , x1 , − y1 , − y3 ] , [ x0 , x1 , − y1 , − y3 ] , [ x1 , x3 , − y1 , − y3 ] , [ x1 , − y0 , − y1 , − y3 ] , [ x1 , − y0 , − y2 , − y3 ] , [ x3 , − y1 , − y2 , − y3 ] ] c l a u s e l s = map( lambda x : map( s t r , x ) , c l a u s e l s ) r e t u r n " \n " . j o i n ( l i s t (map( lambda x : " " . j o i n ( x ) , l i s t ( c l a u s e l s ) ) ) ) 261 263 265 267 269 271 d e f c u t a l l ( s , var , n ) : rs = [] for p in s : r s = r s + p o l y c u t ( p , var , n ) return rs def p l i n ( x ) : i f x . deg ( ) != 1 : r e t u r n F a l s e i f l e n ( x ) < 10: r e t u r n F a l s e r e t u r n True 273 275 277 279 def encodelinear (p) : i f p . deg ( ) != 1 : r a i s e V a l u e E r r o r ( " p o l y n o m i a l must be o f degree 1 " ) i f l e n ( p ) == 1 : r a i s e V a l u e E r r o r ( " p o l y n o m i a l must have l e n g t h > 1 " ) v a r = l i s t ( p . vars_as_monomial ( ) . v a r i a b l e s ( ) ) i d x = [ v . index ( )+1 f o r v i n v a r ] i f not p . h a s _ c o n s t a n t _ p a r t ( ) : i d x [ − 1] = − i d x [ − 1] r e t u r n " x " +( " " . j o i n (map( lambda x : s t r ( x ) , i d x ) ) )+" 0 " 281 283 285 287 289 291 293 def l i n e a r i z e ( s , v ) : rs = [] vmap = {} for p in s : pt = l i s t ( tuple (p) ) f o r i i n range ( l e n ( p t ) ) : i f p t [ i ] . deg ( ) > 1 : i f not p t [ i ] i n vmap : v t = v . pop ( 0 ) vmap[ p t [ i ] ] = v t p t [ i ] = vmap[ p t [ i ] ] r s = r s + [sum( p t ) ] 28 295 f o r i i n vmap : r s = r s +[ i + vmap[ i ] ] return rs , v 297 299 301 303 305 307 309 311 313 315 317 319 321 323 325 327 329 331 333 335 337 339 341 343 345 347 349 351 d e f g e t P o l y n o m i a l S y s t e m ( p , c , rounds =32,k=None , k e y i n j e c t =64, i n t e r m e d i a t e=True , c n f=True , p l i n e a r i z e=True , s i d e c h a n n l e = { } ) : cnf = " " p l a i n b i t s = pack4 ( b64 ( p ) ) c i p h e r b i t s = pack4 ( b64 ( c ) ) system = [ ] v = R . gens ( ) key = pack4 ( v ) v = v [64:] s = pack4 ( v ) system = system + l i s t ( reduce ( lambda x , y : l i s t ( x )+ l i s t ( y ) , map( lambda x , y : x+y , s , plainbits ))) v = v [64:] ns = pack4 ( v ) v = v [64:] i f cnf : i n t e r m e d i a t e = True f o r r i n range ( rounds ) : i f ( r % 4) == 0 : i n j e c t k e y ( s , key ) s = addconsts ( s , r ) i f intermediate : i n j e c t k e y ( s , ns ) system = system + l i s t ( reduce ( lambda x , y : l i s t ( x )+ l i s t ( y ) , s ) ) s = ns ns = pack4 ( v ) v = v [64:] system = system + g e t e q u a t i o n s ( s , ns ) i f r in sidechannle : f o r i i n range (16) : c n f += lessthenhamming ( ns [ i ] , s i d e c h a n n l e [ r ] [ i ] ) s = ns ns = pack4 ( v ) v = v [64:] s = shiftrows ( s ) f o r i i n range ( 4 ) : s = m i x c o l ( s , True ) i n j e c t k e y ( s , ns ) system = system + l i s t ( reduce ( lambda x , y : l i s t ( x )+ l i s t ( y ) , s ) ) s = ns ns = pack4 ( v ) v = v [64:] i n j e c t k e y ( s , key ) i n j e c t k e y ( s , ns ) i n j e c t k e y ( ns , c i p h e r b i t s ) system = system + l i s t ( reduce ( lambda x , y : l i s t ( x )+ l i s t ( y ) , s ) ) system = system + l i s t ( reduce ( lambda x , y : l i s t ( x )+ l i s t ( y ) , ns ) ) i f key!=None : k e y b i t s = pack4 ( b64 ( k ) ) kb = l i s t ( reduce ( lambda x , y : l i s t ( x )+ l i s t ( y ) ,map( lambda x , y : x+y , key , k e y b i t s ) ) ) i f k e y i n j e c t == 28: kb = kb [0:4]+ kb [16:24]+ kb [32:36]+ kb [40:44]+ kb [48:52]+ kb [ 6 0 : 6 4 ] e l i f k e y i n j e c t == 16: kb = kb [0:4]+ kb [20:24]+ kb [40:44]+ kb [ 6 0 : 6 4 ] e l i f k e y i n j e c t == 32: kb = kb [0:8]+ kb [20:28]+ kb [40:48]+ kb [60:64]+ kb [ 4 8 : 5 2 ] 29 353 355 357 359 361 363 365 367 system = system+kb else : system = system + kb [ 0 : k e y i n j e c t ] if plinearize : system , v = l i n e a r i z e ( system , l i s t ( v ) ) mqsystem = f i l t e r ( lambda x : not p l i n ( x ) , t u p l e ( system ) ) l i n s y s t e m = f i l t e r ( lambda x : p l i n ( x ) , t u p l e ( system ) ) f n = tmp_filename ( ) s o l v e r = DIMACS( f i l e n a m e=f n ) CE = CNFEncoder ( s o l v e r , R) f o r p o l y i n mqsystem : CE . c l a u s e s ( p o l y ) solver . write () r e s u l t = open ( f n ) . read ( ) for le in linsystem : r e s u l t += e n c o d e l i n e a r ( l e )+" \n " r e t u r n r e s u l t + " \n " + c n f + " \n " + " c key i s 0x "+hex ( k ) + " \n " 369 371 373 375 377 379 381 d e f usage ( ) : print " " " −e e n c r y p t p l a i n t e x t with key and o u t p u t c i p h e r − t e x t −u g e n e r a t e system f o r random key − r <rounds> number o f rounds ( d e f a u l t : 32) −p <p t e x t > s e t p l a i n − t e x t ( d e f a u l t : random ) −k <key> s e t key ( d e f a u l t : random ) −c <c t e x t > s e t c i p h e r − t e x t ( d e f a u l t : random ) − i #b i t s number o f guessed k e y b i t s ( d e f a u l t : 0) − s <s i d e > coma s e p e r a t e d l i s t o f rounds t o e x t r a c t s i d e channel i n f o r m a t i o n from −e j u s t e n c r y p t p l a i n − t e x t u s i n g key """ sys . e x i t (1) 383 opts , a r g s = g e t o p t . g e t o p t ( s y s . argv [ 1 : ] , " huek : p : c : s : r : i : " ) 385 r , u , c , p , k , i , s , e = 32 ,0 , − 1 , − 1 , − 1 ,0 ,[] ,0 387 389 391 393 395 397 399 401 403 405 f o r op i n o p t s : i f op [ 0 ] == "−p " : p = i n t ( op [ 1 ] , 1 6 ) e l i f op [ 0 ] == "−c " : c = i n t ( op [ 1 ] , 1 6 ) e l i f op [ 0 ] == "−k " : k = i n t ( op [ 1 ] , 1 6 ) e l i f op [ 0 ] == "− s " : s = l i s t (map( lambda x : i n t ( x ) , op [ 1 ] . s p l i t ( " , " ) ) ) e l i f op [ 0 ] == "− r " : r = i n t ( op [ 1 ] ) e l i f op [ 0 ] == "− i " : i = i n t ( op [ 1 ] ) e l i f op [ 0 ] == "−e " : e = 1 e l i f op [ 0 ] == "−u " : u = 1 e l i f op [ 0 ] == "−h " : usage ( ) 407 409 i f p == −1: p = random . r a n d i n t (0,1<<64) 411 i f k == −1: 30 413 key = random . r a n d i n t (0,1<<64) else : key = k 415 417 419 421 423 i f c == −1: c , s i d e c h a n n l e = e n c r y p t ( p , key , rounds=r , s i d e c h a n n l e=s ) else : tmp = c c , s i d e c h a n n l e = e n c r y p t ( p , key , rounds=r , s i d e c h a n n l e=s ) c = tmp i f u == 1 : key = random . r a n d i n t (0,1<<64) 425 427 429 431 i f e == 0 : system = g e t P o l y n o m i a l S y s t e m ( p , c , r , key , i , c n f=True , s i d e c h a n n l e=d i c t ( s i d e c h a n n l e ) ) p r i n t system e l i f e == 1 : print sidechannle p r i n t " enc(%x,%x ) = %x " % ( p , key , c ) Listing A.1: LED equation generator 2 4 6 8 import import import import import import itertools functools sys random csasbox getopt R=BooleanPolynomialRing (40000 , " x " ) V=R^8 # 8 t u p l e o f p o l y n o m i a l s 10 12 14 16 18 20 22 24 26 28 30 32 34 36 SBOX = mq . SBox ( [0 x3a , 0xea , 0x68 , 0 xfe 0x83 , 0 x c f , 0xe1 , 0 x7f , 0xe8 , 0x27 , 0x61 , 0x95 , 0xa2 , 0x06 , 0x82 , 0x7c , 0xbe , 0x7a , 0x6d , 0x47 , 0 xcc , 0x5b , 0x67 , 0xbd , 0 x f f , 0x69 , 0 xef , 0x03 , 0 x3f , 0xb4 , 0x10 , 0x04 , 0x16 , 0xab , 0xac , 0x4c , 0x3b , 0xd4 , 0xd5 , 0x94 , 0x71 , 0xa1 , 0 xf9 , 0 x4f , 0xe3 , 0x39 , 0x93 , 0xce , 0x6c , 0x19 , 0x42 , 0x79 , 0x8a , 0xec , 0x1e , 0x85 , 0x7e , 0x0a , 0x9a , 0x13 , 0x5a , 0 x1f , 0x32 , 0x35 , 0x29 , 0x3d , 0xe7 , 0x92 , 0xa5 , 0x57 , 0x97 , 0x40 , 0xeb , 0xc3 , 0x34 , 0x2d , 0x1c , 0xc7 , 0x23 , 0xed , 0x99 , 0x9e , 0x4d , 0xd9 , 0x3e , 0xd7 , 0x21 , 0x74 , 0x8e , 0x5d , 0x37 , 0x11 , 0xa7 , 0x77 , 0x24 , 0 xbf , 0 xf8 , 0 x f c , 0x81 , 0x09 , 0x7d , 0 x0f , 0xc8 , 0xa0 , , 0x33 , 0xe9 , 0x88 , 0x1a , 0xba , 0xe2 , 0x38 , 0x12 , 0x0c , 0x36 , 0xe5 , 0x70 , 0x17 , 0xa3 , 0x26 , 0x49 , 0xc1 , 0x51 , 0 x8f , 0 xf3 , 0xcd , 0x18 , 0x08 , 0xc9 , 0x4e , 0x48 , 0x4a , 0x84 , 0xdc , 0 xf5 , 0x5c , 0xc6 , 0 xf1 , 0x6a , 0 x2f , 0x3c , 0xd0 , 0xc4 , 0x63 , 0x62 , 0x2e , 0xaa , 0xc5 , 0x56 , 0x65 , 0x64 , 0xe4 , 0x58 , 0xdd , 0xee , 0x96 , 0 xf6 , 0x53 , 0x45 , 0xde , 0xbb , 0x2a , 0x9d , 0xc2 , 0x5e , 0x9c , 0xa8 , 0x73 , 0x30 , 0x87 , 0x1b , 0x2b , 0x4b , 0x15 , 0xe6 , 0xbc , 0x0e , 0xb8 , 0x44 , 0x25 , 0xa4 , 0x90 , 0x6e , 0x50 , 0x00 , 0xda , 0x8d , 0 x6f , 0 x5f , 0x86 , 0 xdf , 0x6b , 0x05 , 0xd2 , 0x28 , 0x75 , 0xd6 , 0 xf0 , 0xb0 , 0x02 , 0xb7 , 0xb1 , 0x01 , 0x76 , 0x91 , 0 xf2 , 0xcb , 0x78 , 0x60 , 31 38 40 42 0xd1 , 0x1d , 0 xfb , 0xd8 , 0xad , 0x8c , 0 xf7 , 0xa6 , 0xd3 , 0x41 , 0x46 , 0x89 , 0xe0 , 0xdb , 0xb6 , 0x14 , 0x0b , 0x66 , 0xb5 , 0x7b , 0xca , 0x55 , 0 xaf , 0 xfd , 0x98 , 0x59 , 0x43 , 0x0d , 0x80 , 0xb2 , 0x22 , 0 x9f , 0x72 , 0x54 , 0x52 , 0xa9 , 0xb3 , 0xae , 0x07 , 0x8b , 0x2c , 0x9b , 0x20 , 0x31 , 0 xf4 , 0xb9 , 0 xfa , 0xc0 ] ) 44 46 48 50 52 d e f b8 ( x ) : l = l i s t (map( lambda i : ( x>>i ) &1 , range ( 8 ) ) ) l . reverse () return tuple ( l ) d e f b64 ( x ) : l = l i s t (map( lambda i : ( x>>i ) &1 , range (64) ) ) l . reverse () return tuple ( l ) 54 56 58 def i64 ( x ) : r e t u r n reduce ( lambda x , y : i n t ( x ) * 2 + i n t ( y ) , x ) d e f pack8 ( s ) : r e t u r n l i s t (map( lambda i : V( t u p l e ( s [ i * 8 : i * 8+8]) ) , range ( 8 ) ) ) 60 62 def getidx (p) : v i = p . vars_as_monomial ( ) . v a r i a b l e s ( ) [ 0 ] . index ( )+1 return vi 64 66 68 def P( x ) : p=[1 ,7 ,3 ,0 ,4 ,5 ,2 ,6] p . reverse () r e t u r n V( t u p l e (map( lambda a : x [ p [ a ] ] , range ( 8 ) ) ) ) 70 72 74 76 78 d e f lessthenhamming ( v ,w) : v = l i s t (map( lambda x : i n t ( g e t i d x ( x ) ) , v ) ) r = set ([]) n = 8 f o r c i n i t e r t o o l s . c o m b i n a t i o n s ( v ,w+1) : r . add ( ( " " . j o i n (map( lambda x : s t r (− x ) , c ) ) )+" 0\n " ) f o r c i n i t e r t o o l s . c o m b i n a t i o n s ( v , ( n−w)+1) : r . add ( ( " " . j o i n (map( lambda x : s t r ( x ) , c ) ) )+" 0\n " ) return " " . join ( l i s t ( r ) ) 80 82 84 86 88 90 92 94 96 d e f permuteblock ( x ) : r = [ F a l s e ] * 64 x = tuple (x) p=[36 ,31 ,54 ,8 ,22 ,50 ,1 ,55 ,61 ,51 ,24 ,26 ,45 ,49 ,7 ,10 ,39 ,60 ,11 ,15 , 16 ,2 ,21 ,29 ,53 ,32 ,25 ,57 ,42 ,5 ,43 ,37 ,19 ,38 ,46 ,48 ,62 ,30 ,17 ,0 ,23 , 56 ,52 ,41 ,63 ,28 ,20 ,40 ,58 ,14 ,12 ,27 ,34 ,35 ,3 ,6 ,47 ,44 ,4 ,33 ,9 ,13 ,59 ,18] #r e t u r n t u p l e (map( lambda a : x [ p [ a ] ] , range (64) ) ) f o r i i n range (64) : r [ i ] = x[p[ i ]] return r d e f k e y s c h e d u l e ( key ) : ks = [ t u p l e ( key ) ] f o r i i n range ( 6 ) : ks = [ permuteblock ( ks [ 0 ] ) ] + ks 32 98 100 102 104 106 108 110 112 114 116 118 120 ks = l i s t (map( lambda x : pack8 ( x ) , ks ) ) ks = f u n c t o o l s . reduce ( lambda x , y : x+y , ks ) f o r i i n range (56) : ks [ i ] = V( ks [ i ] )+V( b8 ( i n t ( i /8) ) ) r e t u r n ks def getequations ( i , o) : i i = t u p l e (map( g e t i d x , i ) ) oo = t u p l e (map( g e t i d x , o ) ) r = SBOX . c n f ( i i , oo , format=" dimacs " ) . s p l i t ( " \n " ) [ 1 : ] r e t u r n " \n " . j o i n ( r ) def encodelinear (p) : i f p . deg ( ) != 1 : r a i s e V a l u e E r r o r ( " p o l y n o m i a l must be o f degree 1 " ) i f l e n ( p ) == 1 : #r a i s e V a l u e E r r o r ( " p o l y n o m i a l must have l e n g t h > 1 " ) v = p . vars_as_monomial ( ) . v a r i a b l e s ( ) [ 0 ] r = s t r ( v . index ( ) +1)+" 0 " i f not p . h a s _ c o n s t a n t _ p a r t ( ) : r = "− "+r return r v a r = l i s t ( p . vars_as_monomial ( ) . v a r i a b l e s ( ) ) i d x = [ v . index ( )+1 f o r v i n v a r ] i f not p . h a s _ c o n s t a n t _ p a r t ( ) : i d x [ − 1] = − i d x [ − 1] r e t u r n " x " +( " " . j o i n (map( lambda x : s t r ( x ) , i d x ) ) )+" 0 " 122 124 126 128 130 132 134 136 138 140 142 144 146 148 150 d e f e n c r y p t ( p , k , rounds =56, s i d e c h a n n l e =[]) : r a s i d e = {} r b s i d e = {} ks = k e y s c h e d u l e ( b64 ( k ) ) s = pack8 ( b64 ( p ) ) f o r r i n range ( rounds ) : t 1 = V( ks [ r ] ) + V( s [ 0 ] ) i f s i d e c h a n n l e and r i n s e t ( s i d e c h a n n l e ) : r b s i d e [ r ] = t u p l e (map( lambda x : i n t ( x ) , t 1 ) ) . count ( 1 ) t 1 = V(SBOX( t u p l e ( t 1 ) ) ) i f s i d e c h a n n l e and r i n s e t ( s i d e c h a n n l e ) : r a s i d e [ r ] = t u p l e (map( lambda x : i n t ( x ) , t 1 ) ) . count ( 1 ) t0 = s [6] s [ 6 ] = s [7 ] + s [ 5 ] s [ 5 ] = s [7 ] + s [ 4 ] s [ 4 ] = s [7 ] + s [ 3 ] s [ 3 ] = s [2 ] s [ 2 ] = s [1 ] + V( P ( t 1 ) ) s [ 1 ] = s [0 ] s [ 0 ] = s [7 ] + V( t 1 ) s [ 7 ] =V( t 0 ) s = list (s) #s . r e v e r s e ( ) s = l i s t ( reduce ( lambda x , y : l i s t ( x )+ l i s t ( y ) , s ) ) s = reduce ( lambda x , y : i n t ( x ) * 2 + i n t ( y ) , s ) i f sidechannle : return s , rbside , raside return s 152 154 156 d e f g e t s y s t e m ( p t e x t , c t e x t , key , rounds =56, k e y i n j e c t =0, r b s ={} , r a s ={}) : cnf = " " system = [ ] v = R . gens ( ) k , v = v [:64] , v [64:] 33 158 160 162 164 166 168 170 172 174 176 178 180 182 184 186 188 190 192 s , v = pack8 ( v [ : 6 4 ] ) , v [ 6 4 : ] k e y b i t s = b64 ( key ) ks = k e y s c h e d u l e ( k ) p b y t e s = pack8 ( b64 ( p t e x t ) ) c b y t e s = pack8 ( b64 ( c t e x t ) ) f o r i i n range ( 8 ) : system = system + l i s t ( ( p b y t e s [ i ] + s [ i ] ) ) f o r i i n range ( k e y i n j e c t ) : r = [17 , 56 , 49 , 7 , 8 , 52 , 41 , 30 , 55 , 18 , 4 , 10 , 46 , 1 , 37 , 58 , 33 , 44 , 15 , 48 , 59 , 13 , 61 , 28 , 22 , 53 , 24 , 26 , 16 , 42 , 23 , 47] system = system + [R( k [ r [ i ]]+ k e y b i t s [ r [ i ] ] ) ] f o r r i n range ( rounds ) : t 1 = ks [ r ] + s [ 0 ] ns1 , v = V( t u p l e ( v [ : 8 ] ) ) , v [ 8 : ] ns2 , v = V( t u p l e ( v [ : 8 ] ) ) , v [ 8 : ] system = system + l i s t ( t 1 + ns1 ) t 1 = V( ns1 ) i f r i n r b s . ke ys ( ) : c n f += lessthenhamming ( ns1 , r b s [ r ] ) c n f = c n f + c s a s b o x . s b o x c l a u s e l s (map( g e t i d x , ns1 ) ,map( g e t i d x , ns2 ) ) + " \n " i f r i n r a s . ke ys ( ) : c n f += lessthenhamming ( ns2 , r a s [ r ] ) t 1 = V( ns2 ) t0 = s [6] s [ 6 ] = s [7 ] + s [ 5 ] s [ 5 ] = s [7 ] + s [ 4 ] s [ 4 ] = s [7 ] + s [ 3 ] s [ 3 ] = s [2 ] s [ 2 ] = s [1 ] + V( P ( t 1 ) ) s [ 1 ] = s [0 ] s [ 0 ] = s [7 ] + V( t 1 ) s [ 7 ] = V( t 0 ) f o r i i n range ( 8 ) : system = system + l i s t ( ( c b y t e s [ i ] + s [ i ] ) ) system = l i s t (map( e n c o d e l i n e a r , system ) ) c n f = c n f + " \n " . j o i n ( system ) r e t u r n c n f + " \ nc " + hex ( key ) 194 196 198 200 202 204 d e f usage ( ) : print " " " −e −u −r −p −k −c −i −s e n c r y p t p l a i n t e x t with key andoutput c i p h e r − t e x t g e n e r a t e system f o r random key <rounds> number o f rounds ( d e f a u l t : 32) <p t e x t > s e t p l a i n − t e x t ( d e f a u l t : random ) <key> s e t key ( d e f a u l t : random ) <c t e x t > s e t c i p h e r − t e x t ( d e f a u l t : random ) #b i t s number o f guessed k e y b i t s ( d e f a u l t : 0) <s i d e > coma s e p e r a t e d l i s t o f rounds t o e x t r a c t s i d e channel i n f o r m a t i o n from −e j u s t e n c r y p t p l a i n −t e x t u s i n g 206 key 208 """ sys . e x i t (1) 210 opts , a r g s = g e t o p t . g e t o p t ( s y s . argv [ 1 : ] , " huek : p : c : s : r : i : " ) 212 r , u , c , p , k , i , s , e = 56 ,0 , − 1 , − 1 , − 1 ,0 ,[ − 1] ,0 214 f o r op i n o p t s : 34 216 218 220 222 224 226 228 230 232 i f op [ 0 ] == "−p " : p = i n t ( op [ 1 ] , 1 6 ) e l i f op [ 0 ] == "−c " : c = i n t ( op [ 1 ] , 1 6 ) e l i f op [ 0 ] == "−k " : k = i n t ( op [ 1 ] , 1 6 ) e l i f op [ 0 ] == "− s " : s = l i s t (map( lambda x : i n t ( x ) , op [ 1 ] . s p l i t ( " , " ) ) ) e l i f op [ 0 ] == "− r " : r = i n t ( op [ 1 ] ) e l i f op [ 0 ] == "− i " : i = i n t ( op [ 1 ] ) e l i f op [ 0 ] == "−e " : e = 1 e l i f op [ 0 ] == "−u " : u = 1 e l i f op [ 0 ] == "−h " : usage ( ) 234 236 238 240 i f p == −1: p = random . r a n d i n t (0,1<<64) i f k == −1: key = random . r a n d i n t (0,1<<64) else : key = k 242 244 246 248 250 i f c == −1: c , rb , r a = e n c r y p t ( p , key , rounds=r , s i d e c h a n n l e=s ) else : tmp = c c , rb , r a = e n c r y p t ( p , key , rounds=r , s i d e c h a n n l e=s ) c = tmp i f u == 1 : key = random . r a n d i n t (0,1<<64) 252 254 256 i f e == 0 : system = g e t P o l y n o m i a l S y s t e m ( p , c , r , key , i , r a s=ra , r b s=rb ) p r i n t system e l i f e == 1 : p r i n t " enc(%x,%x ) = %x " % ( p , key , c ) Listing A.2: CSA equation generator 35
© Copyright 2026 Paperzz