You are on page 1of 6

ARC4: A lightweight encryption algorithm

Background
There are several applications that need to securely communicate that run on platforms that do not have the processing capability required for conventional encryption algorithms. This note describes how to use ARC4, a public, lightweight, shared secret key encryption algorithm that provides sufficient security and can be supported on low end platforms. It assumes that the encryption key is available to both parties. A simple PKI based key distribution mechanism is described separately.

The ARC4 cipher


RC4 is a fast shared key stream cipher. It generates a sequence of bytes which can be simply XORed with sensitive plaintext to encrypt it. The same mechanism is used to decrypt the encrypted text. It was designed by Ron Rivest, who is one of the developers of the RSA algorithm. It is used in WEP, WPA, and is an option for TLS and SSH. Except for its name, RC4 is in the public domain. It is henceforth referred to as ARC4. ARC4 has been analyzed extensively and its weaknesses have been documented. There are a few other fast encryption algorithms, but none of them have been analyzed as well. It is better to use an algorithm with known issues than one with possible unknown issues. A property of ARC4 is that, given the same key, it will generate the same stream. This property can be exploited by attackers to deduce & record the key stream using a known plaintext attack. This key stream can then be used to decrypt subsequent messages. One way to avoid this vulnerability is to add a random salt (nonce) to the key. This nonce should be selected by the encrypting party and sent in the clear to the decrypting party. The Usage Guidelines section describes how to work around the known issues in ARC4 and the following source code implements the relevant guidelines.

Usage Guidelines
1. A random salt (nonce) must be used for each session. It should be of the same length as the key. It should contain genuinely random bits and should be sent unencrypted from the encrypting party to the decrypting party. Both ends should XOR this salt with the key before ARC4 initialization. [ref] 2. The first 768 (or up to 3072) bytes generated by ARC4 should be discarded by both ends after initialization. This avoids some key correlation attacks. [ref] 3. The state of the ARC4 engine must be saved and reused throughout the session, i.e., ARC4 must not be reinitialized for each transaction or packet. Besides being more efficient, this avoids a known weakness. 4. Encryption may be limited to only sensitive fields, and not the whole transaction. 5. Each application must have its own unique key. The key must not be shared by more than two parties. 6. Keys, passwords & PINs should be at least 8 characters.

ARC4 Encryption

Rajaram Pejaver

1/6

Source Code (in C): Not thread-safe, not guidelines compliant


// file: arc4.c static unsigned char S[256]; static unsigned int i, j; unsigned char arc4_gen(); // static private state table S // static private counters

// arc4_init: key-scheduling algorithm void arc4_init(unsigned char *key, int key_length) { unsigned char si; // holds S[i] int k = 0; // index into key & salt for (i = 0; i < 256; i++) S[i] = i; for (i = j = 0; i < 256; i++, k++) { if (k >= key_length) // k = k % key_length k = 0; si = S[i]; j = (si + j + (key[k])) & 255; S[i] = S[j]; // swap S[i] & S[j] S[j] = si; } i = j = 0; } // arc4gen: pseudo-random stream cipher generation unsigned char arc4gen() { unsigned char si, sj; i = (i + 1) & 255; si = S[i]; j = (j + si) & 255; sj = S[j]; S[i] = sj; S[j] = si; return S[(si + sj) & 255]; } // arc4crypt: encrypt or decrypt using stream cipher void arc4crypt(unsigned char *pdata, int len) { while (len-- > 0) *pdata++ ^= arc4gen(); // XOR in place } // reset static counters

// swap S[i] & S[j]

ARC4 Encryption

Rajaram Pejaver

2/6

ARC4 man page


NAME
arc4init, arc4gen, arc4crypt ARC4 encryption

SYNOPSIS
void arc4init(unsigned char *key, int key_length); unsigned char arc4gen(); void arc4crypt(unsigned char *ptr, int len);

DESCRIPTION
These functions provide basic encryption and decryption using ARC4. This version of the functions is not reentrant or thread safe since the encryption state is stored as a static table. It does not follow the guidelines and does not protect against known attacks. The arc4init() function initializes the encryption state and must be called once before encrypting or decrypting data.
arc4init(key, key_length);

The arc4gen() function returns one byte which is the next value in the pseudo random stream. It updates the encryption state table. It is used for both encrypting and decrypting a byte of data by XORing the value as follows.
enc_byte = clear_byte ^ arc4gen();

The arc4crypt() function is used to encrypt or decrypt an array of bytes.


arc4_crypt(sensitive_field1, sizeof(sensitive_field1));

These functions may not be suitable in some applications where two peers are exchanging encrypted traffic if the encryption states of the traffic in the two directions are different. However, they can be used in simple communicating applications where data is encrypted and decrypted in a lock-step manner.

DIAGNOSTIC MESSAGES
None

SEE ALSO
arc4init_r, arc4gen_r, arc4crypt_r, arc4free_r

ARC4 Encryption

Rajaram Pejaver

3/6

Thread-safe Source Code (in C)


// file: arc4_r.c Thread safe struct arc4 { unsigned char S[256]; // state table S unsigned int i, j; // counters }; unsigned char arc4gen_r(struct arc4 *ap); // arc4init_r: key-scheduling algorithm; return context void *arc4init_r(unsigned char *key, int key_length, unsigned char *salt, int skip) { struct arc4 *ap; char *pi; unsigned char si; // holds S[i] unsigned char ks; // key byte int k = 0; // index into key & salt int i, j; ap = (struct arc4 *) malloc(sizeof *ap); if (ap == 0) return 0; // boom, like that for (i = 0, pi = ap->S; i < 256; i++, pi++) *pi = i; for (i = j = 0, pi = ap->S; i < 256; i++, k++, pi++) { if (k >= key_length) // k = k % key_length k = 0; ks = key[k]; if (salt) ks ^= salt[k]; si = *pi; j = (si + j + ks)) & 255; *pi = ap->S[j]; // swap S[i] & S[j] ap->S[j] = si; } ap->i = ap->j = 0; // reset counters if (skip) // discard first few bytes for (i = 0; i < 768; ++i) (void) arc4_gen(ap); return (ap); }

ARC4 Encryption

Rajaram Pejaver

4/6

// arc4gen_r: pseudo-random stream cipher generation unsigned char arc4gen_r(struct arc4 *ap) { unsigned char si, sj; ap->i = (ap->i + 1) & 255; si = ap->S[ap->i]; ap->j = (ap->j + si) & 255; sj = ap->S[ap->j]; ap->S[ap->i] = sj; // swap S[i] & S[j] ap->S[ap->j] = si; return ap->S[(si + sj) & 255]; }

ARC4_r man page


NAME
arc4init_r, arc4gen_r, arc4crypt_r, arc4free_r ARC4 encryption

SYNOPSIS
void *arc4init_r(unsigned char *key, int key_length, unsigned char *salt, int skip); unsigned char arc4gen_r(void *ap); void arc4crypt_r(void *ap, unsigned char *ptr, int len); void arc4free_r(void *ap);

DESCRIPTION
These functions provide encryption and decryption using ARC4. This version of the functions is reentrant and thread safe since the encryption state is stored in blob of memory that is returned by arc4init_r(). The memory must be released eventually via arc4free_r(). This version also follows the guidelines and supports skipping of the first few bytes of the stream cipher, to protect against key correlation attacks. The arc4init_r() function initializes the encryption state and must be called once before encrypting or decrypting data. If used, salt is an array of random values and must be of the same length as the key. If salt is not desired, then specify a null pointer or an array of zeros. The salt must be sent to the other party so that it can be passed to arc4init_r() at that end. If skip is non-zero, then the first 768 bytes of the stream are discarded.
void *ap; unsigned char salt[128]; int salt_length = strlen(passwd); for (int i = 0; i < salt_length; ++i) salt[i] = random(); ap = arc4init(key, key_length, salt, 1);

ARC4 Encryption

Rajaram Pejaver

5/6

The arc4gen_r() function returns one byte which is the next value in the pseudo random stream. It updates the encryption state table referenced by its parameter ap. It is used for both encrypting and decrypting a byte of data by XORing the value as follows.
enc_byte = clear_byte ^ arc4gen_r(ap);

The arc4crypt_r() function is used to encrypt or decrypt an array of bytes.


arc4_crypt_r(ap, sensitive_fld1, sizeof(sensitive_fld1));

DIAGNOSTIC MESSAGES
arc4init_r() returns null if it cannot allocate memory for encryption state.

SEE ALSO
arc4init, arc4gen, arc4crypt

References
http://en.wikipedia.org/wiki/RC4

ARC4 Encryption

Rajaram Pejaver

6/6

You might also like