Progress pill
RC4 and AES

The RC4 stream cipher

  • Step 1
  • Step 2
  • Step 3
  • Step 4
In this Chapter, we will discuss the details of an encryption scheme with a modern primitive stream cipher, RC4 (or "Rivest cipher 4"), and a modern block cipher, AES. While the RC4 cipher has fallen into disfavor as a method of encryption, AES is the standard for modern symmetric encryption. These two examples should give a better idea of how symmetric encryption works under the hood.

In order to have a sense of how modern pseudorandom stream ciphers work, I will focus on the RC4 stream cipher. It is a pseudorandom stream cipher that was used in the WEP and WAP wireless access point security protocols as well as in TLS. As RC4 has many proven weaknesses, it has fallen into disfavor. In fact, the Internet Engineering Task Force now forbids the use of RC4 suites by client and server applications in all instances of TLS. Nevertheless, it works well as an example to illustrate how a primitive stream cipher works.
To start, I will first show how to encrypt a plaintext message with a baby RC4 cipher. Suppose our plaintext message is “SOUP.” Encryption with our baby RC4 cipher, then, proceeds in four steps.

Step 1

First, define an array S with to . An array here simply means a mutable collection of values organized by an index, also called a list in some programming languages (e.g., Python). In this case, the index runs from 0 through 7, and the values also run from 0 to 7. So S is as follows:
The values here are not ASCII numbers, but the decimal value representations of 1-byte strings. So the value 2 would equal . The length of the array S is, thus, 8 bytes.

Step 2

Second, define a key array K of 8 bytes length by choosing a key between 1 and 8 bytes (with no fractions of bytes permissible). As each byte is 8 bits, you can select any number between 0 and 255 for each byte of your key.
Suppose we choose our key k as , so that it has a length of 3 bytes. Each index of our key array is, then, set according to the decimal value for that particular element of the key, in order. If you run through the entire key, start again at the beginning, until you have filled the 8 slots of the key array. Hence, our key array is as follows:

Step 3

Third, we will transform the array S using the key array K, in a process known as key scheduling. The process is as follows in pseudocode:
  • Create variables j and i
  • Set the variable
  • For each from 0 to 7:
    • Set
    • Swap and
The transformation of array S is captured by Table 1.
To start, you can see the initial state of S as with an initial value of 0 for j. This will be transformed using the key array .
The for loop starts with . According to our pseudocode above, the new value of j becomes 6 (). Swapping and , the state of S after 1 round becomes .
In the next row, . Going through the for loop again, j obtains a value of 7 (). Swapping and from the current state of S, , yields after round 2.
We continue with this process until we produce the final row at the bottom for the array S, .
Table 1: Key scheduling table
RoundijS[0]S[1]S[2]S[3]S[4]S[5]S[6]S[7]
Initial001234567
10661234507
21767234501
32267234501
43367234501
54367203541
65664203751
76164203752
87264103752

Step 4

As a fourth step, we produce the keystream. This is the pseudorandom string of a length equal to the message we want to send. This will be used to encrypt the original message “SOUP.” As the keystream needs to be as long as the message, we need one that has 4 bytes.
The keystream is produced by the following pseudocode:
  • Create the variables j, i, and t.
  • Set .
  • For each of the plaintext, starting with and going until , each byte of the keystream is produced as follows:
    • Swap and .
    • The byte of the keystream =
You can follow the calculations in Table 2.
The initial state of S is . Setting , the value of j becomes 4 (). We then swap and to produce the transformation of S in the second row, . The value of t is then 7 (). Finally, the byte for the keystream is , or 2.
We then continue to produce the other bytes until we have the following four bytes: 2, 6, 3, and 7. Each of these bytes can then be used to encrypt each letter of the plaintext, "SOUP".
To start, using an ASCII table, we can see that “SOUP” encoded by the decimal values of the underlying byte strings is “83 79 85 80”. Combination with the keystream “2 6 3 7” yields “85 85 88 87”, which stays the same after a modulo 256 operation. In ASCII, the ciphertext “85 85 88 87” equals “UUXW”.
What happens if the word to encrypt were longer than the array S? In that case, the array S just keeps transforming in this manner displayed above for every byte i of the plaintext, until we have a number of bytes in the keystream equal to the number of letters in the plaintext.
Table 2: Keystream generation
ijtKeystreamS[0]S[1]S[2]S[3]S[4]S[5]S[6]S[7]
064103752
147263104752
250663704152
351363714052
417264713052
The example that we just discussed is only a watered-down version of the RC4 stream cipher. The actual RC4 stream cipher has an S array of 256 bytes in length, not 8 bytes, and a key that can be between 1 and 256 bytes, not between 1 and 8 bytes. The key array and the keystreams are then all produced considering the 256-byte length of the S array. The calculations become immensely more complex, but the principles stay the same. Using the same key, [14,48,9], with the standard RC4 cipher, the plaintext message "SOUP" is encrypted as 67 02 ed df in hexadecimal format.
A stream cipher in which the keystream updates independently of the plaintext message or the ciphertext is a synchronous stream cipher. The keystream is only dependent on the key. Clearly, RC4 is an example of a synchronous stream cipher, as the keystream has no relationship with the plaintext or the ciphertext. All our primitive stream ciphers mentioned in the previous chapter, including the shift cipher, the Vigenère cipher, and the one-time pad, were also of the synchronous variety.
By contrast, an asynchronous stream cipher has a keystream that is produced by both the key and previous elements of the ciphertext. This type of cipher is also called a self-synchronizing cipher.
Importantly, the keystream produced with RC4 should be treated as a one-time pad, and you cannot produce the keystream in exactly the same way the next time. Rather than changing the key each time, the practical solution is to combine the key with a nonce to produce the bytestream.
Quiz
Quiz1/5
What is asynchronous stream encryption?