perl version of rc4

It's been long enough since perl5 that we'll consider perl5 the default. The perl4 version is just for historic value now.

This was originally implemented by John Allen as a perl4 script, then Malcolm Beattie shortened it (see perl4 page), then John Allen changed to perl5 and shortened it some more, then Jan Engelhardt shortened John's script by 4 bytes chars; subsequently I found another 32 bytes. Then Paul Crowley found another 4 chars, but in the mean time someone else (was that Jan? can't seem to find email trail) shortened it a bunch more with the introduction of the INIT idiom allowing -p), and then Paul Crowley found another 2 bytes, so the current shortest version is:

#!/usr/bin/perl -p
INIT{sub Q{$s[($_[0]+=$_[1])%=256]}sub
S{@s[$y,$x++]=@s[$x,$y]}@k=pop=~/../g;S$y=map{S
Q$y,$_+hex$k[$x%@k]}@s=0..255}s/\C/$&^chr Q S Q$y,Q$x/eg
You can fit this onto three lines at the cost of one extra character:
#!/usr/bin/perl -p
INIT{sub Q{$s[($_[0]+=$_[1])%=256]}sub S{@s[$y,$x++]=@s[$x,$y]}@k=pop
=~/../g;S$y=map{S Q$y,$_+hex$k[$x%@k]}@s=0..255}s/\C/$&^chr Q S Q$y,Q$x/eg
Another branch is one by Jan Engelhardt which is 1 char longer, but if you replace $^C with $\0x03 (ie ascii char 3) then you can make it 4 chars shorter than previous best, though it is then not 7-bit clean:
#!/usr/bin/perl -p
INIT{@k=pop=~/../g;$^C=map@s[$w++,$^C]=@s[$^C+=$_+hex$k[$w%@k],$w],@s=0..255}
s#\C#$&^chr$s[255&map{1..$_}@s[$^C,$x]=@s[++$x,$^C+=$s[$x%=@s]]]#eg

Fastest perl5 version

John Allen also implemented this perl5 only version optimised for speed (with second optimisation criteria of size, not saying that this is the fastest rc4 can be made to go in perl):
#!/bin/perl -0777p-- export-a-crypto-system-sig -RC4-in-3-lines-of-perl
use integer;BEGIN{sub S{@s[$x,$y]=@s[$y,$x]}@k=unpack"C*",pack"H*",shift@ARGV;
for(@t=@s=0..255){($y+=$k[$_%@k]+$s[$x=$_])%=256;&S}$x=$y=0}$l=0;($y+=$s[($x+=
1)%=256])%=256,&S,vec($_,$l++,8)^=$s[($s[$x]+$s[$y])%256]while$l<length

Redhat perl bug

Note that the redhat 5.8.0 perl rpm did something silly with unicode configuration so that a lot of scripts won't work. The fix is to obtain and install a newer rpm >= 5.8.1. A work around if you have 5.8.0 is to set the environment variable LC_ALL=C.

This belongs in /etc/profile (or .profile if you're not root):

export LC_ALL=C
and this belongs in /etc/csh.cshrc (or .cshrc or .tcshrc if you're not root and are using respectively csh or tcsh):
setenv LC_ALL C

Legal status

RC4 is a symmetric stream cipher designed by RSADSI. This cipher used to be trade secret of RSADSI, but some anonymous person distributed the source code on the Internet in 1994. It is not known whether the code was "leaked" by a source license holder or whether someone reverse engineered one of the libraries which used RC4. In either case now that it is no longer a trade secret you can use it legally without paying RSA. In theory you could use RC4 in a commercial product without buying a license from RSADSI, but it is possible that RSADSI may make legal threats. If they do this it may turn out to be cheaper to buy a license than fight a protracted legal battle. Some people are calling RC4 ARC4 (Alleged RC4) to avoid using RC4 which is probably a trademark.

The cipher

RC4 is a symmetric stream cipher and is fairly fast. It allows keys up to 2048 bits in length. It uses an internal table of 256 bytes which is seeded with your key, so you can use smaller key sizes too. Since the source has been available cryptographers have been studying the RC4 cipher with interest. Itsik Mantin maintains a page with current results.

Using the perl implementation of RC4

To use you just give a key in hex on the command line and the rc4 perl program will encrypt standard input to standard output. In this example we encrypt the message "test message" with the 32 bit hex key "12abcdef" (such a small key size is insecure, you would choose much larger keys, 128 bits or more for reasonable security). The message is encrypted from stdin to stdout which is redirected to the file "test.rc4":
% echo test message | rc4 12abcdef > test.rc4
To decrypt the message you just reverse the process giving the same key and using the encrypted file:
% rc4 12abcdef < test.rc4

The equivalent C code

The equivalent C code is included here to allow you to test the perl version - they behave in exactly the same way, but the C code is faster, has a lot more lines and is more readable. Here is the equivalent source code plus the testing harness which makes it comparable to perl-RC4:

Equivalent C source code

See also John Allen's compact version of RC4 in C RC4 in C.

The source of rc4 is also available from numerous ftp sites, I got mine from here:

ftp://ftp.ox.ac.uk/pub/crypto/misc/rc4.tar.gz


Comments, html bugs to me (Adam Back) at <adam@cypherspace.org>