IT 14 063 Examensarbete 30 hp Oktober 2014

Implementation of bit-vector variables in a CP solver, with an application to the generation of cryptographic S-boxes

Kellen Dye

Masterprogram i datavetenskap Master Programme in Computer Science

Abstract Implementation of bit-vector variables in a CP solver, with an application to the generation of cryptographic S-boxes Kellen Dye

Teknisk- naturvetenskaplig fakultet UTH-enheten We present a bit-vector variable implementation for the constraint programming (CP) solver Gecode and its application to the problem of nding high-quality Besöksadress: Ångströmlaboratoriet cryptographic substitution boxes (S-boxes). Lägerhyddsvägen 1 Hus 4, Plan 0 S-boxes are a component in some cryptographic protocols, for example DES, which are critical to the strength of the entire system. S-boxes are arrays of Postadress: Box 536 bit-vectors, where each bit-vector is itself an array of bits. The desirable 751 21 Uppsala properties of an S-box can be described as relationships between its constituent bit-vectors. Telefon: 018 – 471 30 03 We represent substitution boxes as arrays of bit-vector variables in Gecode in Telefax: order to leverage CP techniques for nding high-quality S-boxes. In a CP solver, 018 – 471 30 00 bit-vectors can alternatively be represented as sets or as arrays of Boolean variables. Experimental evaluation indicates that modeling substitution boxes Hemsida: http://www.teknat.uu.se/student with bit-vector variables is an improvement over both set- and Boolean-based models. We additionally correct an error in previous work which invalidates the main experimental result, extend a heuristic for evaluating S-box quality, present two symmetries for substitution boxes, de ne several generic bit-vector propagators, and de ne propagators for the S-2 and S-7 DES design criteria.

Handledare: Jean-Noël Monette Ämnesgranskare: Pierre Flener Examinator: Ivan Christoff IT 14 063 Tryckt av: Reprocentralen ITC

Contents

1 Introduction 1

2 Background 3 2.1 Constraint Programming ...... 3 2.1.1 Example: Sudoku ...... 4 2.1.2 Definition ...... 6 2.2 Bit-vectors ...... 9 2.2.1 Integers ...... 9 2.2.2 Concatenation ...... 9 2.2.3 Bitwise operations ...... 10 2.2.4 Parity ...... 10 2.2.5 Linear combination ...... 10 2.2.6 ...... 11 2.2.7 Hardware support ...... 11 2.2.8 Support in constraint solvers ...... 11 2.3 Substitution boxes ...... 11 2.3.1 Description ...... 12 2.3.2 Measuring the linearity of an S-box ...... 14 2.3.3 DES S-Box design criteria ...... 15

3 Previous work 17 3.1 Bit-vector variables and constraints ...... 17 3.2 Constraint programming and substitution boxes ...... 20 3.2.1 Criterion S-2 ...... 20 3.2.2 Criterion S-3 ...... 21 3.2.3 Criterion S-4 ...... 21 3.2.4 Criterion S-5 ...... 21 3.2.5 Criterion S-6 ...... 22 3.2.6 Criterion S-7 ...... 22 3.3 Symmetries ...... 22

4 Theoretical contributions 25 4.1 Propagators ...... 25 4.1.1 Hamming weight ...... 25 4.1.2 Parity ...... 26 4.1.3 Disequality ...... 27 4.2 An extension to the constraint for criterion S-2 ...... 28 4.3 Corrected S-7 constraint ...... 28

i 4.4 Reflective symmetry ...... 29 4.4.1 Reflection over the x-axis ...... 29 4.4.2 Reflection over the y-axis ...... 33 4.4.3 Symmetry-breaking ...... 33

5 Bit-vector implementation for Gecode 35 5.1 Variable implementations ...... 35 5.2 Variables & variable arrays ...... 37 5.3 Variable views ...... 37 5.4 Propagators ...... 37 5.5 Branchings ...... 39 5.6 Source code ...... 40

6 Bit-vector S-Box models 41 6.1 Variable choice ...... 41 6.2 Channeling ...... 41 6.3 Criterion S-2 ...... 41 6.3.1 Decomposed bit-vector S-2 ...... 41 6.3.2 Global integer & bit-vector S-2 ...... 42 6.4 Criterion S-3 ...... 43 6.5 Criteria S-4, S-5, and S-6 ...... 43 6.6 Criterion S-7 ...... 43 6.6.1 Decomposed bit-vector S-7 ...... 43 6.6.2 Global bit-vector S-7 ...... 44 6.7 Models ...... 45

7 Alternative S-Box models 47 7.1 Set model ...... 47 7.1.1 Channeling ...... 47 7.1.2 Bitwise operations ...... 47 7.1.3 Criterion S-2 ...... 47 7.1.4 Criterion S-3 ...... 48 7.1.5 Criteria S-4, S-5, and S-6 ...... 48 7.1.6 Criterion S-7 ...... 48 7.1.7 Comparison ...... 48 7.2 Boolean model ...... 48 7.2.1 Channeling ...... 48 7.2.2 Bitwise operations ...... 48 7.2.3 Criterion S-2 ...... 49 7.2.4 Criterion S-3 ...... 49 7.2.5 Criteria S-4, S-5, and S-6 ...... 49 7.2.6 Criterion S-7 ...... 49 7.2.7 Comparison ...... 49

8 Evaluation 51 8.1 Setup ...... 51 8.2 Results ...... 52

9 Conclusion 59

Bibliography 61

ii Acknowledgements

I would like to thank my advisor Jean-Noël Monette, who proposed the subject of this thesis and who provided valuable suggestions and feedback as well as several crucial insights. Additionally, I would like to thank Pierre Flener for his excellent teaching in his constraint programming course at Uppsala University, and Christian Schulte for producing the most complete and clear definition of constraint programming I have read, and for his prompt help with issues on the Gecode mailing list.

iii

Chapter 1

Introduction

Secure communications rely on cryptography in order to hide the contents of messages from eavesdroppers. On the internet, these messages might be users’ passwords, bank details, or other sensitive information. For the communica- tions to truly be secure, the cryptography must be strong enough to withstand attacks from dedicated adversaries. Substitution boxes are a component in some cryptographic protocols which are critical to the strength of the entire system. These substitution boxes should have particular properties in order to ensure that the cryptographic system can withstand efforts to decrypt a message. Substitution boxes are arrays of bit-vectors, where each bit-vector is itself an ar- ray of binary digits, or bits (a 0 or a 1). The desirable properties of a substitution box can be described as relationships between its constituent bit-vectors. Constraint programming is a technique used to find values for variables in such a way that certain relationships between the variables are maintained and, optionally, the best values are found. If each bit-vector in a substitution box is represented by a variable, then constraint programming can be used to express the desirable properties of substitution boxes and then find substitution boxes which fulfill these properties. Constraint programming typically occurs in the context of a program called a constraint solver which provides different types of variables such as integers or Booleans. Currently, most solvers do not have support for bit-vectors. Although it is possible to convert the bit-vectors into another form (for exam- ple, interpreting each bit-vector as a number of Boolean variables; one for each bit), some of the desirable properties of substitution boxes are much more eas- ily expressed in terms of bit-vectors. This thesis therefore describes the implementation of bit-vector variables in the open-source constraint solver Gecode and their application to the problem of finding high-quality cryptographic substitution boxes. In Chapter 2, constraint programming is defined, bit-vectors and operations

1 over bit-vectors are introduced, and substitution boxes and their desirable prop- erties are described. In Chapter 3, the works on which this thesis is based are reviewed. Michel and Van Hentenryck introduce bit-vector variables and domains for constraint programming and also define a number of propagators for bit-vector oper- ations [10]. Ramamoorthy et al. suggested the application of constraint pro- gramming to substitution box generation [13] as well as some method for break- ing symmetry in the search space [12]. In Chapter 4 we present our contributions: two additional symmetries of sub- stitution boxes, several additional bit-vector propagators, an addition to the non-linearity constraint, and a correction to the S-7 constraint presented by Ra- mamoorthy et al. which invalidates their main experimental result. In Chapter 5, we detail a bit-vector variable implementation in Gecode. In Chapter 6, we present several alternative bit-vector models for substitution box generation. In Chapter 7, we describe a set variable-based model and a Boolean variable-based model. We also define new propagators for the S-2 non-linearity constraint and the S-7 constraint. In Chapter 8, we give a comparison of the various models for substitution box generation and describe their relative merits. Experimental evaluation indi- cates that modeling substitution boxes with bit-vector variables is an improve- ment over both set- and Boolean-based models and that efficiency can be im- proved by the implementation of propagators for some of the substitution box criteria. Finally, in Chapter 9 we summarize the thesis and present possibilities for fu- ture work.

2 Chapter 2

Background

Here we present an introduction to constraint programming, bit-vectors, and substitution boxes. We use sudoku as a simple example problem for constraint programming, then present a more formal definition. Bit-vectors and the rele- vant operations over them are then presented. Finally, substitution boxes and their desirable properties are introduced.

2.1 Constraint Programming

Constraint programming is a method of solving problems in which the prob- lem is characterized as a set of constraints over a set of variables, each of which has a domain of potential values. The constraints describe relationships be- tween variables and limits on the variable domains. Taken together, these form a constraint satisfaction problem. Finding a solution to a specific problem is typically done within a constraint solver, a program which can be used for many different problems and which can provide implementations for commonly used constraints. The solver performs inference on the potential domains of the variables in a process called propagation in which the domain of a variable is reduced by elim- inating values not satisfying a constraint and subsequently applying the impli- cations of the altered domain to other variables. Propagation is performed by components of the constraint solver called propagators. Once the propagators can no longer make additional changes to variable domains, they are said to be at fixpoint and the solver then performs systematic search by altering the do- main of a variable. Search is interleaved with the propagation described above. Search occurs in the solution space, that is, all possible combinations of values for all variables. The searching of the solution space can be represented as a search tree, where each search choice creates a branch and propagation occurs at the nodes of the tree. In the case that a search choice leads to the violation of a constraint or to a variable having no potential values, that part of the space is said to be failed and the search engine backtracks up the search tree and tries a different choice.

3 2 5 1 9 8 2 3 6 3 6 7 1 6 5 4 1 9 2 7 9 3 8 2 8 4 7 1 9 7 6

Figure 2.1: An example sudoku puzzle

Once a variable’s domain is reduced to a single value, it is assigned, and once all variables are assigned the solver has produced a solution, so long as no con- straints have been violated. Certain problems may also require a problem-specific objective function to be optimized. The objective function evaluates the variable domains and pro- duces a value which is to be minimized or maximized. Problems with such an objective function are called constrained optimization problems. Constraint programming follows a declarative programming paradigm. Most programming is imperative, in which the steps needed to produce a solution are written by the programmer and followed by the computer. In declarative programming, the programmer describes the properties of a problem’s solu- tion, but not the method by which this should be computed [6].

2.1.1 Example: Sudoku

Sudoku is a kind of combinatorial puzzle which provides a simple example for demonstrating the application of constraint programming to a concrete prob- lem. See Figure 2.1 for an example sudoku puzzle. The goal of sudoku is for the player to fill in each of the grid squares of a 9 × 9 grid with one the numbers 1–9. Some grid squares are pre-filled and are intended to give a unique solution to the puzzle. The sudoku grid is divided into rows (Figure 2.2a) and columns (Figure 2.2b), and into nine 3 × 3 blocks (Figure 2.2c). The rules of sudoku are simple: in each row, column, or block, each of the numbers 1–9 must be present and may not be repeated. Once all grid squares are filled and this rule is fulfilled, the puzzle is solved. To produce a constraint satisfaction problem from a specific sudoku puzzle, the puzzle must first be modelled by defining the variables, their domains, and the constraints imposed upon them. Each grid square can be represented by a variable, so there are 9 · 9 = 81 vari- ables. Each of these variables can take on values 1–9, so their initial domains are: {1, 2, 3, 4, 5, 6, 7, 8, 9}.

4 2 5 1 9 2 5 1 9 2 5 1 9 8 2 3 6 8 2 3 6 8 2 3 6 3 6 7 3 6 7 3 6 7 1 6 1 6 1 6 5 4 1 9 5 4 1 9 5 4 1 9 2 7 2 7 2 7 9 3 8 9 3 8 9 3 8 2 8 4 7 2 8 4 7 2 8 4 7 1 9 7 6 1 9 7 6 1 9 7 6 (a) row (b) column (c) block

Figure 2.2: Regions of the sudoku grid

2 5 1 9 8 2 3 6 3 6 7 1 6 5 4 1 9 2 7 9 3 8 2 8 4 7 1 9 7 6

Figure 2.3: The grid square represented by x

For the pre-filled values, the domain associated with that variable contains only a single value, for example: {5}. The rules of the puzzle are implemented as constraints over a subset of the vari- ables. The rule we wish to express is that the values taken by the variables in a given row (or column, or block) should all be different. The constraint which can enforce this relationship is also called alldifferent. A constraint must be de- fined for each row, column and block in the grid so a complete model consists of 9 row constraints + 9 column constraints + 9 block constraints = 27 constraints. Once the variables, domains, and constraints are defined, they may be used by a constraint solver to solve the problem by first reducing the variable domains by propagation, then by search, if necessary.

Propagation for a single variable

In Figure 2.3, a single grid square is indicated; let it be represented by a variable x. Initially, the domain for x is: {1, 2, 3, 4, 5, 6, 7, 8, 9}, like the domains of all variables representing empty grid squares. The variable x is a member of three alldifferent constraints: one for its block, one for its column, and one for its row. First we apply the alldifferent constraint for the block; in the block there are the assigned values 1, 2, and 9. Since the constraint says that x’s value must

5 be different from all other values, we remove these from the domain of x: {3, 4, 5, 6, 7, 8}. Next, the alldifferent constraint for the column is applied; here there are the values 1, 2, 3, 4, and 9. The values 1, 2, and 9 are no longer a part of x’s domain, so these have no effect. We remove the remaining values 3 and 4 from the domain of x: {5, 6, 7, 8}. Finally, the alldifferent constraint for the row is applied. The values 2 and 4 have already been removed, but the remaining values 7 and 8 are removed from the domain of x: {5, 6}. Thus, by propagating just the three constraints in which x is directly involved and only examining the initially-provided values, the domain of x has been re- duced to only two possibilities. Actual propagation by a constraint solver will also change the domains of the other variables, and provide better inference. For example, if x’s domain is {5, 6}, but no other variable in its block has 5 in its domain, the propagator can assign x to 5 directly.

2.1.2 Definition

The following definition of constraint programming is a condensed version of the presentation given by Schulte in [14]. A constraint satisfaction problem (CSP) is a triple hV, U, Ci where V is a finite set of variables, U is a finite set of values, and C is a finite set of constraints. Each constraint c ∈ C is a pair hv, si where v are the variables of c, v ∈ Vn, and s are the solutions of c, s ⊆ Un for the arity n, n ∈ N. For notational convenience, the variables of c can be written var(c) and the solutions of c can be written sol(c). An assignment a is a function from the set of variables V to a universe U: a ∈ V → U. For the set of variables V = {x1,..., xk}, a particular variable xi is assigned to the value ni, that is: a(xi) = ni. A particular assignment a is a solution of constraint c, written a ∈ c, if for var(c) = hx1,..., xni, ha(x1),..., a(xn)i ∈ sol(c). The set of solutions to a constraint satisfaction problem C = hV, U, Ci is

sol(C ) = {a ∈ V → U | ∀c ∈ C : a ∈ c}

Propagation

In constraint solvers, constraints are implemented with propagators. Propa- gators perform inference on sets of possible variable values, called constraint stores, s, with s ∈ V → 2U, where 2U is the power set of U. The set of all constraint stores is S = V → 2U.

If, for two stores s1 and s2, ∀x ∈ V : s1(x) ⊆ s2(x), then s1 is stronger than s2, written s1 ≤ s2. s1 is strictly stronger than s2, written s1 < s2, if ∃x ∈ V : s1(x) ⊂ s2(x).

6 If ∀x ∈ V : a(x) ∈ s(x) for an assignment a and a store s, then a is contained in the store, written a ∈ s. The store store(a) ∈ V → 2U is defined as: ∀x ∈ X : store(a)(x) = {a(x)}. A propagator p is a function from constraint stores to constraint stores: p ∈ S → S. A propagator must be contracting, ∀s ∈ S : p(s) ≤ s and monotonic, ∀s1, s2 ∈ S : s1 ≤ s2 =⇒ p(s1) ≤ p(s2). A store s is failed if ∃x ∈ V : s(x) = ∅. A propagator p fails on a store s if p(s) is failed. A constraint model is M = hV, U, Pi, where V and U are the same as defined previously and P is a finite set of propagators over V and U. The set of solutions of a propagator p is

sol(p) = {a | a ∈ V → U, p(store(a)) = store(a)}

The set of solutions for a particular model M is sol(M ) = ∩ sol(p). p∈P For a propagator p ∈ S → S, the variables involved in the particular constraint implemented by p are given by var(p). The fixpoint of a function f , f ∈ X → X, is an input x, x ∈ X such that f (x) = x. A propagator p is at fixpoint for a store s if p(s) = s. A propagator p is subsumed by a store s if ∀s0 ≤ s : p(s0) = s0, that is if all stronger stores are fixpoints of p. In order to implement propagation in a solver, it is useful for the propagators to be able to report about the status of the returned store. We therefore define an extended propagator, ep, as a function from constraint stores to a pair containing a status message and a constraint store: ep ∈ S → SM × S where the set of status messages is SM ∈ {nofix, fix, subsumed}. The application of an extended propagator ep to a constraint store s results in a tuple hm, s0i, where the status message m indicates whether s0 is a fixpoint (m = fix), whether s0 subsumes ep (m = subsumed), or if no information is available (m = nofix). A propagation algorithm using extended propagators is given in Algorithm 2.1. Initially, the solver will schedule all propagators P in the queue Q. The propa- gation algorithm executes the following inner loop until the queue is empty. One propagator, p, is selected by a function select, which is usually specified dependent upon the problem to be solved. The propagator p is executed, then its returned status, m, is examined. If p is subsumed by the returned store s0, then p is removed from P, since further executions will never reduce variable domains. Next, the set of modified variables, MV, is calculated. From this set, the set of propagators which are dependent upon these variables, DP, is calculated. If s0 is a fixpoint of p, then p is removed from the list of dependent propagators. Finally, the dependent propagators are added to the queue if they were not already present, and the current store s is updated to be the store s0, the result of executing p. In this step, changes to variable domains (indicated by MV)

7 cause propagators to be scheduled for execution (added to Q), thus propagating these changes to other variable domains. Once the queue Q is empty, propagation is at fixpoint and the set of non- subsumed propagators P and the updated store s are returned.

Algorithm 2.1 Propagation algorithm function propagate(hV, U, Pi , s) Q ← P while Q 6= ∅ do p ← select(Q) hm, s0i ← p(s) Q ← Q \ {p} if m = subsumed then P ← P \ {p} MV ← {x ∈ V | s(x) 6= s0(x)} DP ← {p ∈ P | var(p) ∩ MV 6= ∅} if m = fix then DP ← DP \ {p} Q ← Q ∪ DP s ← s0 return hP, si end function

Search

A branching for M is a function b which takes a set of propagators Q and a store s and returns an n-tuple hQ1,..., Qni of sets of propagators Qi. The branching b must satisfy certain properties, see [14] for these. A search tree for a model M and a branching b is a tree where the nodes are la- belled with pairs hQ, si where Q is a set of propagators and s is a store obtained by constraint propagation with respect to Q.

The root of the tree is hP, si, where s = propagate(P, sinit) and sinit = λx ∈ V.U. Each leaf of the tree, hQ, si, either has a store s which is failed or at which b(Q, s) = hi in which case the leaf is solved. For each inner node of the tree, s is not failed and b(Q, s) = hQ1,..., Qni where n ≥ 1. Each inner node has n children where each child is labelled hQ ∪ Qi, propagate(Q ∪ Qi, s)i for 1 ≤ i ≤ n. To actually construct a search tree (that is, to search the solution space) some exploration strategy must be chosen. As an example, a depth-first exploration procedure is given in Algorithm 2.2.

Decomposition

In some cases, a constraint c can be broken down into a set of more basic con- straints, {c0, c1,..., cn}, where this set can be called the decomposed version of c.

8 Algorithm 2.2 Depth-first exploration function dfe(P, s) s0 ← propagate(P, s) if s0 is failed then return s0 else case b(P, s0) of hi then return s0 of hP1, P2i then 00 0 s ← dfe(P ∪ P1, s ) if s00 is failed then 0 return dfe(P ∪ P2, s ) else return s00 end function

2.2 Bit-vectors

Bit-vectors are arrays of Boolean variables where each variable is represented by a single binary digit or bit.

The bits of an n-bit bit-vector x are addressed as xi where i is the index, with 0 ≤ i < n. The bit at index 0 is the least significant bit while the bit at n − 1 is the most significant bit.

2.2.1 Integers

A bit-vector x can be interpreted as a non-negative integer:

n−1 i I(x) = ∑ xi · 2 i=0

2.2.2 Concatenation

A bit-vector can be seen as a concatenation of bits:

n−1 x = x0 k x1 k ... k xn−1 = n xi i=0

So the concatenation of a bit-vector x and a single bit b is:

x k b = x0 k x1 k ... k xn−1 k b or b k x = b k x0 k x1 k ... k xn−1

Note that the argument to the right of the concatenation operator is concate- nated after the most significant bit of the bit-vector, that is, to the left side of the bit-vector, when written as a string. For example, the bit-vector 100 could

9 be written as 0 k 0 k 1, and the concatenation of the bit-vector 100 and the bit 1, 100 k 1 results in the bit-vector 1100.

2.2.3 Bitwise operations

Bitwise operations are Boolean operations applied to each bit position of the bit-vector inputs to the operation. For operations with more than one input, the inputs must be of the same length, n. The result of a bitwise operation is a bit-vector also of length n.

The result of bitwise operations can therefore be seen as concatenations of the logical operations applied to single bit positions. For a binary Boolean opera- tion op and input bit-vectors x and y, both of length n:

n−1 x op y = n (xi op yi) i=0

And for unary operations:

n−1 op x = n (op xi) i=0

The bitwise operations are denoted with their logical operator symbols or names: AND (∧), OR (∨), XOR (⊕), NOT (¬).

2.2.4 Parity

The result of the Boolean function parity is 1 if the number of ones in the input bit-vector x is odd and 0 otherwise:

n−1 M parity(x) = x0 ⊕ x1 ⊕ ... ⊕ xn−1 = xi i=0

2.2.5 Linear combination

The linear combination of two bit-vectors x and y is a single bit: 1 if the num- ber of ones which x and y have in common is odd and 0 otherwise. This is calculated by computing the parity of the bitwise AND of x and y:

linear (x, y) = (x0 ∧ y0) ⊕ (x1 ∧ y1) ⊕ ... ⊕ (xn−1 ∧ yn−1) n−1 M = (xi ∧ yi) i=0 = parity (x ∧ y)

10 2.2.6 Hamming weight

The Hamming weight is the count of the nonzero bits of a bit-vector x:

n−1 weight(x) = x0 + x1 + ... + xn−1 = ∑ xi i=0

2.2.7 Hardware support

Computers typically represent data as bit-vectors both in CPU registers and in memory. The CPU operates on fixed-length bit-vectors, called words, which can differ in length from machine to machine [21]. Bitwise operations and shifts are provided as CPU instructions in, for example, processors [4].

2.2.8 Support in constraint solvers

Constraint solvers typically reason over integer variables, but additional vari- able types have been implemented. The bit-vectors described in this thesis are implemented in Gecode, an open-source constraint solver, written in C++ [7]. Gecode currently provides integer, Boolean, float, and set variables [18]. In some cases it can be more natural to reason about bit-vectors than other representations. As an example, the XOR operation is more-easily understood using bit-vector rather than integer variables. Constraints which can be expressed with bit-vectors can of course also be ex- pressed using arrays of Boolean variables with one variable per bit, or with set variables where the set contains the indexes of the ’on’ bits. The approach with an array of Boolean variables is called bit-blasting which can create very large numbers of variables. Using bit-vector variables in a constraint solver allows for constant-time prop- agation algorithms if the length of the bit-vectors is less than the word size of the underlying computer architecture [10].

2.3 Substitution boxes

The goal of cryptography is to hide the contents of messages such that if a message between two parties is intercepted by a third, this third party will not easily be able to recover the message contents. In order for both parties to be able to read messages from the other, they must have some kind of shared secret information. One such method is for both par- ties to have a copy of the same key, which both encrypts ("locks") and decrypts ("unlocks") the contents of a message; this is called symmetric-key cryptography. The method or algorithm by which encryption is performed is called a cipher and the encrypted text produced by a cipher is called the ciphertext. Substitution boxes, or S-boxes, are used in order to obscure the relationship between the key and the ciphertext, a property called confusion [19].

11 Middle 4 bits S 4 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 00 0111 1101 1110 0011 0000 0110 1001 1010 0001 0010 1000 0101 1011 1100 0100 1111 Outer 01 1101 1000 1011 0101 0110 1111 0000 0011 0100 0111 0010 1100 0001 1010 1110 1001 bits 10 1010 0110 1001 0000 1100 1011 0111 1101 1111 0001 0011 1110 0101 0010 1000 0100 11 0011 1111 0000 0110 1010 0001 1101 1000 1001 0100 0101 1011 1100 0111 0010 1110

Figure 2.4: DES’s 6×4 S-box S4. Highlighted is the row and column for the input pattern 110000. The output for this pattern is 1111.

2.3.1 Description

Substitution boxes are look-up tables which provide a mapping from a certain input to an output. An example of an S-box is given in Figure 2.4. S-boxes are categorized based on their input and output sizes; a box which takes n bits of input and produces m bits of output is an n×m S-box. The example given is a 6×4 S-box. The input for the example S-box is 6 bits long, the first and last of which are used to determine the row, while the middle 4 bits determine the column. In the example, an input of 110000 results in an output of 1111. Because the rows of the S-box are determined by the most- and least-significant bits, each row will contain outputs for either all odd or all even inputs, when the inputs are interpreted as integers. For an even input i, the next input, i + 1 is on the subsequent row. Additionally, the top two rows contain only outputs for inputs whose first bit is 0, while the bottom two rows contain only outputs for inputs whose first bit is 1. Substitution boxes are used in substitution-permutation networks and Feistel ciphers, both of which divide the encryption process into a number of rounds in which a portion of the message and a portion of the key are combined and then passed through a number of S-boxes to produce a new interim message which will be processed by further rounds of the encryption process [22]. The Data Encryption Standard, or DES, is a superceded symmetric-key encryption scheme which uses a Feistel cipher [3].

DES operates on a 64-bit block of a message and produces a 64-bit ciphertext as output. Each block is passed through 16 rounds, each of which operates on a 32-bit half of a message block and a 48-bit subkey. A different subkey is generated for each round from the overall key. See Figure 2.5.

In each DES round, shown in Figure 2.6, the half-block is first expanded to 48-bits, then the expanded half-block and the subkey are XORed together. The resultant 48-bit block is then passed through 8 predefined S-boxes, each of which takes 6 bits of input and gives a 4-bit output, resulting in a new 32-bit interim message. The interim message is then permuted by a permutation box or P-box which diffuses the contents of the message in order to make the output more uniform and therefore more difficult to analyze. Finally, the result of the P-box is XORed with the half-block which was used as input to the previous round in order to produce the new half-block for the following round [2]. Matsui describes one method by which a cipher may be broken by estimating

12 plaintext

L0 R0

K0 F

K1 F

Kn F

Rn+1 Ln+1 ciphertext

Figure 2.5: Feistel cipher. The 64-bit plaintext is initially split into two 32-bit half-blocks, L0 and R0, and passed into the Feistel function F, along with the subkey for round 0, K0. Each subsequent round follows the same pattern.

Half block Subkey

/ 32

E / 48

/ 48 / / / / / / 6 / 6 6 6 6 6 / 6 6

S1 S2 S3 S4 S5 S6 S7 S8 / / / / / / / / 4 4 4 4 4 4 4 4

P

/ 32

Figure 2.6: Feistel function, F. The 32-bit half-block passes through the extender E to produce a 48-bit extended block. The extended block is XORed with the 48-bit subkey, then split into eight 6-bit portions which are passed through the substitution boxes S1–S8, producing eight 4-bit outputs. These outputs are reassembled into a single 32-bit pattern and finally passed through the permutation box P.

13 β 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...... 13 6 0 2 0 -2 4 -10 -2 0 -2 4 -2 8 -6 0 14 -2 -2 0 -2 4 0 2 -2 0 4 2 -4 6 -2 -4 α 15 -2 -2 8 6 4 0 2 2 4 8 -2 8 -6 2 0 16 2 -2 0 0 -2 -6 -8 0 -2 -2 -4 0 2 10 -20 ......

Table 2.1: Portion of a linear approximation table for DES’s S5 a linear Boolean expression of the cipher for certain output bits and using this expression to reveal the bits of the key [9]. Because his method is made easier if the output of a substitution box is close to a linear function of its inputs, and because S-boxes are the only non-linear part of a Feistel or substitution-permu- tation network, it is critical to the security of the system that the S-boxes be as non-linear as possible [13]. In the next section, we describe ways of evaluating the linearity of an S-box.

2.3.2 Measuring the linearity of an S-box

The linearity of an S-box can be investigated by examining the correlation be- tween the input and output bits of an n×m S-box S. Matsui [9] calculates the probability that a set of input bits α (a bit-vector) coin- cides with a set of output bits β (another bit-vector). A desirable property for an S-box is that this probability, p(α, β), should be close to 1/2, since this gives the least predictable relationship between input and output bits. For an S-box S, the number of matches between a pair α and β is the count of the number of times linear(x, α) equals linear(S(x), β) for all possible inputs x:

N(α, β) = |{x | 0 ≤ x < 2n, linear(x, α) = linear(S(x), β)}| where n is the number of input bits to the S-box and S(x) is the output of the S-box S for the input x. We will call N(α, β) the count of the S-box, as Matsui did not give a name. Since 0 ≤ N(α, β) ≤ 2n, the probability that some α coincides with some β is

N(α, β) p(α, β) = 2n

n Equivalently, since p(α, β) should be close to 1/2, N(α, β) should be close to 2/2. In the case of the 6×4 S-boxes used in DES, N(α, β) should be close to 32. Example 2.1. For a 6×4 S-box and α = 16 (binary 010000), β = 15 (binary 1111), the value N(16, 15) = 12 indicates that the probability that a bit at index 4 of the S-box 1 input coincides with an XORed value of all output bits with probability 12/64 ≈ 0.19.

1Matsui’s example; he gives this as the fourth input bit, presumably using 0-based ordinals

14 N(α, β) itself is less interesting than its closeness to 1/2 which Matsui collects in a table called the linear approximation table, LAT. A portion of the LAT for DES’s S5 substitution box is given in Table 2.1. The rows of the table correspond to α, where 1 ≤ α < 2n, and the columns correspond to β where 1 ≤ β < 2m. An entry in this table is

2n LAT(α, β) = N(α, β) − 2

An S-box is only as good as its weakest point (the LAT entry furthest from zero), so an overall evaluation criterion for non-linearity can be defined as a score, σ, where "good" S-boxes have a lower score:

σ = max {|LAT (α, β)|} α,β

2.3.3 DES S-Box design criteria

DES was designed at IBM in the 1970s, but the design criteria for the substitution boxes were kept a secret until after the description of differential cryptanalysis by Biham and Shamir in [2]. In 1994, Coppersmith disclosed the criteria in [5], given in Table 2.2. Criterion S-2 describes a weaker evaluation of an S-box for linearity than the one given by Matsui [9]. Coppersmith calls Matsui’s variant S-20 and recom- mends it as a better criterion for the evaluation of future cryptographic sys- tems. Specifically, S-2 says only that single output bits should not be "too close to a linear function of the input bits" while S-20 considers all possible combina- tions of output bits. These criteria form the basis of the constraint programming model for substi- tution box generation discussed in the next chapter. Observe that criteria S-4, S-5, and S-6 are requirements on pairs of S-box entries; these can be enforced by pairwise constraints on variables representing these entries. In contrast, criteria S-2, S-3, and S-7 are requirements on groups of variables; these can be enforced by global constraints which can potentially achieve much better propagation than a collection of pairwise constraints expressing the same re- quirement.

15 S-1 Each S-box has six bits of input and four bits of output.

S-2 No output bit of an S-box should be too close to a linear function of the input bits.

S-3 If we fix the leftmost and rightmost input bits of the S-box and vary the four middle bits, each possible 4-bit output is attained exactly once as the middle four input bits range over their 16 possibilities.

S-4 If two inputs to an S-box differ in exactly one bit, the outputs must differ in at least two bits.

S-5 If two inputs to an S-box differ in the two middle bits exactly, the outputs must differ in at least two bits.

S-6 If two inputs to an S-box differ in their first two bits and are identical in their last two bits, the two outputs must not be the same.

S-7 For any nonzero 6-bit difference between inputs, ∆I, no more than eight of the 32 pairs of inputs exhibiting ∆I may result in the same output difference ∆O.

Table 2.2: DES design criteria [5]

16 Chapter 3

Previous work

In this chapter the works on which this thesis is based are presented. We first introduce a bit-vector variable domain and bit-vector constraints described by Michel and Van Hentenryck in [10]. We then review two works by Ramamoor- thy et al. which describe the application of constraint programming to S-box generation and symmetries of S-boxes, based on the DES design criteria [12, 13].

3.1 Bit-vector variables and constraints

Ordering on bit-vectors b1 and b2 is defined according to the integer represen- tation: b1 ≤ b2 if I(b1) ≤ I(b2). A bit-vector domain is a pair hl, ui where l and u are bit-vectors of length k and li ≤ ui for 0 ≤ i < k. Assuming that the length of the bit-vector is less than the length of the word-size of the executing computer, several operations can be done in constant time. The free bits of the domain, the bits which are not assigned to either 1 or 0, are

V(hl, ui) = {i | 0 ≤ i < k, li < ui}

The free bits can be found in constant time

free(hl, ui) = u ⊕ l

The fixed bits of the domain, the bits which are assigned to either 1 or 0, are

F(hl, ui) = {i | 0 ≤ i < k, li = ui}

The fixed bits can be found in constant time

fixed(hl, ui) = ¬ free(l, u)

A bit-vector domain then represents the set of bit-vectors

{b | l ≤ b ≤ u ∧ ∀i ∈ F(hl, ui) : bi = li}

17 A bit domain is the domain of bit i in a bit-vector domain D, Di = {bi | b ∈ D}. A bit-vector variable x is associated with a domain D = hl, ui. lx and ux de- note the bit-vectors defining x’s domain and Fx and Vx denote F(hlx, uxi) and V(hlx, uxi). For a binary constraint c over two bit-vector variables x and y with domains hlx, uxi and hly, uyi, the goal of propagation is to determine new domains hlowx, upxi and hlowy, upyi and to check if the constraint has failed. The check for failure is done by checking if the new domains are valid, that is if ∀i : 0 ≤ i < k : li ≤ ui. This test can be done in constant time by the expression

valid(hl, ui) = ¬(l ⊕ u) ∨ u where valid is true if all bits of the resultant bit-vector are set to 1. Michel and Van Hentenryck define propagators for a number of bit-vector op- erations; described here are only the propagators for the constraints used in the implementation of the DES design criteria. The propagator for equality between two bit-vector variables x and y of equal length is given in Algorithm 3.1.

Algorithm 3.1 Propagator for x = y function propagate(x = y) lowx ← lx ∨ ly lowy ← lowx upx ← ux ∧ uy upy ← upx hlx, uxi ← hlowx, upxi hly, uyi ← hlowy, upyi return valid(hlx, uxi) ∧ valid(hly, uyi) end function

The XOR constraint holds for three bit-vector variables x, y, and z of equal length if x ⊕ y = z, the propagator for this relationship is given in Algo- rithm 3.2.

The AND constraint holds for three bit-vector variables x, y, and z of equal length if x ∧ y = z, the propagator for this relationship is given in Algo- rithm 3.3. The membership constraint, x ∈ [L, U] holds for a bit-vector variable x and in- tegers L and U if L ≤ I(x) ≤ U; the propagator for the membership constraint is given in Algorithm 3.4.

18 Algorithm 3.2 Propagator for x ⊕ y = z function propagate(x ⊕ y = z) lowx ← lx ∨ (¬uz ∧ ly) ∨ (lz ∧ ¬uy) upx ← ux ∧ (uz ∨ uy) ∧ ¬(ly ∧ lz) lowy ← ly ∨ (¬uz ∧ lx) ∨ (lz ∧ ¬ux) upy ← uy ∧ (uz ∨ ux) ∧ ¬(lx ∧ lz) lowz ← lz ∨ (¬ux ∧ ly) ∨ (lx ∧ ¬uy) upz ← uz ∧ (ux ∨ uy) ∧ ¬(lx ∧ ly) hlx, uxi ← hlowx, upxi hly, uyi ← hlowy, upyi hlz, uzi ← hlowz, upzi return valid(hlx, uxi) ∧ valid(hly, uyi) ∧ valid(hlz, uzi) end function

Algorithm 3.3 Propagator for x ∧ y = z function propagate(x ∧ y = z) upx ← ux ∧ (¬((¬uz) ∧ ly)) lowx ← lx ∨ lz upy ← uy ∧ (¬((¬uz) ∧ lx)) lowy ← ly ∨ lz upz ← uz ∧ ux ∧ uy lowz ← lz ∨ (lx ∧ ly) hlx, uxi ← hlowx, upxi hly, uyi ← hlowy, upyi hlz, uzi ← hlowz, upzi return valid(hlx, uxi) ∧ valid(hly, uyi) ∧ valid(hlz, uzi) end function

Algorithm 3.4 Propagator for x ∈ [L, U] function propagate(x ∈ [L, U]) i ← k − 1 while i ≥ 0 do if I(ux) < L ∨ I(lx) > U then return false if i ∈ Vx then if I(ux) − 2i < L then x li = 1 else if I(lx) + 2i > U then x ui = 0 else break i ← i − 1 return true end function

19 The constraint channel(x, X) for a bit-vector variable x and an integer variable X channels the domain bounds of x to X and vice-versa; a propagator for chan- neling is given in Algorithm 3.5.

Algorithm 3.5 Propagator for channel(x, X) function propagate(channel(x, X)) if ¬ propagate(X ∈ [I(lx), I(ux)]) then return false if ¬ propagate(x ∈ DX) then return false return propagate(X ∈ [I(lx), I(ux)]) end function

3.2 Constraint programming and substitution boxes

Ramamoorthy et al. propose the application of constraint programming to S-box generation, using the DES design criteria as a basis for their recommended con- straints [13]. They represent an n×m S-box as an array of 2n decision variables, which ful- fills criterion S-1. For criterion S-2, they introduce a series of heuristics for evaluating non-linearity of S-boxes. They then define additional constraints for criteria S-3–S-7. For an S-box S, the decision variable corresponding to an input x is denoted S(x).

3.2.1 Criterion S-2

To enforce criterion S-2, the non-linearity constraint, Ramamoorthy et al. ini- tially propose a hard constraint, HS, which requires fully-assigned S-boxes to have a score not exceeding a threshold τ: σ ≤ τ. They then extend the idea of a threshold to S-boxes which have φ or more assigned variables. This "incomplete, incremental heuristic," HI, allows the solver to fail a space where the score of the partially-filled S-box, σφ (defined below), exceeds the threshold τ: σφ ≤ τ. Note that in the context of HI, φ is a fixed value, so the heuristic does nothing until there are at least φ assigned variables.

Finally, they propose a "complete, incremental heuristic," HC, which does not require a fixed number of assigned variables. They again use a threshold, τ, while the number of currently-assigned variables is given by φ:

n n 2  2 φ − τ − ≤ max Nφ(α, β) ≤ + τ 2 α,β 2

This HC heuristic requires that the weakest point of the S-box have a count which falls within the range of the threshold. The upper bound is unchanged from HS and HI, but the lower bound ensures that it is possible for the count of the partially-filled S-box to reach some part of the acceptable range given

20 the remaining number of unassigned variables. Nφ(α, β) adds a clause to the counting of matches between α and β, namely that S(x) must be assigned:

n Nφ(α, β) = |{x | 0 ≤ x < 2 , assigned (S (x)) ∧ linear (x, α) = linear (S (x) , β)}|

Recall that the count, N(α, β), has the range 0 ≤ N(α, β) ≤ 2n where n is the φ size of the S-box inputs. Nφ(α, β) therefore has the range 0 ≤ Nφ(α, β) ≤ 2 . The score for a partially-assigned S-box with φ assigned variables is then de- fined in terms of Nφ(α, β) (omitting the linear approximation table, LAT):

 n  2 σφ = max Nφ(α, β) − α,β 2

As given by Ramamoorthy et al., HC is actually not complete; we describe why and extend the definition slightly in Section 4.2.

3.2.2 Criterion S-3

Criterion S-3 requires that the set of inputs with the same first and last bits must take on distinct values. The structure of the S-boxes are such that this is equivalent to saying that the variables in each row must take distinct values:

∀i : 1 ≤ i ≤ 4 : alldifferent(rowi)

3.2.3 Criterion S-4

Criterion S-4 requires that for any two inputs x and y which differ in exactly one bit, S(x) and S(y) must differ in at least two bits. The XOR (⊕) operation results in a bit-vector indicating bits which differ, and the Hamming weight applied to the resultant bit-vector gives a count of how many bits differ:

∀x : 0 ≤ x < 2n : ∀y : x + 1 ≤ y < 2n : weight (x ⊕ y) = 1 =⇒ weight (S(x) ⊕ S(y)) ≥ 2

3.2.4 Criterion S-5

Criterion S-5 requires that for any two inputs x and y which differ in exactly the two middle bits, S(x) and S(y) must differ in at least two bits. For a 6×4 S-box, the bit-vector with the two middle bits set is 001100:

∀x : 0 ≤ x < 2n : ∀y : x + 1 ≤ y < 2n : (x ⊕ y) = 001100 =⇒ weight(S(x) ⊕ S(y)) ≥ 2

21 3.2.5 Criterion S-6

Criterion S-6 requires that for any two x and y which differ in their first two bits but are the same in their last two, S(x) and S(y) must not be equal. The XOR (⊕) operation over two bit-vectors gives the bits which differ. For a 6×4 S-box, applying an AND (∧) to the result of the XOR operation and the bit-vector 110011 isolates the first two and last two bits; if the result is equal to 110000 then the input bit-vectors differ in their first two bits but are equal in their last two bits:

∀x : 0 ≤ x < 2n : ∀y : x + 1 ≤ y < 2n : ((x ⊕ y) ∧ 110011) = 110000 =⇒ S(x) 6= S(y)

Ramamoorthy et al. give two different values for the equality, 3 · 2n−1 and 3 · 2n−2; it is the second of these which is correct. For a 6×4 S-box, this is equivalent to the bit-vector 110000.

3.2.6 Criterion S-7

Unfortunately, it appears that Ramamoorthy et al. have not fully encoded the S-7 criterion. Specifically, they have only defined their S-7 constraint for the the input difference ∆I = 111111 [20]. They specify S-7 in terms of input pairs hi, 2n − 1 − ii, 0 ≤ i < 2n−1 which, for a 6×4 S-box represents ∆I = 111111 for all pairs; these are pairs in which all six bits differ.

Meanwhile, Coppersmith, who was involved in the design of DES, gives 110100 as an example of ∆I; such a ∆I is not covered by the constraint defined by Ramamoorthy et al. The incomplete S-7 constraint invalidates the main experimental result given by Ramamoorthy et al.; they claim to have found a large number of 6×4 S-boxes with score 8. However, although the single instance of such a S-box given in their paper does have a score of 8, it violates the full S-7 constraint. A complete constraint for S-7 is given in Section 4.3.

3.3 Symmetries

Ramamoorthy et al. also describe several symmetries of S-boxes and means to break these symmetries [12]. Based on analysis of constraints S-4, S-5, and S-6, they identify row, column, and diagonal symmetries. The row symmetry allows the top two rows of the S-box to be exchanged so long as the bottom two are simultaneously exchanged. To break the row sym- metry, the integer interpretation of the value for input 0 is constrained to be less than or equal to the integer interpretation of the value for the same position in the next row, namely input 1: I(S(0)) ≤ I(S(1)). The column symmetry allows certain pairs of columns to be exchanged, as long as they are all simultaneously exchanged. Columns 0 and 6 are one such pair

22 in a 6×4 S-box, so this symmetry can be broken by constraining the value for input 0 (which is in column 0) to be less than or equal to the value for input 12 (which is in column 6): I(S(0)) ≤ I(S(12)). The diagonal symmetry allows a quadrant of the S-box to be exchanged with the quadrant diagonal from it as long as both pairs of quadrants are switched simultaneously. The top-left quadrant will therefore be exchanged with the lower-right quadrant; in a 6×4 S-box, the top-left value of the top-left quadrant is the value for input 0, while the top-left value of the bottom-right quadrant is the value for input 48. To break the diagonal symmetry, the integer repre- sentation of the value for input 0 is constrained to be less than or equal to the integer representation of the value for the input 48: I(S(0)) ≤ I(S(48)). They then describe a rotational symmetry and a symmetry they call bit inver- sion symmetry. First, they establish some properties of bit-vectors and linear approximation tables. They show that the linear combination of the bitwise negation of a bit-vector x and a constant bit-vector y is

linear(¬x, y) = linear(x, y) ⊕ parity(y)

Changing an assignment for an input x from S(x) to ¬S(x) changes the entry LAT(α, β) such that the new entry, LAT0(α, β) is:   LAT0(α, β) = LAT(α, β) + −1linear(x,α)⊕linear(¬S(x),β) · parity(β)

Swapping the assignments for the inputs x and ¬x changes the entry LAT(α, β) such that the new entry, LAT0(α, β) is: ! ! − 1linear(x,α)⊕linear(¬S(x),β)+ LAT0(α, β) = LAT(α, β) + · parity(α) − 1linear(¬x,α)⊕linear(¬S(¬x),β)

Using these properties, they show that the score of a complete assignment re- mains unchanged if its assigned values are replaced by the NOT of those values; they call this the bit inversion symmetry. To break this symmetry, the domain of the variable for input 0 is limited to the range 0–(2m−1 − 1) (i.e., the most sig- nificant bit is set to 0). For a 6×4 S-box, this becomes: I(S(0)) ≤ 7. They also show that the score of a complete assignment remains unchanged if the assigned values are swapped between the variables x and ¬x; this is equivalent to rotating an S-box by 180◦. To break this symmetry, the variable for input 0 can be constrained to be less-than or equal-to the variable for input 2n − 1. For a 6×4 S-box, the integer representation of the value for input 0 is therefore constrained to be less than or equal to the integer representation of the value value for input 63: I(S(0)) ≤ I(S(63)).

23

Chapter 4

Theoretical contributions

In this chapter we describe several new bit-vector propagators for typical bit- vector operations, we present an addition to the HC heuristic, we correct the S-7 constraint presented by Ramamoorthy et al. [12], and finally we identify two new symmetries of S-boxes.

4.1 Propagators

Most of the bit-vector propagators implemented have already been described in Section 3.1. Some additional propagators are necessary for working with S-boxes but are nevertheless generally useful.

4.1.1 Hamming weight

The constraint weight(x) = y holds for a bit-vector variable x and an integer variable y when y is equal to the Hamming weight of x; a propagation algo- rithm is given in Algorithm 4.1. For a bit-vector variable x, the possible Ham- ming weights are an interval [min_weight, max_weight]. The minimum weight of x, min_weight, is the weight of the currently-fixed bits of the bit-vector variable if the free bits are fixed to zero. This is exactly the same as the lower bound, lx, where all the free bits are taken as 0, while the fixed bits have their final values, so min_weight = weight(lx). Conversely, for the maximum weight of x, max_weight: if all of the currently- free bits are fixed to 1, then x will be exactly equal to ux, and weight(x) = weight(ux), so max_weight = weight(ux). Otherwise, the integer variable y is exactly equal to either the minimum or maximum weight of the bit-vector x, and x must be exactly lx or ux, respec- tively. The complexity of the propagator for weight(x) = y itself is O1: it needs only to compute the maximum and minimum weights of x, both of which can be done in constant time for bit-vector variables less than the word length of the

25 underlying architecture. In our development environment, a 32-bit Linux using gcc 4.7.2, weight is implemented by the standard library bitset.count(). In- ternally, bitset uses the gcc-built-in function __builtin_popcount, which on our system compiles to a single processor instruction: __popcountsi2.

Algorithm 4.1 Propagator for weight(x) = y function propagate(weight(x) = y) min_weight ← weight(lx) max_weight ← weight(ux) if ¬ propagate(y ∈ [min_weight, max_weight]) then return false if assigned(y) then if y = max_weight then if ¬ propagate(x = ux) then return false if y = mix_weight then if ¬ propagate(x = lx) then return false return true end function

4.1.2 Parity

The constraint parity(x) = y holds for a bit-vector variable x and a Boolean variable y when y is equal to the parity of x. Recall that parity(x) is true (1) when the number of set bits in x is odd and false (0) otherwise. A propagation algorithm is given in Algorithm 4.2.

It is possible to fix the value of the Boolean variable y only when x is assigned. In this case, y is propagated to the value true when parity(x) = 1 and to false when parity(x) = 0.

If y is assigned and x has only a single free bit, it is possible to fix this bit based on the value of y: if y is equal to the parity of the bits currently set to 1, then this final bit must be 0, otherwise, this final bit must be 1. The parity of the bits currently set to 1 is equivalent to the parity of the lower bound of x, parity(lx).

The propagator for parity(x) = y takes O1 time; it must determine if a vari- able is assigned, it must find the free bits of a bit-vector variable, it must calcu- late the weight of a bit-vector, and it must calculate the parity of a bit-vector. We have previously described that the first three of these can be calculated in constant time.

The parity can be calculated by linear scan (On time on the number of bits n), by a "bit twiddling hack" [1] (O1 time with a look-up table), or by a gcc-builtin (also O1 time, no look-up table necessary). In our development environment, parity is implemented using the gcc-built-in function __builtin_- parity, which compiles down to a series of 8 assembly instructions.

26 Algorithm 4.2 Propagator for parity(x) = y function propagate(parity(x) = y) if assigned(x) then if parity(x) = 1 then if ¬ propagate(y = true) then return false else if ¬ propagate(y = false) then return false if assigned(y) ∧ ¬ assigned(x) then if weight(free(hlx, uxi)) = 1 then current_parity ← parity(lx) if y = current_parity then if ¬ propagate(x = lx) then return false else if ¬ propagate(x = ux) then return false return true end function

4.1.3 Disequality

The disequality constraint holds for a pair of bit-vectors, x and y, if x 6= y.A propagation algorithm is given in Algorithm 4.3. For the constraint x 6= y to hold, at least one bit of the fixed bits which are common to both bit-vectors, fixed_both, must be unequal when x and y are both assigned. If one of the bits of the common fixed bits becomes unequal at some point before both are assigned, the propagator may be subsumed. If both bit-vectors are assigned, but their common bits are equal, then x = y, so the propagator returns failure. If one bit-vector is assigned while the other has a single free bit and the values of the common bits are equal, then the value of the final bit can be determined. If x is the assigned bit-vector, then the value of x for the free bit of y can be masked off with lx ∧ free(hly, uyi). Inverting this value produces a mask such that uy ∧ ¬(lx ∧ free(hly, uyi)) will be equivalent to y with the final free bit set to the inverse of the value of that bit in x. The propagator for x 6= y is also O1 time. The propagator must check for assignment, find the free and fixed bits of bit-vector variables, calculate their Hamming weight, and apply bitwise operations. We have previously pre- sented constant-time operations for all of these.

27 Algorithm 4.3 Propagator for x 6= y function propagate(x 6= y) fixed_both ← fixed(lx, ux) ∧ fixed(ly, uy) if (lx ∧ fixed_both) 6= (ly ∧ fixed_both) then return true if assigned(x) ∧ assigned(y) then return false if (assigned(x) ∧ ¬ assigned(y)) ∨ (¬ assigned(x) ∧ assigned(y)) then free_y ← free(hly, uyi) if assigned(x) ∧ weight(free_y) = 1 then if ¬ propagate(y = uy ∧ ¬(lx ∧ free_y)) then return false free_x ← free(hlx, uxi) if assigned(y) ∧ weight(free_x) = 1 then if ¬ propagate(x = ux ∧ ¬(ly ∧ free_x)) then return false return true end function

4.2 An extension to the constraint for criterion S-2

The goal of the HC heuristic, described in Section 3.2.1, is to ensure that the overall score of the S-box is at most τ, but Ramamoorthy et al. only define HC in terms of the maximum of Nφ(α, β), omitting the minimum value, which can also be the cause of a high (bad) score [13]. We therefore also define a lower bound which ensures that given φ assigned variables, it is possible for the min- imum value of Nφ(α, β) to reach the acceptable range once all values become assigned: n  2 n min Nφ(α, β) ≥ − τ − (2 − φ) α,β 2

  Since minα,β Nφ(α, β) ≤ maxα,β Nφ(α, β) , the lower bound in Ramamoor- thy et al.’s version of HC can be omitted, and the remaining test is:

n  2 max Nφ(α, β) ≤ + τ α,β 2

This altered definition of HC is incorporated into the implementations of S-2 given in Section 6.

4.3 Corrected S-7 constraint

The S-7 criterion requires that for each group of pairs of inputs whose differ- ence is the same (and non-zero), at most eight pairs can have the same output difference. For this criterion, which is described as applying to "any nonzero 6-bit difference", Ramamoorthy et al. have only considered the case where six bits of inputs x and y (see Section 3.2.6).

28 A corrected constraint for S-7 for an input XOR i and an output XOR o is as follows:

∀i : 1 ≤ i < 2n : ∀o : 0 ≤ o < 2m : 8 ≥ |{hx, yi | 0 ≤ x < y < 2n, x ⊕ y = i ∧ S(x) ⊕ S(y) = o}|

Biham and Shamir collect the counts for each difference in a table called the pairs XOR distribution table. They use ordered pairs instead of unordered pairs as given here; the DES threshold would need to be increased to 16 if applied to their counts [2].

4.4 Reflective symmetry

Ramamoorthy et al. define several types of symmetry: bit-inversion symmetry in which the value of an S-box S(x) is replaced with its inverse, ¬S(x), rota- tional symmetry for a 180◦ rotation, row symmetry in which certain rows are exchanged, column symmetry in which certain columns are exchanged, and diagonal symmetry in which blocks of values in the S-box are exchanged diag- onally [12]. We additionally identify a reflective symmetry over the x axis and a reflective symmetry over the y axis.

4.4.1 Reflection over the x-axis

Reflecting an S-box S over the x-axis produces a new S-box, S0 in which the values in row 1 are exchanged for those in row 4 and the values in row 2 are exchanged for those in row 3, and vice-versa. Reflecting a 6 × 4 S-box S, for any input x to S, the value at S(x) will be moved to input x ⊕ 100001. For an n×m S-box this is x ⊕ (2n−1 + 20). For this to be a symmetry, the constraints applied to S should not be violated 0 for S , and conversely. The DES criterion S-1 is already fulfilled by the choice of variables.

Non-linearity criterion S-2

The S-2 criterion requires that no output bit should be "too close" to a linear function of the input bits. This measure of linearity is captured in the count N(α, β) and the score σ. Recall that the linear combination of two bit-vectors x and y of equal length is:

linear(x, y) = (x0 ∧ y0) ⊕ (x1 ∧ y1) ⊕ ... ⊕ (xn−1 ∧ yn−1)

k If it is known that a bit k is 0 in x, then linear(x + 2 , y) = linear(x) ⊕ yk. Recall that the count of the S-box is defined as:

N(α, β) = |{x | 0 ≤ x < 2n, linear(x, α) = linear(S(x), β)}|

29 It is possible to rewrite N(α, β) as a column-based sum (assuming four rows):

 1 ⊕ linear(2i, α) ⊕ linear(S(2i), β)+  2n−2−1  ⊕ linear( + ) ⊕ linear( ( + ) )+   1 2i 1, α S 2i 1 , β  N(α, β) =   ∑  1 ⊕ linear(2i + 2n−1, α) ⊕ linear(S(2i + 2n−1), β)+  i=0   1 ⊕ linear(2i + 2n−1 + 1, α) ⊕ linear(S(2i + 2n−1 + 1), β)

The top line of the sum corresponds to the first row of the S-box, the second line to the second row, and so on. Due to the range of i, the 0-th and n − 1-st bits of 2 · i will always be zero and because of this, terms like linear(2i + 2n−1 + 1) can be reduced:

 1 ⊕ linear(2i, α) ⊕ linear(S(2i), β)+  2n−2−1  ⊕ linear( ) ⊕ ⊕ linear( ( + ) )+   1 2i, α α0 S 2i 1 , β  N(α, β) =   ∑  1 ⊕ linear(2i, α) ⊕ α ⊕ linear(S(2i + 2n−1), β)+  i=0  n−1  n−1 1 ⊕ linear(2i, α) ⊕ α0 ⊕ αn−1 ⊕ linear(S(2i + 2 + 1), β)

Reflecting over the x axis alters the values in each column. The corresponding N0(α, β) for the reflection of the S-box over the x axis involves swapping the values S(2i) and S(2i + 2n−1 + 1) and the values S(2i + 1) and S(2i + 2n−1) to get the sum:   1 ⊕ linear(2i, α) ⊕ linear(S(2i + 2n−1 + 1), β)+ 2n−2−1  n−1  0  1 ⊕ linear(2i, α) ⊕ α ⊕ linear(S(2i + 2 ), β)+ N (α, β) =  0  ∑  linear linear  i=0  1 ⊕ (2i, α) ⊕ αn−1 ⊕ (S(2i + 1), β)+  1 ⊕ linear(2i, α) ⊕ α0 ⊕ αn−1 ⊕ linear(S(2i), β)

When a0 and an−1 are both equal to 0 or both equal to 1, observe that N(α, β) = 0 N (α, β). For a0 = an−1 = 1:

 1 ⊕ linear(2i, α) ⊕ linear(S(2i), β)+  2n−2−1  ⊕ linear( ) ⊕ ⊕ linear( ( + ) )+   1 2i, α 1 S 2i 1 , β  N(α, β) =   ∑  1 ⊕ linear(2i, α) ⊕ 1 ⊕ linear(S(2i + 2n−1), β)+  i=0   1 ⊕ linear(2i, α) ⊕ 1 ⊕ 1 ⊕ linear(S(2i + 2n−1 + 1), β)  1 ⊕ linear(2i, α) ⊕ linear(S(2i), β)+  2n−2−1  linear( ) ⊕ linear( ( + ) )+   2i, α S 2i 1 , β  =   ∑  linear(2i, α) ⊕ linear(S(2i + 2n−1), β)+  i=0   1 ⊕ linear(2i, α) ⊕ linear(S(2i + 2n−1 + 1), β)   1 ⊕ linear(2i, α) ⊕ linear(S(2i + 2n−1 + 1), β)+ 2n−2−1  n−1  0  1 ⊕ linear(2i, α) ⊕ 1 ⊕ linear(S(2i + 2 ), β)+ N (α, β) =   ∑  linear linear  i=0  1 ⊕ (2i, α) ⊕ 1 ⊕ (S(2i + 1), β)+  1 ⊕ linear(2i, α) ⊕ 1 ⊕ 1 ⊕ linear(S(2i), β)

30   1 ⊕ linear(2i, α) ⊕ linear(S(2i + 2n−1 + 1), β)+ 2n−2−1  −   linear(2i, α) ⊕ linear(S(2i + 2n 1), β)+  =   ∑  linear linear  i=0  (2i, α) ⊕ (S(2i + 1), β)+  1 ⊕ linear(2i, α) ⊕ linear(S(2i), β) = N(α, β)

The same equality holds if a0 = an−1 = 0. 0 n When a0 6= an−1, however, N (α, β) = 2 − N(α, β). For a0 = 0, an−1 = 1:  1 ⊕ linear(2i, α) ⊕ linear(S(2i), β)+  2n−2−1  ⊕ linear( ) ⊕ ⊕ linear( ( + ) )+   1 2i, α 0 S 2i 1 , β  N(α, β) =   ∑  1 ⊕ linear(2i, α) ⊕ 1 ⊕ linear(S(2i + 2n−1), β)+  i=0   1 ⊕ linear(2i, α) ⊕ 0 ⊕ 1 ⊕ linear(S(2i + 2n−1 + 1), β)  1 ⊕ linear(2i, α) ⊕ linear(S(2i), β)+  2n−2−1  ⊕ linear( ) ⊕ linear( ( + ) )+   1 2i, α S 2i 1 , β  =   ∑  linear(2i, α) ⊕ linear(S(2i + 2n−1), β)+  i=0   linear(2i, α) ⊕ linear(S(2i + 2n−1 + 1), β)   1 ⊕ linear(2i, α) ⊕ linear(S(2i + 2n−1 + 1), β)+ 2n−2−1  n−1  0  1 ⊕ linear(2i, α) ⊕ 0 ⊕ linear(S(2i + 2 ), β)+ N (α, β) =   ∑  linear linear  i=0  1 ⊕ (2i, α) ⊕ 1 ⊕ (S(2i + 1), β)+  1 ⊕ linear(2i, α) ⊕ 0 ⊕ 1 ⊕ linear(S(2i), β)   1 ⊕ linear(2i, α) ⊕ linear(S(2i + 2n−1 + 1), β)+ 2n−2−1  −   1 ⊕ linear(2i, α) ⊕ linear(S(2i + 2n 1), β)+  =   ∑  linear linear  i=0  (2i, α) ⊕ (S(2i + 1), β)+  linear(2i, α) ⊕ linear(S(2i), β)

Notice that when the term for a row is added to N(α, β), its inverse is added to N0(α, β). Since these are Boolean terms and there are four rows and 2n−2 columns of terms to be summed, N(α, β) + N0(α, β) = 2n−2 · 22 = 2n, which 0 n then implies that N (α, β) = 2 − N(α, β). The same equality holds for α0 = 1, αn−1 = 0. Recall that the score, σ, of an S-box is defined as  n  2 σ = max N(α, β) − α,β 2

n 0 Let A = |N(α, β) − 2 /2|. The corresponding A for the reflected S-box has two cases, one for α0 = αn−1 and another for α0 6= αn−1:

( 0 n N (α, β) − 2 /2 if α = α − 0 = 0 n 1 A 0 n N (α, β) − 2 /2 if α0 6= αn−1 n |N(α, β) − 2 /2| if α = α = 0 n−1 n n |2 − N(α, β) − 2 /2| if α0 6= αn−1

31  n |N(α, β) − 2 /2| if α0 = αn−1 = n |N(α, β) − 2 /2| if α0 6= αn−1 n = |N(α, β) − 2 /2| = A

So the score for the reflected S-box, σ0, is the same as σ: σ0 = max A0 = max {A} = σ α,β α,β

Since the reflected S-box has the same score as the original S-box, the original S-box fulfills criterion S-2 if and only if the reflected S-box also fulfills criterion S-2.

Criterion S-3

Criterion S-3 requires that the values of each row are distinct; the original S-box has this property if and only if the reflected S-box also has this property.

Criterion S-4

Criterion S-4 is a constraint on pairs of bit-vector variables, x and y, whose inputs differ by a single bit, that is that weight(x ⊕ y) = 1. In the reflected S-box, S0, the input x is moved to x ⊕ (2n−1 + 20) and the input y is moved to y ⊕ (2n−1 + 20). Because x ⊕ (2n−1 + 20) ⊕ y ⊕ (2n−1 + 20) = x ⊕ y, reflecting S to S0 maintains this relationship between x and y, so criterion S-4 is fulfilled in S if and only if it is also fulfilled in S0.

Criterion S-5

Criterion S-5 is a constraint on pairs of bit-vector variables whose inputs differ in the "two middle bits exactly." Variables which have this property belong to the same row of the S-box, and these middle bits are not affected by the reflection, so this constraint is fulfilled by S if and only if it is also fulfilled by S0.

Criterion S-6

Criterion S-6 is a constraint on pairs of bit-vector variables whose inputs differ in their first two bits, but are the same in their last two. For a given input x, the inputs related to x are several variables y such that (x ⊕ y) ∧ (2n−1 + 2n−2 + 21 + 20) = (2n−1 + 2n−2). In the reflected S-box, S0, the input x is moved to x ⊕ (2n−1 + 20) and y is moved to y ⊕ (2n−1 + 20). And because x ⊕ (2n−1 + 20) ⊕ y ⊕ (2n−1 + 20) = (x ⊕ y), the relationship between these inputs is maintained in S0.

Criterion S-7

Criterion S-7 places a constraint on sets of pairs of bit-vector variables whose inputs x and y differ for some input difference i: x ⊕ y = i.

32 Again, because x ⊕ (2n−1 + 20) ⊕ y ⊕ (2n−1 + 20) = (x ⊕ y), this relationship is unchanged for the reflected S-box S0, so criterion S-7 is fulfilled in S if and only if it is also fulfilled in S0.

4.4.2 Reflection over the y-axis

We have shown that reflection over the x axis is a symmetry, while Ramamoor- thy et al. have shown a 180◦ degree rotational symmetry. A reflection over the y-axis is equivalent to a reflection over the x axis followed by a 180◦ rotation. If an S-box S fulfills criteria S-1–S-7, then so does an S-box S0 which is reflected over the x-axis, and so does an S-box S00 which is S0 rotated by 180◦, which in turn is equivalent to an S-box reflected over the y-axis.

4.4.3 Symmetry-breaking

During search, reflective symmetry over the x-axis can be broken by constrain- ing the variable at the top-left of the S-box to be less than or equal to the vari- able at the bottom-left of the S-box. For a 6×4 S-box, these are the variables for input 0 and 33: I(S(0)) ≤ I(S(33)). The reflective symmetry over the y-axis can be broken during search by con- straining the variable at the top-left of the S-box to be less than or equal to the variable at the top-right of the S-box. For a 6×4 S-box, these are the variables for input 0 and 30: I(S(0)) ≤ I(S(30)).

33

Chapter 5

Bit-vector implementation for Gecode

The implementation of variables for Gecode consists of defining variable imple- mentations, variables and variable arrays, variable views, propagators, and branch- ings. This process is covered extensively by [15]. Variable implementations are the objects which actually store the variable do- mains and which implement the operations which manipulate the domain. Variables are read-only interfaces to variable implementations that enable mul- tiple variables to refer to the same implementation. Variable arrays are just arrays of variables. Variable views allow Gecode to decouple variable imple- mentations from propagator implementations. Propagators are the implemen- tations of constraints for a given variable type. Branchings consist of variable and value selection functions which choose variables on which to branch and which value to fix for each branch of the search tree. Presented below are the implementation details for each of these components for the bit-vector variables and propagators implemented in this thesis.

5.1 Variable implementations

The domain of the bit-vector variable implementation is defined by a pair of bit-vectors, hl, ui, as described in Section 3.1. These upper and lower bounds of the bit-vector variables are represented as unsigned ints, which are typically the same size as a machine’s word size [11]. The variable implementation also contains an unsigned int n, the number of bits to use for the variable, where n must be less-than or equal to the length of l and u, that is, the length of an unsigned int, and a bit-mask m which masks the lower n bits. A new variable type must be compiled into Gecode by way of a variable imple- mentation specification file which defines the variable name, its C++ namespace, the possible modification events, and the possible propagation conditions. Modification events describe how the domain of a view has changed. All vari-

35 modification event description ME_BIT_NONE no change to the variable domain ME_BIT_FAILED the variable domain is failed ME_BIT_VAL the variable has become assigned ME_BIT_LOWER the lower bound of the variable domain has changed ME_BIT_UPPER the upper bound of the variable domain has changed ME_BIT_BND both the upper and lower bounds have changed

Table 5.1: Bit-vector modification events

propagation condition description PC_BIT_NONE the propagator will not create any subscriptions PC_BIT_VAL will schedule a propagator when a subscribed variable is assigned PC_BIT_LOWER will schedule a propagator when a subscribed variable’s lower bound is altered PC_BIT_UPPER will schedule a propagator when a subscribed variable’s upper bound is altered PC_BIT_BND will schedule a propagator when a subscribed variable’s upper or lower bound is altered

Table 5.2: Bit-vector propagation conditions able implementations must provide modification events for NONE, FAILED, and ASSIGNED (aliased as VAL). We define these modification events and the addi- tional events for when the the lower and upper bounds of a variable’s domain change (LOWER and UPPER) or when both change (BND). All modification events are listed in Table 5.1.

Propagation conditions describe when a propagator is scheduled depending on how the views to which it is subscribed are modified. All variable im- plementations must provide propagation conditions for NONE and ASSIGNED (aliased as VAL). We additionally define propagation conditions for when a view’s upper, lower, or both bounds change (UPPER, LOWER, BND), summarized in Table 5.2.

Variable implementations must implement an assigned function, which re- turns true when the implementation becomes assigned; in the case of bit- vectors, this is when l = u.

The implementation must also provide subscribe and cancel functions which are used by propagators to be notified upon certain propagation conditions, functions for copying the variable during search, and access operations to the relevant member variables: for bit-vectors these are lower and upper for the variable bounds, num_bits for the number of bits n, and mask for the mask of the lower n bits.

Finally, the implementation must provide some way of modifying the variable domain and ensure that these modification operations return the correct modi- fication events. For bit-vectors, these are lower and upper which set the lower or upper bound to a passed value, and bounds, which sets both the lower and upper bounds simultaneously.

36 Gecode supports a construct called an advisor which is used to improve incre- mental propagation. Advisors use deltas to communicate changes in variable domains. Our bit-vector variable implementation does not support this feature and therefore does not provide deltas to be used by advisors; it indicates this by the GECODE_NEVER macro in the relevant functions.

5.2 Variables & variable arrays

Variables are read-only interfaces to variable implementations, where each im- plementation can be referred to by an arbitrary number of variables [15]. The code to be written for a variable is minimal and consists of a few construc- tors and a pair of access operations which pass directly through to the variable implementation, lower and upper. The code for variable arrays is similarly simple; the constructors initialize the relevant number of variables.

5.3 Variable views

Variable views are used by Gecode to decouple the variable implementations from propagator implementation. Each view implements the same operations as a variable. Gecode supports variable implementation views which maintain a reference to a variable and directly invoke operations on this backing variable, constant views where the view behaves as a variable equal to some constant c without the need for a backing variable, and derived views which reference another view instead of a variable [17]. Propagators can then be implemented generically to operate on these views [16]. [15] gives examples of derived views for integer variables: an offset view, which adds a constant factor c and a scale view, which scales the variable value by a constant a. The implementation described here contains a variable implementation view and a constant view for bit-vectors.

5.4 Propagators

The code necessary to implement the propagate function in Gecode is similar to the pseudocode defined in Sections 3.1 and 4.1. The propagate function for the XOR propagator implementation given in Listing 5.1 corresponds closely with the XOR propagator in Algorithm 5.1 (a slightly altered version of Algo- rithm 3.2 which more clearly shows the parallels). For example, lines 11–12 in Listing 5.1 correspond to lines 2–3 in Algorithm 5.1, while line 13 corresponds to lines 4–5.

37 Listing 5.1 XOR propagate function 1: ExecStatus 2: Exor::propagate(Space& home, 3: const ModEventDelta&) { 4: BitType ux = x0.upper(); 5: BitType uy = x1.upper(); 6: BitType uz = x2.upper(); 7: BitType lx = x0.lower(); 8: BitType ly = x1.lower(); 9: BitType lz = x2.lower(); 10: 11: BitType lowx = lx | ((~ uz) & ly) | (lz & (~ uy)); 12: BitType upx = ux & (uz | uy) & (~ (ly & lz)); 13: GECODE_ME_CHECK(x0.bounds(home, upx, lowx)); 14: 15: BitType lowy = ly | ((~ uz) & lx) | (lz & (~ ux)); 16: BitType upy = uy & (uz | ux) & (~ (lx & lz)); 17: GECODE_ME_CHECK(x1.bounds(home, upy, lowy)); 18: 19: BitType lowz = lz | ((~ ux) & ly) | (lx & (~ uy)); 20: BitType upz = uz & (ux | uy) & (~ (lx & ly)); 21: GECODE_ME_CHECK(x2.bounds(home, upz, lowz)); 22: 23: if(x0.assigned() && x1.assigned() && x2.assigned()) { 24: return home.ES_SUBSUMED(*this); 25: } 26: return ES_FIX; 27: }

Algorithm 5.1 Altered propagator for x ⊕ y = z 1: function propagate(x ⊕ y = z) x 2: low ← lx ∨ (¬uz ∧ ly) ∨ (lz ∧ ¬uy) 3: upx ← ux ∧ (uz ∨ uy) ∧ ¬(ly ∧ lz) x 4: hlx, uxi ← hlow , upxi 5: if ¬ valid(hlx, uxi) then 6: return false y 7: low ← ly ∨ (¬uz ∧ lx) ∨ (lz ∧ ¬ux) 8: upy ← uy ∧ (uz ∨ ux) ∧ ¬(lx ∧ lz) y 9: hly, uyi ← hlow , upyi 10: if ¬ valid(hly, uyi) then 11: return false z 12: low ← lz ∨ (¬ux ∧ ly) ∨ (lx ∧ ¬uy) 13: upz ← uz ∧ (ux ∨ uy) ∧ ¬(lx ∧ ly) z 14: hlz, uzi ← hlow , upzi 15: if ¬ valid(hlz, uzi) then 16: return false 17: return true 18: end function

38 5.5 Branchings

The implementation of branchings in Gecode requires variable selection and value selection functions, a default merit function, and a branch commit func- tion [15]. The bit-vector implementation provides a number of variable-value branchings. Variable selection functions operate on a number of decision variables and choose a best-suited variable on which to branch based on the given selec- tion strategy. For bit-vector variables, the possible variable selection functions are given in Table 5.3. The variable selection code itself is mostly boilerplate, which uses Gecode ViewSel classes to do the actual variable selection. In the case of ties, the variable with the lowest index in the array is chosen by default. The variable selection functions involving the merit make use of a merit func- tion. By default, the bit-vector merit function returns the number of free bits. This function can be overridden by a user-defined function, which allows for custom variable selection.

variable selection select. . . BIT_VAR_NONE the first unassigned variable BIT_VAR_RND a random variable BIT_VAR_SIZE_MIN the variable with the smallest domain size BIT_VAR_MERIT_MAX the variable with highest merit as defined by merit BIT_VAR_DEGREE_MAX the variable on which most propagators depend BIT_VAR_ACTIVITY_MAX the variable which has been involved in most constraint propagation

Table 5.3: Bit-vector branching variable selection

value selection select. . . BIT_VAL_MIN_BIT the least-significant free bit BIT_VAL_MAX_BIT the most significant free bit BIT_VAL_RND_BIT a random free bit BIT_VAL user-defined value selection

Table 5.4: Bit-vector branching value selection

Value selection functions operate on the selected variable and choose a value in the domain of this variable on which to branch. In the case of bit-vectors, the function chooses a single bit according to the chosen strategy. The defined value selection functions are given in Table 5.4. The value selection functions require find first set bit and find last set bit functions in order to find a bit to select. Our implementation uses the gcc built-in functions __builtin_ffs (find first set) and __builtin_clz (count leading zeros), which internally use the bsfl (bit scan forward) and bsrl (bit scan reverse) instructions [8]. These run in constant time, which allows our selection functions to run in constant time. Finally, branch commit function branches on the chosen variable and value. For bit-vectors, the default branch commit function first fixes the selected bit to 1, then fixes the selected bit to 0.

39 5.6 Source code

The source code used in this thesis is available online on github at https://github.com/kellen/bitvector-masters.

40 Chapter 6

Bit-vector S-Box models

We present several model variants for enforcing the DES design criteria for S-boxes using bit-vector variables. In Chapter 7, two alternative models are presented; one using set variables and another using Boolean variables.

6.1 Variable choice

All bit-vector-based models represent the problem as an array of 2n bit-vector variables which each have m "active" bits. Criterion S-1 is fulfilled by this choice of variables.

6.2 Channeling

All bit-vector models channel their variables to an integer variable represen- tation in order to take advantage of the built-in Gecode implementation of alldifferent and in some cases count. The channeled representation is an array of 2n integer variables. The channeling constraint for bit-vectors is as presented in Algorithm 3.5. For some bit-vector models, the integer representations are used in S-2, the non- linearity constraint. All bit-vector models use integer representations in S-3.

6.3 Criterion S-2

Each model enforces the non-linearity constraint, which fulfills criterion S-2, with one of two variants of the HC heuristic presented in Section 3.2.1: a global constraint presented in Section 6.3.2 or a series of more basic constraints pre- sented in Section 6.3.1.

6.3.1 Decomposed bit-vector S-2

The HC heuristic can be expressed as a set of constraints as presented in Algo- rithm 6.1.

41 For each combination of α and β and every S-box input x, an entry in the array Nab of Boolean variables is constrained to be true when the linear combination of x and α equals the linear combination of S(x) and β. An integer variable in the array N is constrained to be the sum of Nab for the given α and output bit i. The max and min of N are constrained to be within the acceptable range given the threshold τ.

Algorithm 6.1 Model for the S-2 non-linearity constraint for 1 ≤ α < 2n do for 0 ≤ i < m do β ← 2i for 0 ≤ x < 2n do Nab[α][i][x] = (parity(x ∧ α) ⇔ parity(S(x) ∧ β)) N[α − 1][i] = sum(Nab[α][i]) n 2 /2 + τ ≥ max(N) n 2 /2 − τ ≤ min(N)

6.3.2 Global integer & bit-vector S-2

A propagator for the S-2 non-linearity constraint is given in Algorithm 6.2. We implement two variants of nonlinear; one which operates on integer variables and one which operates directly on bit-vector variables; these implementations are identical except for their C++ variable types. For all assigned variables, and for all potential combinations of α and β, the propagator increments N(α, β) when the linear combination of the current in- put, x, and α is equal to the linear combination of the current variable, S(x), and β. The propagator keeps a count of the number of assigned variables, assigned_count, and calculates the max and min of N(α, β). If the maximum or minimum values are not within the acceptable range, given the threshold τ and assigned_count, then the propagator reports failure. The advantage of using a propagator in this case is a much reduced number of variables to which changes must be propagated. The implementation of this propagator additionally keeps track of which variables have been assigned and incrementally updates N(α, β) in order to improve execution time, rather than completely recalculating N(α, β) on each run.

42 Algorithm 6.2 Global propagator for nonlinear(S, τ) function propagate(nonlinear(S, τ)) for 1 ≤ α < 2n do for 0 ≤ i < m do β ← 2i N(α, β) ← 0 assigned_count ← 0 for 0 ≤ x < 2n do if assigned(S(x)) then assigned_count ← assigned_count + 1 for 1 ≤ α < 2n do for 0 ≤ i < m do β ← 2i if parity(x ∧ α) = parity(S(x) ∧ β) then N(α, β) ← N(α, β) + 1 max ← max {N(α, β)} α,β min ← min {N(α, β)} α,β n n n if ¬(2 /2 + τ ≥ max ∧ min ≥ 2 /2 − τ − (2 − assigned_count)) then return false return true end function

6.4 Criterion S-3

Criterion S-3 requires that each possible value from 0 to (2m − 1) occur at least once; this is enforced by an alldifferent constraint on the channelled integer vari- ables as described in Section 3.2.2.

6.5 Criteria S-4, S-5, and S-6

Criteria S-4, S-5, and S-6 are implemented as described in Sections 3.2.3, 3.2.4, and 3.2.5. These use the bit-vector propagators for weight, xor, and disequal as described in Sections 3.1 and 4.1.

6.6 Criterion S-7

Criterion S-7, described in Section 4.3, is expressed either as a global con- straint or as a decomposed series of basic constraints. The criterion specifies max_count to be 8 for a 6×4 S-box.

6.6.1 Decomposed bit-vector S-7

The S-7 criterion can be expressed as a series of constraints as presented in Algorithm 6.3. For each input difference, i, each pair of inputs j and k are found which result in this difference. Because we are using max_count for unordered

43 pairs, we ensure that j < k to avoid duplicates. The output difference S(j) ⊕ S(k) is channeled to an integer representation. Once all input pairs for this input difference are found, a global cardinality constraint (built-in to Gecode as count) constrains the variable at index idx of the integer variable array counts to be equal to the number of occurrences of the value idx in xorintvals[i]. Finally, these counts are constrained to be less than or equal to max_count.

Algorithm 6.3 Model for the S-7 constraint for 1 ≤ i < 2n do cur ← 0 for 0 ≤ j < 2n do k ← i ⊕ j if j < k then xorintvals[i][cur] = channel(S(j) ⊕ S(k)) cur ← cur + 1 counts = count(xorintvals[i]) counts ≤ max_count

6.6.2 Global bit-vector S-7

We also implement a propagator for criterion S-7, as given in Algorithm 6.4, called xordist in reference to the pairs XOR distribution table mentioned in Sec- tion 4.3. The propagator operates on a slightly different principle than the model presented in the Section 6.6.1. Instead of starting with an input dif- ference i, it iterates over all inputs x, and all inputs y such that x < y, making ordered pairs of inputs hx, yi with the input difference x ⊕ y. The count in the table T for the output difference for these inputs S(x) ⊕ S(y) is then incre- mented. If at any point the count exceeds max_count, the propagator reports failure. Like the global nonlinear constraint presented in Section 6.3.2, the xordist prop- agator reduces the number of variables to which changes must be propagated to achieve the same constraint, and like nonlinear, xordist also incrementally up- dates T in order to improve execution time.

Algorithm 6.4 Global propagator for criterion S-7 function propagate(xordist(S, max_count)) for 0 ≤ x < 2n do if assigned(S(x)) then for x < y < 2n do if assigned(S(y)) then T[x ⊕ y][S(x) ⊕ S(y)] ← T[x ⊕ y][S(x) ⊕ S(y)] + 1 if T[x ⊕ y][S(x) ⊕ S(y)] > max_count then return false return true end function

44 6.7 Models

Four bit-vector model variants are constructed: • A bit-vector model using the decomposed S-2 and S-7 constraints. • A bit-vector model using the integer S-2 propagator and the decomposed S-7 constraint. • A bit-vector model using the bit-vector S-2 propagator and the decom- posed S-7 constraint. • A bit-vector model using both the bit-vector S-2 propagator and the S-7 propagator.

45

Chapter 7

Alternative S-Box models

This chapter details two alternative S-box models using, respectively set vari- ables and Boolean variables to represent the S-box’s constituent bit-vectors.

7.1 Set model

The set-based model represents an n×m S-box as an array of 2n set variables, each of which can contain values from 0 to m; if a value k is present in a set, it indicates that bit k is set to 1, otherwise the bit is set to 0.

7.1.1 Channeling

Set variables are channeled to an integer representation. The channeling is achieved by using the Gecode-provided weights constraint, which gives a weight to each possible set element and constrains an integer variable to be the sum of the weights for the elements present in the set.

7.1.2 Bitwise operations

For the set model, the built-in set operations described in [18] are used to implement "bitwise" operations on sets representing "on" bits. The bitwise XOR (⊕) operation over two variables p and q, p ⊕ q, is equivalent to (p ∨ q) ∧ ¬(p ∧ q). For the representation described here, the set union (∪) is equivalent to ∨, the set intersection (∩) is equivalent to ∧, and the set complement (SC for a set S) is equivalent to ¬. Thus, bitwise ⊕ is implemented for two sets p and q as (p ∪ q) ∩ (p ∩ q)C. Set cardinality is here equivalent to the Hamming weight described in Section 2.2.6.

7.1.3 Criterion S-2

The non-linearity criterion S-2 uses the channeled integer representations and the integer S-2 propagator described in Section 6.3.2.

47 7.1.4 Criterion S-3

This criterion is implemented in exactly the same way as for the bit-vector models, as described in Section 6.4.

7.1.5 Criteria S-4, S-5, and S-6

As with S-3, the set model variants of S-4, S-5, and S-6 correspond with the bit-vector models. The set model uses the set-based interpretation of bitwise operations described in Section 7.1.2.

7.1.6 Criterion S-7

The set-based implementation of criterion S-7 corresponds with the decom- posed bit-vector S-7 implementation presented in Section 6.6.1, but with the set-based interpretation of bitwise operations described in Section 7.1.2.

7.1.7 Comparison

The set-based model builds on existing variable implementations, which have the potential to be more thoroughly optimized than our bit-vector variable im- plementation. However, this set-based model also requires some acrobatics to express bitwise operations (as detailed in Section 7.1.2) which can result in a significant number of auxiliary variables.

7.2 Boolean model

The Boolean-based model represents an n×m S-box as an array of 2n arrays of 2m Boolean variables, where each array of Boolean variables represents a bit-vector and each variable in such an array represents a single bit.

7.2.1 Channeling

Each Boolean array representing a bit-vector is channeled to a single integer variable using the built-in Gecode integer linear constraint. For a Boolean array, the linear constraint interprets each true value as 1 and each false value as 0 and constrains an integer variable to be the linear combination of the array and a set of weights. The weights in this case are 2k for each possible bit k, 0 ≤ k < m. Note that this is not the same as the bit-vector linear operation described in Section 2.2.5.

7.2.2 Bitwise operations

Bitwise operations are more easily represented with arrays of Boolean variables than with set variables; for each index i in a pair of Boolean arrays, p and q, the Boolean operation can be directly applied to the corresponding indices. For example, performing o = p ⊕ q is just ∀i : 0 ≤ i < m : o[i] ⇔ p[i] ⊕ q[i].

48 7.2.3 Criterion S-2

For the Boolean model, the non-linearity criterion S-2 uses the channeled inte- ger representations and the integer S-2 propagator described in Section 6.3.2.

7.2.4 Criterion S-3

For the Boolean model, criterion S-3 is implemented in exactly the same way as for the bit-vector models, as described in Section 6.4.

7.2.5 Criteria S-4, S-5, and S-6

As with S-3, the Boolean model variants of S-4, S-5, and S-6 correspond with the bit-vector models. The Boolean model uses the Boolean bitwise operations described in Section 7.2.2.

7.2.6 Criterion S-7

The Boolean implementation of criterion S-7 corresponds with the decomposed bit-vector S-7 implementation presented in Section 6.6.1, but with the Boolean bitwise operations described in Section 7.2.2 and channeling to integer vari- ables as described in Section 7.2.1.

7.2.7 Comparison

Like the set-based model, the Boolean model builds on existing variable im- plementations, which may be better optimized than our bit-vector variable im- plementation. The Boolean model requires more variables than the set-based model, but uses fewer interim steps to perform the bitwise operations. Inter- nally, Gecode uses integer variables to represent Boolean variables, which will not be as memory-efficient when compared with bit-vector variables.

49

Chapter 8

Evaluation

This chapter describes the set-up and results of benchmarking run on the set, Boolean, and four bit-vector models.

8.1 Setup

In order to ensure that a solution exists, one of the DES-defined S-boxes was chosen as a basis for the search space. For all models, we use all symmetry breaking constraints as defined in Sec- tions 3.3 and 4.4. However, no S-box defined by DES satisfies all of the given symmetry-breaking constraints, so we transform the chosen S-box into one which satisfies these symmetry-breaking constraints by inverting bits, trans- posing rows, rotating the S-box, etc., as appropriate. A set of randomly-chosen values are then removed from the S-box and the time necessary to find the specific S-box solution is measured for 25 runs. Other solutions are ignored. These values are selected randomly for each run but the same values are used for all models. Four variable selection methods were evaluated: NONE (choose first unassigned variable), DEGREE_MAX (choose the variable involved in most constraints), AC- TIVITY_MAX (choose the variable with most activity), and RND (choose a ran- dom variable). For the bit-vector and set models, the variable selection targets an entire bit- vector. In the Boolean model, in contrast, the variable selection targets individ- ual bits. For bit-vector models, value selection was BIT_VAL_RND_BIT, which first fixes a randomly-chosen bit to 1, then to 0. Value selection for the set-based model was SET_VAL_RND_INC, which includes a random element in the set; this is equivalent to setting a random bit to 1. For the Boolean-based model, the value selection was INT_VAL_MAX, which first fixes the chosen bit to 1, then to 0. Each combination of model, variable selection, and n, the number of elements to remove from the chosen S-box, n ∈ {4, 8, 12, . . . , 64}, is tested for 25 runs.

51 The threshold for the non-linearity criterion is set to 14 to match the score of S3, the selected S-box. A timeout of 30 seconds was used. If a model timed out fewer than 3 times, we report the number of timeouts and its average time and nodes for the remain- ing runs. Once a model times out 3 times for a given n, we abort execution for the remaining n. Tests were performed under Debian Linux on a virtual private server with an emulated CPU (AuthenticAMD, QEMU Virtual CPU version 0.12.5, 1909.490 MHz, 512 KB cache) and 500 MB of RAM. The DES S-boxes are 6×4 substitution boxes, meaning they consist of 64 4-bit bit-vectors.

8.2 Results

The average execution time, number of timeouts, and average number of nodes are presented in Table 8.1. The best times for a given n are shown in bold. The RND variable selection performed poorly for all models. Figure 8.1 graphs the results of each model for RND variable selection and shows the relative ad- vantage of the bit-vector model with the bit-vector S-2 and S-7 propagators. The bit-vector model using the decomposed S-2 and S-7 constraints performed the worst, though only slightly worse than the set-based model. Presumably, RND performed poorly because many of the propagators require variables to become assigned before they execute and selecting random variables delays this process. The DEGREE variable selection also performed poorly. The results for each model and DEGREE variable selection are graphed in Figure 8.2, where it can be seen that the only successful case is the Boolean model. This is likely due to the fact that the variable selection for the Boolean model is targeting individ- ual bits rather than entire bit-vectors, unlike the other models. Each bit-vector is involved in the same number of constraints, while individual bits may be involved in more or less. ACTIVITY variable selection improved on the previous two variable selection methods. Figure 8.3 shows the Boolean model performing the worst, followed by the set model, then the bit-vector models, with the model using bit-vector S-2 and S-7 propagators performing the best. The poor performance of the Boolean model in this case is again likely due to the fact that variable selec- tion targets individual Boolean variables representing bits, which are either assigned or not and therefore cannot accumulate much activity. Finally, the best performing variable selection was NONE. The best perform- ing model was the bit-vector model using the bit-vector S-2 and S-7 propa- gators, while the worst performing model was the bit-vector model with the decomposed S-2 and S-7 constraints, as shown in Figure 8.4. This variable selection probably performed well for the same reasons that RND performed poorly, namely that it causes variables to become assigned more quickly and therefore increases propagation. Overall, the bit-vector model with bit-vector propagators for both S-2 and S-7,

52 in combination with the NONE variable selection performed the best for all val- ues of n; no other model/variable-selection combination reached n = 40.

53 Boolean, integer S-2 propagator ACTIVITY DEGREE NONE RND n time t/o nodes time t/o nodes time t/o nodes time t/o nodes 8 0.02 21 0.02 21 0.02 21 0.02 21 12 0.05 56 0.04 43 0.04 43 0.11 155 16 0.12 154 0.10 112 0.10 112 0.83 1228 20 0.64 769 0.19 218 0.20 218 14.79 18972 24 5.01 (1) 5950 0.56 674 0.58 674 28 1.99 2330 1.91 2330 32 4.51 6441 4.75 6441

set, integer S-2 propagator ACTIVITY DEGREE NONE RND n time t/o nodes time t/o nodes time t/o nodes time t/o nodes 8 0.05 29 0.14 87 0.05 28 0.09 55 12 0.11 59 1.06 635 0.10 54 0.60 353 16 0.27 157 10.35 (2) 5467 0.20 110 4.92 2695 20 1.01 581 0.46 245 24 3.45 (2) 1764 2.15 1165 28 6.20 (1) 3687

bit-vector, decomposed S-2, decomposed S-7 ACTIVITY DEGREE NONE RND n time t/o nodes time t/o nodes time t/o nodes time t/o nodes 8 0.03 18 0.10 69 0.04 17 0.06 39 12 0.08 41 1.38 782 0.07 37 0.35 214 16 0.18 88 0.18 80 3.25 1798 20 0.66 315 0.44 204 24 2.15 936 2.81 1115 28 5.95 2853

Table 8.1: (continued on next page) Average execution time in seconds, total number of timeouts, average number of nodes over 25 runs. Boldface values are the best time for the given number of values to find, n.

54 bit-vector, integer S-2, decomposed S-7 ACTIVITY DEGREE NONE RND n time t/o nodes time t/o nodes time t/o nodes time t/o nodes 8 0.02 18 0.04 70 0.02 18 0.03 40 12 0.03 41 0.45 786 0.03 37 0.12 215 16 0.06 88 12.42 21898 0.06 80 0.98 1782 20 0.20 320 0.14 204 10.81 19630 24 0.60 937 0.71 1117 28 4.57 (1) 7834 1.37 2860 32 3.95 8978

bit-vector, bit-vector S-2 propagator, decomposed S-7 ACTIVITY DEGREE NONE RND n time t/o nodes time t/o nodes time t/o nodes time t/o nodes 8 0.02 18 0.04 71 0.03 18 0.03 40 12 0.03 41 0.44 786 0.05 37 0.12 212 16 0.06 88 12.35 21898 0.10 80 0.98 1782 20 0.21 320 0.19 204 10.82 19630 24 0.60 937 1.13 1117 28 4.58 (1) 7834 1.94 2860 32 5.02 (1) 5810

bit-vector, bit-vector S-2 propagator, S-7 propagator ACTIVITY DEGREE NONE RND n time t/o nodes time t/o nodes time t/o nodes time t/o nodes 8 0.01 18 0.01 71 0.01 18 0.01 40 12 0.01 41 0.05 786 0.01 37 0.02 211 16 0.01 88 1.24 21569 0.01 80 0.10 1683 20 0.03 333 0.02 205 1.16 20926 24 0.10 1542 0.08 1119 28 0.63 12180 0.14 2862 32 2.87 (1) 49179 0.44 8989 36 2.01 41245 40 6.66 (1) 130116

Average execution time in seconds, total number of timeouts, average number of nodes over 25 runs. Boldface values are the best time for the given number of values to find, n.

55 16 set, integer S-2 14 boolean, integer S-2 bit-vector, integer S-2 12 bit-vector, decomposed S-2 bit-vector, S-2 10 bit-vector, S-2, S-7

8 time (s) 6

4

2

0

8 12 16 20 # unassigned variables

Figure 8.1: RND

set, integer S-2 12 boolean, integer S-2 bit-vector, integer S-2 10 bit-vector, decomposed S-2 bit-vector, S-2 bit-vector, S-2, S-7 8

6 time (s)

4

2

0

8 12 16 20 24 28 32 # unassigned variables

Figure 8.2: DEGREE

56 5 set, integer S-2 boolean, integer S-2 bit-vector, integer S-2 4 bit-vector, decomposed S-2 bit-vector, S-2 bit-vector, S-2, S-7 3

time (s) 2

1

0

8 12 16 20 24 28 32 # unassigned variables

Figure 8.3: ACTIVITY

7 set, integer S-2 boolean, integer S-2 6 bit-vector, integer S-2 bit-vector, decomposed S-2 5 bit-vector, S-2 bit-vector, S-2, S-7 4

3 time (s)

2

1

0

8 12 16 20 24 28 32 36 40 # unassigned variables

Figure 8.4: NONE

57

Chapter 9

Conclusion

We have presented a bit-vector variable implementation for Gecode and its application to the problem of finding high-quality cryptographic substitution boxes.

We have described constraint programming, bit-vectors, and substitution boxes, and reviewed previous work on bit-vectors in constraint programming and the application of constraint programming to substitution box generation.

We have corrected an error that invalidates the main experimental result of [13], extended the HC heuristic, presented two additional symmetries for substitu- tion boxes, defined several generic bit-vector propagators, and defined propa- gators for the S-2 and S-7 criteria.

The bit-vector variable implementation was used in several models for substi- tution box generation, and tested against models using set and Boolean vari- ables for different variable selection methods. Our testing indicates that the best combination of model and variable selection was a model based on bit- vector variables using propagators for the S-2 and S-7 constraints in conjunc- tion with the NONE variable selection.

We have implemented only the subset of the bit-vector propagators defined by Michel and Van Hentenryck [10] necessary for our experiments, and they define propagators for only a subset of logical operations. Future work could implement the remaining propagators for Gecode and provide definitions for other logical operations. Furthermore, there are additional operations on bit- vectors which may be of interest; for example the find-first or find-last set bit operations.

We implemented the DES-defined S-2 constraint; a trivial to implement exten- sion would be to use Matsui’s S-20 instead [9]. This work is based heavily on the DES design criteria, but there may be additional constraints which would provide better substitution boxes.

As defined, the propagators for requirements S-2 and S-7 only fail a space and provide no propagation; it may be possible to improve these requirements in

59 such a way that the propagators can actually perform propagation, which in turn could lead to better runtimes. Our models use the integer-based alldifferent constraint, and place constraints on the channeled integer representations of bit-vectors to break symmetries. Implementing integer relation operators directly on bit-vectors and providing a bit-vector implementation of alldifferent would allow us to totally eliminate integer channeling, potentially improving runtimes. Alternatively, it may be possible to define an integer view for bit-vectors which could use the integer- based alldifferent without needing a separate integer variable. Finally, although the core of Gecode is heavily optimized, our limited C++ ex- perience likely leaves room for the use of more advanced C++ tricks to further improve the performance of our bit-vector components.

60 Bibliography

[1] S. E. Anderson. Bit Twiddling Hacks. URL: https://graphics.stanford.edu/ ~seander/bithacks.html (visited on 2014-07-10). [2] E. Biham and A. Shamir. “Differential Cryptanalysis of DES-like Cryptosystems.” In: Advances in Cryptology-CRYPT0 90. Ed. by A. Menezes and S. A. Vanstone. Vol. 537. Lecture Notes in Computer Science. Springer Berlin Heidelberg, 1991, pp. 2–21. [3] R. Blahut. Cryptography and Secure Communication. Cambridge University Press, 2014. [4] J. Cavanagh. X86 Assembly Language and C Fundamentals. Taylor & Francis, 2013. [5] D. Coppersmith. “The Data Encryption Standard (DES) and its strength against attacks.” In: IBM Journal of Research and Development 38.3 (May 1994), pp. 243–250. [6] N. Dale and J. Lewis. Computer Science Illuminated. Jones & Bartlett Learning, 2012. [7] Gecode: generic constraint development environment. 2014. URL: http://www.gecode. org/ (visited on 2014-04-02). [8] 64 and IA-32 Architectures Developer Manual. Vol. 2A. Intel, 2014, 3:92–3:97. [9] M. Matsui. “Linear Cryptanalysis Method for DES Cipher.” In: Advances in Cryp- tology EUROCRYPT 93. Ed. by T. Helleseth. Vol. 765. Lecture Notes in Computer Science. Springer Berlin Heidelberg, 1994, pp. 386–397. [10] L. D. Michel and P. Van Hentenryck. “Constraint Satisfaction over Bit-Vectors.” In: Principles and Practice of Constraint Programming – CP 2012. Ed. by M. Milano. Vol. 7514. Lecture Notes in Computer Science. Springer Berlin Heidelberg, 2012, pp. 527–543. [11] L. Nyhoff. Programming in C++ for Engineering and Science. Taylor & Francis, 2012. [12] V. Ramamoorthy, M. C. Silaghi, T. Matsui, K. Hirayama, and M. Yokoo. Symme- tries of Nonlinearity Constraints. In: The 11th International Workshop on Symmetry in Constraint Satisfaction Problems. 2011. URL: http://www.cse.unsw.edu.au/ ~ninan/symcon2011.html. [13] V. Ramamoorthy, M. C. Silaghi, T. Matsui, K. Hirayama, and M. Yokoo. “The De- sign of Cryptographic S-Boxes Using CSPs.” In: Principles and Practice of Constraint Programming – CP 2011. Ed. by J. Lee. Vol. 6876. Lecture Notes in Computer Sci- ence. Springer Berlin Heidelberg, 2011, pp. 54–68. [14] C. Schulte. Course Notes Constraint Programming (ID2204). 2012. URL: http:// www . ict . kth . se / courses / ID2204 / notes / ID2204 - CN . pdf (visited on 2014-05-19).

61 [15] C. Schulte. “Programming variables.” In: Modeling and Programming with Gecode. Ed. by C. Schulte, G. Tack, and M. Z. Lagerkvist. Corresponds to Gecode 4.2.1. 2013. [16] C. Schulte and G. Tack. “Views and Iterators for Generic Constraint Implementa- tions.” In: Recent Advances in Constraints. Ed. by B. Hnich, M. Carlsson, F. Fages, and F. Rossi. Vol. 3978. Lecture Notes in Computer Science. Springer Berlin Hei- delberg, 2006, pp. 118–132. [17] C. Schulte and G. Tack. “Programming propagators.” In: Modeling and Program- ming with Gecode. Ed. by C. Schulte, G. Tack, and M. Z. Lagerkvist. Corresponds to Gecode 4.2.1. 2013. [18] C. Schulte, G. Tack, and M. Z. Lagerkvist. “Modeling.” In: Modeling and Program- ming with Gecode. Ed. by C. Schulte, G. Tack, and M. Z. Lagerkvist. Corresponds to Gecode 4.2.1. 2013. [19] C. E. Shannon. “Communication Theory of Secrecy Systems.” In: Bell System Tech- nical Journal 28.4 (1949), pp. 656–715. [20] M. Silaghi. personal communication. Oct. 18, 2014. [21] P. Silvester and D. Lowther. Computer Engineering: Circuits, Programs, and Data. Oxford University Press, 1989. [22] D. Stinson. Cryptography: Theory and Practice, Third Edition. Discrete Mathematics and Its Applications. Taylor & Francis, 2005.

62