How The Mighty Have Fallen: RC4 — Fast, Compact, and Can Be Insecure

When I started in networking, the world was just getting into wireless communications. For the first time on a local area network, we…

How The Mighty Have Fallen: RC4 — Fast, Compact, and Can Be Insecure

When I started in networking, the world was just getting into wireless communications. For the first time on a local area network, we could communicate with a computer without wires. But, it was a technical disaster — aka WEP (Wired Equivalent Privacy).

WEP broke almost every rule in how to design Wifi security. It used a broadcast encryption key for the whole network, which meant that anyone with the key could read every other packet on the network and decrypt it. It also used a 24-bit IV (Initial Vector), which was too small, and it rolled around within a relatively short period. When this happened, it was then easy to crack the encryption. And, finally, it used RC4. While fast and efficient, it has been shown to have security issues [1]:

For this, Fluher et al showed that there were a large number of weak keys, where the outputs could be guessed for given inputs, and which Klein improved on. When the Fluhrer et al method was uncovered, it caused many — including Ron Rivest — problems in their implementations:

It should be noted that the cracking team included one of Ron’s co-researchers: Adi Shamir — one of the great cryptanalysts.

RC4 — Ron’s Cipher 4

RC4 is a stream cipher that was created by Ron Rivest and created in 1987. It is generally a fast cipher, and where we create a key stream based on a password. RC4 was used in WEP (Wired Equivalent Privacy), and where a small IV value caused serious security problems.

The key length can vary from one to 256 bytes and is used to create an initial 256-byte state vector (S). The output is basically X-OR’ed one bit at a time with the keystream, and the plaintext is recovered by X-OR’ing the cipher stream with the keystream. As we are using a stream cipher, there is no need for padding, and where the ciphertext stream size will be the same as the plaintext length.

The basics of key generation are given here:

https://asecuritysite.com/symmetric/rc4_key

Coding

RC4 is still a fairly popular method, especially due to variable key lengths from 40 bits up to 256 bits. In C#/.NET, we first we create a folder named “bc_rc4”, and then go into that folder.We can create a Dotnet console project for .NET 8.0 with:

dotnet new console --framework net8.0

This produces a Csproject file of:

<Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
 </Project>

We then add the latest Bouncy Castle library:

dotnet add package BouncyCastle.Cryptography --version 2.2.1

The following is the coding [here]:

namespace RC4
{
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
class Program
{

static void Main(string[] args)
{



var msg="Hello";


var size=512;
if (args.Length >0) msg=args[0];




try {

var plainTextData=System.Text.Encoding.UTF8.GetBytes(msg);
var cipher = new RC4Engine();

CipherKeyGenerator keyGen = new CipherKeyGenerator();
keyGen.Init(new KeyGenerationParameters(new SecureRandom(), size));
KeyParameter keyParam = keyGen.GenerateKeyParameter();

cipher.Init(true,keyParam);
int outputSize = plainTextData.Length;
byte[] cipherTextData = new byte[outputSize];
cipher.ProcessBytes(plainTextData, 0, plainTextData.Length, cipherTextData, 0);
var rtn = cipherTextData;

// Decrypt
cipher.Init(false,keyParam);
outputSize = cipherTextData.Length;
plainTextData = new byte[outputSize];
cipher.ProcessBytes(cipherTextData, 0, cipherTextData.Length,plainTextData, 0);
var pln=plainTextData;

Console.WriteLine("=== {0} ==",cipher.AlgorithmName);
Console.WriteLine("Message:\t\t{0}",msg);
Console.WriteLine("Key size:\t\t{0} bits",size);
Console.WriteLine("Key:\t\t\t{0} [{1}]",Convert.ToHexString(keyParam.GetKey()),Convert.ToBase64String(keyParam.GetKey()));

Console.WriteLine("\nCipher (hex):\t\t{0}",Convert.ToHexString(rtn));
Console.WriteLine("Cipher (Base64):\t{0}",Convert.ToBase64String(rtn));
Console.WriteLine("\nPlain:\t\t\t{0}",System.Text.Encoding.ASCII.GetString(pln));

} catch (Exception e) {
Console.WriteLine("Error: {0}",e.Message);
}
}
}

}

A sample run is [here]:

=== RC4 ==
Message: Hello 123
IV: 00112233445566778899AABBCCDDEEFF
Key size: 128 bits
Key: BD03B43CCAB7009822551578AC6E5C53 [vQO0PMq3AJgiVRV4rG5cUw==]
Cipher (hex): 7527E4782509FCBDC2
Cipher (Base64): dSfkeCUJ/L3C
Plain: Hello 123

Notice that the cipher length is the same length as the plaintext (in terms of the number of bytes).

Conclusions

And, so, RC4 crashed and burned. One vulnerability and it was gone. Most systems moved to use the AES standard, which was much more robust. While the block cipher mode of AES was much slower, the GCM mode converted it into a stream cipher and made it just as fast as RC4. So, thank you, Ron, you have led the way in so many areas, but RC4 was not something that will sustain into the future in the way that RSA has.

And, if you are interesting in cryptography and .NET, try here:

https://asecuritysite.com/csharp

References

[1] Klein, A. (2008). Attacks on the RC4 stream cipher. Designs, codes and cryptography, 48, 269–286.

[2] Fluhrer, S., Mantin, I., & Shamir, A. (2001). Weaknesses in the key scheduling algorithm of RC4. In Selected Areas in Cryptography: 8th Annual International Workshop, SAC 2001 Toronto, Ontario, Canada, August 16–17, 2001 Revised Papers 8 (pp. 1–24). Springer Berlin Heidelberg.