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>