CS 4005-705-01 Cryptography I Prof
Total Page:16
File Type:pdf, Size:1020Kb
CS 4005-705-01 Cryptography I Prof. Alan Kaminsky Graduate Project: Team: “The Number Crunchers” Members: Sharif Hdairis Andrew Hoffman Nelson Powell Introduction Cryptography has progressed significantly from the days of substitution and affine ciphers, to the modern block and stream ciphers based on high order mathematics. This course provides an introduction to the fundamentals of cryptography as it applies to the field of security via the examination of both cryptography and cryptanalysis. This project focuses an empirical investigation on the statistical attributes of stream ciphers, specifically using the published Rabbit Stream Cipher with respect to the randomness of the key stream. The Rabbit Cipher algorithm is a stream cipher utilizing a 128-bit secret key with a 64- bit Initialization Vector (IV) [1][2]. The Rabbit Cipher efficiently encrypts 128-bits per iteration of the algorithm in a synchronous manner to provide an effective ciphered bit stream. The cipher was implemented using the Java language with the intent to utilize the Parallel Java Library [3] as provided by Dr. Alan Kaminsky. Using Object Oriented Design (OOD), the components of the cipher were abstracted in an effort to maximize the utility of fundamental components as well as provide for a possible context based encryption environment. The fundamental components were validated against test sets[2][4] to ensure functional compliance. This statistical analysis test suite TestU01 was used to determine the probability of randomness in cipher’s key stream. Since the Rabbit cipher uses four iterations to mix the key followed by four iterations to mix the IV, the analysis examines the effects on randomness within the keystream with respect to the number of initialization rounds. The “Crush” battery of tests outlined in TestU01 provided the verification of randomness as stated by the original author. 1 Table of Contents Introduction Rabbit Algorithm Mathematical Syntax Component Breakdown Algorithm Breakdown Functional Component Descriptions Key Expansion Key Expansion Counter ReInitialization IV Expansion Next State Function Carry Bit Resolution Counter Iteration State Iteration Encryption KeyStream Generation Key Stream and Data Combining TestU01 Test Suite Random Data Generator Test Results Results Analysis Comparison to Other Analysis’ Conclusion Project Documentation Configuration Management Wiki Environment Project Environment Build Processes User’s Manual Project Discovery Future Research Statement of Work References 2 Rabbit Algorithm The Rabbit Cipher, as described by the authors in [1][2][5], is a streaming cipher utilizing chaos theory as a method of injecting nonlinearity into the algorithm. The authors include a cryptanalysis within their follow on documentation provide evidence of the resilience of Rabbit against algebraic, distinguishing, and brute-force attacks, as well as statistical analysis [1][6][7] [8]. Additional authors have focused on Distinguishing or Bias Attacks as a method to approach the brute force limit of [9][10]. While other authors have attempted other attacks, such as Fault Analysis [11]. Mathematical Syntax To provide a description of the Rabbit Cipher algorithm, a standard mathematical notation must be established in order to familiarize the reader with the mathematical expressions within. The addition sign “+” will be used for bitwise addition, and assumes that the register used to perform the addition has enough bits to satisfy the operation without rollover issues. If the addition is performed with a modulus, the addition will be expressed as a function such as . Logical bit rotations and shifts follow the ANSI C Standard expresses where ‘<<<’ and ‘>>>’ represent logical rotations left and right, respectively, and ‘<<’ and ‘>>’ represent logical shifts left and right respectively. For logical concatenation, the symbol is used for the logical concatenation of two bit fields. The symbol will be used for the logical bitwise exclusive OR function between to bit fields. The rabbit cipher uses registers of the same size and function throughout the standard. Furthermore, each register has state with respect to time. To describe a set of registers over a period of time, the following notation is used: where j describes the register index number and i provides the iteration with respect to time. When referencing a bit field within a variable, the form X[m...n] describes the bits “m” through “n” of the register “X”, where m > n and ‘m’ is consider the MSB and ‘n’ is the LSB. If the bit field describes a register in an array of registers over the course of numerous iterations, the variable is described as a combination of the bit field and the standard register representation, such as . Finally, to describe numbers in varying numerical systems, decimal numbers will be written with standard Arabic values, binary numbers will be succeeded by a ‘b’, such as 100110b for example, and hexadecimal numbers will be preceded by a ‘0x’ value such as 0x1F823C. Component Breakdown The Rabbit Cipher has a total of 513-bits of state information at any given iteration throughout the cipher and decipher processes. The 513-bits of data is broken into eight 32-bit state registers, eight 32-bit counter registers, and a single carry bit. Depending on implementation, one may choose to store more data to avoid extra processing, or maintain all other data items as volatile memory items for code compactness. The eight 32-bit state registers are called the x-registers, or where and i represents the iteration counter. Similar to the x-register, the counter registers, or where 3 , are 32-bit registers coupled with the state registers throughout the process of the algorithm. There is only one carry bit, but this does not detract from the possibility of one creating a data structure in which the carry is also associated with the state and counter registers. It is important to realize that any given instance of the cipher, especially in object oriented designs, must maintain its own instance of the 513-bits of data. Also, any given instance always begins with the ‘i’ value at 0 (i = 0). Later, the single carry bit usage and derivation will be explained. To avoid future confusion, it is important to note that the carry bit is set to 0 at i = - 1, and that the carry bit is the only data item that has a notion of i = -1 at the start of a session. Keeping this in mind during the description of the carry bit will resolve many misconceptions about the use of the carry bit throughout the implementation of the cipher. Though Boesgaard [7], et al., suggests that only 513-bits of non-volatile memory is required for an implementation of the Rabbit Cipher, it is the suggestion of this team to also store an additional 128-bits of keystream in a pseudo-block cipher method for fast access to the keystream. Failure to store the key stream between encryption of bits, bytes, or blocks would require additional memory to store the previously used location in the keystream as well as special processing to recover the new keystream information. Though location information requires less memory, the coding effort outweighs the extra memory required to store the current keystream information. Algorithm Breakdown The Rabbit Cipher can be broken into four fundamental phases of operation as seen in Figure 1: Key and IV Selection/Insertion, Key Initialization, IV Initialization, and Encryption. The Key and IV selection is any method in which an implementation chooses to obtain a secret key and a public IV for the current context to be encrypted or decrypted. This process is outside of the scope of the algorithm itself, and is therefore left to the reader to determine the best business practices for Key management. Figure 1 - Rabbit Cipher Process Overview The second phase of the Rabbit cipher is the Key Setup phase. In this phase, the Key is applied to both the internal State Registers (X) and Counter Registers (C). As seen in Figure 2, the Key bits are first distributed across both the state and counters for an initial value for both and . The NextState() function, also known as the Iterate() function, is called four times to scramble the initial values of X and increment the counters. These four iterations account for the register values and through and . 4 Finally, the eight counters are re-initialized by eXclusive OR’ing the state registers with the counters. It is important to note that the is merely replaced with the result of this XOR process, and the ‘i’ value is not incremented during counter re-initialization. [5] claims that the process of re-initializing the counters avoids an attacker reversing the counter iteration process, thereby recovering the initial Key value. Figure 2 - Secret KEY Setup Process The third process, as seen in Figure 3, is known as the IV Setup process. The IV Setup process is a method of further obfuscating the Secret key by modifying the eight counter registers by distributively XOR’ing every bit in the IV with every bit in the counters. This ensures that there are possible unique key streams for any given Secret Key. One should be aware that the combining of the IV with the counters, much like the Counter Re- Initialization of the Key Setup process, does not constitute an iteration in the system. The IV is combined with the counter registers at iteration 4, where = . After combining the IV with the counters, the IV Setup process ensures the mixing of the IV bit by again processing four iterations of the NextState() function. The iterations will cause a mixing of the IV bits between the counters and the state registers. These four iterations account for the register values and through and . 5 Figure 3 - IV Setup Process The final process in the cipher is the Encryption Cycle. There are two distinct sub-phases within the encryption process, the NextState() or iteration function, and the KeyStream generation.