#!/usr/bin/perl -w
# Copyright (c) 2001-2006 Robert Hagemann <bobzilla@wigle.net>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# $Id: wep.pl 3342 2006-11-21 15:18:49Z bobzilla $

use strict;

use Digest::MD5 qw(md5 md5_hex md5_base64);

my $in = $ARGV[0];
if ( !defined $in ) {
	print "Please enter the text key as the first argument\n";
	exit(1);
}

print "\nConverting ASCII string '$in' to hexadecimal\n";
print "using common wifi driver algorithms.\n\n";

### do 40 bit prismII ###
print "40 bit Prism II (D-Link, Apple)\n";
my @input = split //, $in;
my $length = length $in;
my @pseed = (0,0,0,0);

# print "in:$in length:$length\n\n";

for ( my $i = 0; $i < $length; $i++ ) {
	# print "i:$i input[i]:" . unpack( "c", $input[ $i ] ) . "\n";
	$pseed[ $i % 4 ] ^= unpack( "c", $input[ $i ] );
	# print "pseed[" . $i % 4 . "]: " . $pseed[ $i % 4 ] . "\n";
}

my $randseed = $pseed[0] 
	+ ($pseed[1] * 256) 
	+ ($pseed[2] * 256 * 256) 
	+ ($pseed[3] * 256 * 256 * 256);
# print "seed: $randseed\n\n";

for ( my $j = 0; $j < 4; $j++ ) {
	print "key $j: ";
	for ( my $i = 0; $i < 5; $i++ ) {
		$randseed *= 0x343fd;
		$randseed += 0x269ec3;
	
		# fake the 4byte rollover
		$randseed %= 0x80000000 + 0x80000000;
		if ( $randseed > 0x80000000 ) {
			$randseed -= 0x80000000;
			$randseed -= 0x80000000;
		}
	
		# print "randseed $randseed i:$i\n";
		my $output = ( $randseed / (256*256) ) & 0xff;
		
		# this is a hack due to the signedness of $output being one off
		# if it's negative due to 2's complimentation
		if ( $randseed < 0 ) {
			$output--;
		}
		
		$output &= 0xff;
		print sprintf("%02x", $output) . " ";
	}
	print "\n";
}

### do 104 bit prismII ###
print "\n104 bit Prism II (D-Link, Apple)\n";
my $seed = $ARGV[0];
while ( length $seed < 64 ) {
	$seed .= $ARGV[0];
}
$seed =~ s/^(.{64}).*$/$1/;
my $md5hex = md5_hex( $seed );
print "$md5hex\n";
print " or for apple:\n";
$md5hex =~ s/^(.{26}).*$/$1/si;
print "$md5hex\n";

### do 40 bit hermes ###
print "\n40 bit Hermes (Orinoco)\n";
my $hex = unpack("H*", $ARGV[0]);
my $output = $hex;
$output .= $hex while ( length $output < 10 );
$output =~ s/^(.{10}).*$/$1/si;
print "$output\n";

### do 104 bit hermes ###
print "\n104 bit Hermes (Orinoco)\n";
$output = $hex;
$output .= $hex while ( length $output < 20 );
$output =~ s/^(.{20}).*$/$1/si;
print "$output\n\n";

