Re: What's wrong with this RC4?
Available news archives: comp.lang.tcl - comp.lang.python - comp.security.firewalls - sci.crypt - comp.lang.php - comp.lang.javascript
Google
 
Web news.hping.org


sci.crypt archive

Re: What's wrong with this RC4?

From: Andrew Pogrebennyk <andrew86@voliacable.com>
Date: Wed Dec 28 2005 - 12:56:42 CET

On Tue, 20 Dec 2005 21:25:47 +0000, Bryan Olson wrote:

> Andrew Pogrebennyk wrote:
>> Feel really good when everything is implemented right :) Or, at least,
>> there are no obvious bugs this time.
>
> Now that you've gotten numerically correct output, you should
> look at some subtler issues.
>
> Your code seems to confuse pass-phrase / key / state. An RC4
> key is sequence of octets no more than 256 octets long. For
> security reasons, each new message requires a new key. An RC4
> encryption state consists of a permutation of the integers
> [0..255] and two integers in that same range. RC4 itself has
> no notion of pass-phrase.
>
> For practical reasons, crypto code should not assume that
> the entire input message is available in memory. The usual
> method is to process one piece, while updating the encryption
> state to be ready to handle the next piece.
>
> Reasonable (untested) declarations might be:
>
> typedef struct
> {
> unsigned char s[256];
> unsigned char i;
> unsigned char j;
> } RC4_State;
>
> void set_key(
> RC4_State* state,
> const unsigned char* session_key,
> size_t session_key_size);
>
> void rc4(
> RC4_State* state,
> const unsigned char* in,
> unsigned char* out,
> size_t inout_size);

Thanks for pointing that. After finishing my semester I returned to
crypto, so the first step was to name variables appropriately. There's my
current code in the end of the message.

I am still not sure if ARCFOUR will be used in a project I'm working on,
but if I return to ARCFOUR, I'll use it as a basis for implementing
CipherSaber and probably will enhance it with multi-roung initiation or by
using "2-byte RC4". Would be very grateful for instructions on those
techniques.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define SIZEOF(buf) (sizeof(buf)/sizeof(buf[0]))

typedef struct
{
        unsigned char session_key[256];
        unsigned char index[2];
}
RC4_State;

void swap (unsigned char *a, unsigned char *b)
{
        unsigned char temp;
        temp = *a;
        *a = *b;
        *b = temp;
}

void set_key (unsigned char *key_text, size_t key_text_size, unsigned char *K, RC4_State *state)
{
        unsigned char i, j;
        short int counter;
        unsigned char *S = &state->session_key[0];
        
        state->index[0] = 0;
        state->index[1] = 0;

        for (counter = 0; counter < 256; counter++)
                S [counter] = counter;

        for (counter = 0; counter < 256; counter++)
                K [counter] = key_text [counter % key_text_size ];

        i = j = 0;
        for (counter = 0; counter < 256; counter++) /* initialize the S-box */
        {
                j = (j + S [counter] + K [i]) % 256;
                swap (&S [counter], &S [j]);
                i = (i + 1) % 256;
        }
}

void rc4(unsigned char *plain, size_t plain_size, unsigned char *cipher, RC4_State *state)
{
        unsigned char i, j;
        short int counter;
        unsigned char *S = &state->session_key[0];
        unsigned char xor_index;
        i = state->index[0];
        j = state->index[1];
        for(counter = 0; counter < plain_size; counter ++)
        {
                i = (i + 1) % 256;
                j = (j + S [i]) % 256;
                swap (&S [i], &S [j]);
                xor_index = (S[i] + S[j]) % 256;
                cipher [counter] = plain [counter] ^ S[xor_index];
        }
}

int main()
{
        unsigned char K [256];
        unsigned char key_text [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        unsigned char plain [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        unsigned char *cipher;
        short int i;
        RC4_State state;

        set_key (key_text, SIZEOF(key_text), K, &state);
        
        memset (K, 0x0, SIZEOF(K));
        memset (key_text, 0x0, SIZEOF(key_text));
        
        printf("\nSize(plain): %d\n", SIZEOF(plain));
        for (i = 0; i < SIZEOF(plain); i++)
                printf ("%x ", plain [i]);
        
        cipher = calloc (SIZEOF(plain), sizeof(plain[0]));

        rc4 (plain, SIZEOF(plain), cipher, &state);

        printf("\n\nSize(cipher): %d\n", SIZEOF(plain));
        for (i = 0; i < SIZEOF(plain); i++)
                printf ("%x ", cipher [i]);

        free (cipher);
        printf("\n\n");
        return 0;
}
Received on Tue Jan 3 03:41:37 2006