#!/usr/bin/perl
#
# implementation of the RC4 algorithm with the 24-bit WEP IV
# as well as an attack on the WEP implementation
#
# -samy kamkar, code@samy.pl

use strict;

my (%test, @S, $i, $j);

# we produce 100 "packets" in order to satisfy a 5% correlation
for my $V (1 .. 100)
{

# our KNOWN 24 bit IV. the first 8 bits allows us to determine K[3] for N packets (we use 100 to be more than safe)
my @IV = (3, 255, $V);

# the rest of our key, randomness that we try to determine
my @K = (10, 15, 20, 26, 5, 99, 55, 11, 22, 88, 77);
my $plaintext = "Plaintext";

if ($V == 1)
{
	print "IV + Key: @IV + @K\n";
	print "Plaintext: $plaintext\n";
}

# join our IV and key
@K = (@IV, @K);

# RC4 initialization
@S = ();
$i = $j = 0;
foreach $i (0 .. 255)
{
	$S[$i] = $i;
}

print "S: @S[0..10]\n" if $V == 1;
foreach $i (0 .. 255)
{
	$j = ($j + $S[$i] + $K[$i % @K]) % 256;
	($S[$i], $S[$j]) = ($S[$j], $S[$i]);
}
print "Post-init-S: @S[0..10]\n";
$i = $j = 0;

my $b;
foreach my $byte (split(//, $plaintext))
{
	$b .= unpack("H2", chr(ord($byte) ^ gen_key()));
}
if ($b =~ /(..)/)
{
	print "B: C[0]=$1 C[0]=" . ord(pack("H2", $1)) . " - K[0]?=" . (((ord(pack("H2", $1)) ^ ord("P")) - 6 - $V) % 256) . "\n";
	$test{(((ord(pack("H2", $1)) ^ ord("P")) - 6 - $V) % 256)}++;
}
#print "\n";
}

sub gen_key
{
	# keystream generator
	$i = ($i + 1) % 256;
	$j = ($j + $S[$i]) % 256;
	($S[$i], $S[$j]) = ($S[$j], $S[$i]);
	my $t = ($S[$i] + $S[$j]) % 256;
	return $S[$t];
}

print "\nKnowing IV, 'P', and 100 packets, searching for K[3] with 5% probability...\n";
foreach (keys %test)
{
	if ($test{$_} >= 3)
	{
		print "K[3]: $_ ($test{$_} matches)\n";
	}
}
