n0blinder

Simplified RC4 Encryption

RC4 Encryption in Simple Terms

RC4 is a stream cipher, which means it generates a long sequence of random-looking numbers (called a keystream) and uses that sequence to hide or reveal data. In other words, its steps can be composed into two big steps. First, use algorithms to generate a keystream (end result key). Second, use the keystream to encrypt or decrypt data. In RC4 we apply XOR via keystream on a plain text data to encrypt it. So, just like XOR, it’s symmetric meaning the same process is used to encrypt and decrypt.

The pieces involved in RC4 are:

In simple terms, RC4 works by shuffling numbers in a box (S Array), using your secret key to guide the shuffle (K Array + KSA). Then, it pulls out numbers one by one to form the keystream (PRGA). Finally, the keystream is combined with your message using XOR to encrypt or decrypt.

This way, the same key that encrypted the message can also decrypt it, making RC4 a fast and symmetric encryption method.

Algorithms

We use 2 algorithms in RC4 Encryption:

Key Scheduling

This algorithm eventually fills the S array with random looking bytes that were produced using the K array that is filled with our ASCII Encoded Key. This random looking S array is then used by the PRGA (Pseudo-Random Generation Algorithm) to produce a Keystream. This KeyStream is in essence then our secret key to encrypt data.

Logic (pseudocode):

j = 0
for i = 0 to 255 do
    j = j + S[i] + K[i] mod 256
    swap S[i] and S[j]
end for

In C:

j = 0;
for (i = 0; i < 256; i++) {
    j = (j + S[i] + K[i]) % 256;
    unsigned char temp = S[i];
    S[i] = S[j];
    S[j] = temp;
}

You have two things:

Now the loop:

  1. Start with j = 0.
  2. Go through each i from 0 to 255:
    • Add S[i] and K[i] to j, then keep only the remainder after dividing by 256 (mod 256).
      → this means j is always between 0–255.
    • Swap S[i] with S[j].
      → this mixes S around depending on your key.temp = just a helper variable to store one value while you swap.
At the end, S has been scrambled in a key-dependent way.

Pseudo - Random Generation Algorithm (Stream Generation)

The purpose of this algorithm is to take the filled S array and create a KeyStream from it. The keystream will be used to encrypt our data.

Logic (pseudocode):

set i and j back to 0
for i = i+1
    j = j + S[i] mod 256
    swap S[i] and S[j]
    t = S[i] + S[j] mod 256
    KeyStream = S[t]
end for

In C:

i = 0;
j = 0;

for (i = 1; i < 256; i++) {
    j = (j + S[i]) % 256;

    unsigned char temp = S[i];
    S[i] = S[j];
    S[j] = temp;

    t = (S[i] + S[j]) % 256;
    keyStream = S[t];
}

Encryption & Decryption in RC4

We then use xor encryption using our keystream to encrypt and decrypt data

Logic (pseudocode):

CT = PT xor KeyStream
PT = CT xor KeyStream

Simplified RC4 Length 8

Define our Arrays and Key

Key Scheduling Begins

In C:

j = 0;
for (i = 0; i < 8; i++) {
    j = (j + S[i] + K[i]) % 8;
    unsigned char temp = S[i];
    S[i] = S[j];
    S[j] = temp;
}

Now let's walk through the code:

In C:

was --> 0 1 2 3 4 5 6 7

swap 0 and 3 

now --> 3 1 2 0 4 5 6 7

Repeat the Steps until you arrive at the final S array (in green) `3 5 0 1 7 6 4 2`

RC4 swap step illustration

Simplified Stream Generation (Pseudo-Random)

Define What we Want to Encrypt

Proceed with Pseudo - Random Generation Algorithm (Stream Generation)

Crucial here is that we will perform this until we reach the length of the plain text (to length of PT):

set i and j back to 0
for i = i+1 to length of PT
    j = j + S[i] mod 8
    swap S[i] and S[j]
    t = S[i] + S [j] mod 8
    KeyStream = S[t]
end for

Let’s walk through the first iteration:

j    =    j     +    S[i]     mod     8

j    =    0     +     5       mod     8    =    5
t    =    S[i]  +    S[j]     mod     8

t    =     6    +     5       mod     8    =    11   mod  8  = 3 

(see t in row 2 in red)

→ pay attention that in this case S[i] is 6 and not 5 because we swapped in the previous step.

KeyStream = S[t]

KeyStream = S[3]

KeyStream = 1
RC4 stream generation step illustration

Our KeyStream is --[ 1 0 0 2 ]--

Simplified Encryption

  1. First Change the Plain Text and the KeyStream to binary
PT: 0110 0001 0101 0100
KS: 0001 0000 0000 0010
  1. Now apply xor on to encrypt the PT
PT: 0110 0001 0101 0100
KS: 0001 0000 0000 0010
CT: 0111 0001 0101 0110
  1. Finally convert the binary CT to a numerical CT
CT Binary:      0111 0001 0101 0110
CT Numerical:    7     1    5    6 
  1. We encrypted 6154 to 7156

A Complete Simple RC4 Encryption Program in C

#include <stdio.h>
int main() {
    unsigned char K[] = { 3, 1, 4, 1, 5, 3, 1, 4 };
    unsigned char S[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
    int j = 0;
    int i = 0;
    unsigned char plain_text[] = "6154";
    
    
    printf("1. Plain Text to Encrypt: %s\n\n", plain_text);
    printf("2. The key is: 31415\n\n");
    printf("3. The S array is: ");
    for (int i = 0; i < 8; i++) {
        printf("%d ", S[i]);
    }
    
    printf("\n");
    printf("\n");
    printf("4. The K array is: ");
    for (int i = 0; i < 8; i++) {
        printf("%d ", K[i]);
    }
    printf("\n");
    printf("\n");

    for (i = 0; i < 8; i++) {
        j = (j + S[i] + K[i]) % 8;
        unsigned char temp = S[i];
        S[i] = S[j];
        S[j] = temp;
    }
    printf("5. New S array is: ");
    for (i = 0; i < 8; i++) {
        printf("%d ", S[i]);
    }
    printf("\n");
    printf("\n");

    j = 0;
    i = 0;

    unsigned char KeyStream[4];
    int t;

    for (i = 1; i < 5; i++) {
        j = (j + S[i]) % 8;

        unsigned char temp = S[i];
        S[i] = S[j];
        S[j] = temp;

        t = (S[i] + S[j]) % 8;
        KeyStream[i - 1] = S[t];
    }
    printf("6. New KeyStream array is: ");
    for (i = 0; i < 4; i++) {
        printf("%d ", KeyStream[i]);
    }
    printf("\n");
    printf("\n");

    unsigned char shifr[4];
    for (i = 0; i < 4; i++) {
        shifr[i] = plain_text[i] ^ KeyStream[i];
    }

    printf("7. Encrypted Result (hex): ");
    for (i = 0; i < 4; i++) {
        printf("\\x%02x", shifr[i]);
    }
    printf("\n");
    printf("\n");

    printf("8. Encrypted Result (text): ");
    for (i = 0; i < 4; i++) {
        printf("%c", shifr[i]);
    }
    printf("\n");
    printf("\n");

    printf("9. Decrypted Result (text): ");
    for (i = 0; i < sizeof(shifr); i++) {
        printf("%c", shifr[i] ^ KeyStream[i]);
    }
    printf("\n");
    return 0;
}