Crypt-RC4-2.02/ 40755 764 1040 0 7406220302 10464 5ustar klk8380Crypt-RC4-2.02/RC4.pm100444 764 1040 11441 7406220232 11530 0ustar klk8380#--------------------------------------------------------------------# # Crypt::RC4 # Date Written: 07-Jun-2000 04:15:55 PM # Last Modified: 13-Dec-2001 03:33:49 PM # Author: Kurt Kincaid (sifukurt@yahoo.com) # Copyright (c) 2001, Kurt Kincaid # All Rights Reserved. # # This is free software and may be modified and/or # redistributed under the same terms as Perl itself. #--------------------------------------------------------------------# package Crypt::RC4; use strict; use vars qw( $VERSION @ISA @EXPORT $MAX_CHUNK_SIZE ); $MAX_CHUNK_SIZE = 1024 unless $MAX_CHUNK_SIZE; require Exporter; @ISA = qw(Exporter); @EXPORT = qw(RC4); $VERSION = '2.02'; sub new { my ( $class, $key ) = @_; my $self = bless {}, $class; $self->{state} = Setup( $key ); $self->{x} = 0; $self->{y} = 0; $self; } sub RC4 { my $self; my( @state, $x, $y ); if ( ref $_[0] ) { $self = shift; @state = @{ $self->{state} }; $x = $self->{x}; $y = $self->{y}; } else { @state = Setup( shift ); $x = $y = 0; } my $message = shift; my $num_pieces = do { my $num = length($message) / $MAX_CHUNK_SIZE; my $int = int $num; $int == $num ? $int : $int+1; }; for my $piece ( 0..$num_pieces - 1 ) { my @message = unpack "C*", substr($message, $piece * $MAX_CHUNK_SIZE, $MAX_CHUNK_SIZE); for ( @message ) { $x = 0 if ++$x > 255; $y -= 256 if ($y += $state[$x]) > 255; @state[$x, $y] = @state[$y, $x]; $_ ^= $state[( $state[$x] + $state[$y] ) % 256]; } substr($message, $piece * $MAX_CHUNK_SIZE, $MAX_CHUNK_SIZE) = pack "C*", @message; } if ($self) { $self->{state} = \@state; $self->{x} = $x; $self->{y} = $y; } $message; } sub Setup { my @k = unpack( 'C*', shift ); my @state = 0..255; my $y = 0; for my $x (0..255) { $y = ( $k[$x % @k] + $state[$x] + $y ) % 256; @state[$x, $y] = @state[$y, $x]; } wantarray ? @state : \@state; } 1; __END__ =head1 NAME Crypt::RC4 - Perl implementation of the RC4 encryption algorithm =head1 SYNOPSIS # Functional Style use Crypt::RC4; $encrypted = RC4( $passphrase, $plaintext ); $decrypt = RC4( $passphrase, $encrypted ); # OO Style use Crypt::RC4; $ref = Crypt::RC4->new( $passphrase ); $encrypted = $ref->RC4( $plaintext ); $ref2 = Crypt::RC4->new( $passphrase ); $decrypted = $ref2->RC4( $encrypted ); # process an entire file, one line at a time # (Warning: Encrypted file leaks line lengths.) $ref3 = Crypt::RC4->new( $passphrase ); while () { chomp; print $ref3->RC4($_), "\n"; } =head1 DESCRIPTION A simple implementation of the RC4 algorithm, developed by RSA Security, Inc. Here is the description from RSA's website: RC4 is a stream cipher designed by Rivest for RSA Data Security (now RSA Security). It is a variable key-size stream cipher with byte-oriented operations. The algorithm is based on the use of a random permutation. Analysis shows that the period of the cipher is overwhelmingly likely to be greater than 10100. Eight to sixteen machine operations are required per output byte, and the cipher can be expected to run very quickly in software. Independent analysts have scrutinized the algorithm and it is considered secure. Based substantially on the "RC4 in 3 lines of perl" found at http://www.cypherspace.org A major bug in v1.0 was fixed by David Hook (dgh@wumpus.com.au). Thanks, David. =head1 AUTHOR Kurt Kincaid (sifukurt@yahoo.com) Ronald Rivest for RSA Security, Inc. =head1 BUGS Disclaimer: Strictly speaking, this module uses the "alleged" RC4 algorithm. The Algorithm known as "RC4" is a trademark of RSA Security Inc., and this document makes no claims one way or another that this is the correct algorithm, and further, make no claims about the quality of the source code nor any licensing requirements for commercial use. There's nothing preventing you from using this module in an insecure way which leaks information. For example, encrypting multilple messages with the same passphrase may allow an attacker to decode all of them with little effort, even though they'll appear to be secured. If serious crypto is your goal, be careful. Be very careful. It's a pure-Perl implementation, so that rating of "Eight to sixteen machine operations" is good for nothing but a good laugh. If encryption and decryption are a bottleneck for you, please re-write this module to use native code wherever practical. =head1 LICENSE This is free software and may be modified and/or redistributed under the same terms as Perl itself. =head1 SEE ALSO L, L, L, L, L =cut Crypt-RC4-2.02/Makefile.PL100444 764 1040 350 7115774052 12524 0ustar klk8380use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( 'NAME' => 'Crypt::RC4', 'VERSION_FROM' => 'RC4.pm', # finds $VERSION ); Crypt-RC4-2.02/Changes100444 764 1040 1136 7406217404 12064 0ustar klk8380Revision history for Perl extension Crypt::RC4. 2.02 12-Dec-2001 - Initialized $x and $y to make the code warnings-compliant. - Converted globals to instance variables so that the OO interface can work correctly; added tests to ensure that. - Eliminated modification of return value from unpack. - Increased efficiency on long messages. - Fixed buggy tests. - Added some documentation and tests. 2.01 28-Nov-2001 16:12:14 - removed use of "our" to make Crypt::RC4 compatible with earlier versions of perl - stripped ^M's out of .pm file 2.0 23-Nov-2001 13:02:26 - added OO interface Crypt-RC4-2.02/MANIFEST100444 764 1040 54 7115774052 11664 0ustar klk8380Changes MANIFEST Makefile.PL RC4.pm test.pl Crypt-RC4-2.02/test.pl100444 764 1040 10060 7406217140 12116 0ustar klk8380# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl test.pl' ######################### We start with some black magic to print on failure. # Change 1..1 below to 1..last_test_to_print . # (It may become useful if the test is moved to ./t subdirectory.) BEGIN { $| = 1; print "1..9\n"; } END {print "not ok 1\n" unless $loaded;} use Crypt::RC4; $loaded = 1; print "ok 1\n"; ######################### End of black magic. # Insert your test code below (better if it prints "ok 13" # (correspondingly "not ok 13") depending on the success of chunk 13 # of the test code): # # test vectors are from: # # Legion of The Bouncy Castle Java Crypto Libraries http://www.bouncycastle.org # and Crypto++ 3.2 http://www.eskimo.com/~weidai/cryptlib.html # my $passphrase = pack('C*', (0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef)); my $plaintext = pack('C*', (0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef)); my $encrypted = RC4( $passphrase, $plaintext ); my $decrypt = RC4( $passphrase, $encrypted ); if (($encrypted ne pack('C*', (0x75,0xb7,0x87,0x80,0x99,0xe0,0xc5,0x96))) or ($decrypt ne $plaintext)) { print "not ok 2\n"; } else { print "ok 2\n"; } $passphrase = pack('C*', (0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef)); $plaintext = pack('C*', (0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20)); $encrypted = RC4( $passphrase, $plaintext ); $decrypt = RC4( $passphrase, $encrypted ); if (($encrypted ne pack('C*', (0x1c,0xf1,0xe2,0x93,0x79,0x26,0x6d,0x59))) or ($decrypt ne $plaintext)) { print "not ok 3\n"; } else { print "ok 3\n"; } $passphrase = pack('C*', (0xef,0x01,0x23,0x45)); $plaintext = pack('C*', (0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)); $encrypted = RC4( $passphrase, $plaintext ); $decrypt = RC4( $passphrase, $encrypted ); if (($encrypted ne pack('C*', (0xd6,0xa1,0x41,0xa7,0xec,0x3c,0x38,0xdf,0xbd,0x61))) or ($decrypt ne $plaintext)) { print "not ok 4\n"; } else { print "ok 4\n"; } { # Test code by Tom Phoenix use strict; { # Checking that the OO interface maintains separate states my $message = RC4("This is my passphrase", "looks good"); my $one = Crypt::RC4->new("This is my passphrase"); my $two = Crypt::RC4->new("This is not my passphrase"); print "not " unless $one->RC4("looks good") eq $message; print "ok 5\n"; } { # Checking that state is properly maintained my $one = Crypt::RC4->new("This is my passphrase"); # These two must be the same number of bytes my $message_one = $one->RC4("This is a message of precise length"); my $message_two = $one->RC4("This is also a known-length message"); my $two = Crypt::RC4->new("This is my passphrase"); print "not " if $message_two eq $two->RC4("This is also a known-length message"); print "ok 6\n"; print "not " if $message_two ne $two->RC4("This is also a known-length message"); print "ok 7\n"; } { # Ensure that RC4 is not sensitive to chunking. my $message = "This is a message which may be encrypted in chunks, but which should give the same result nonetheless."; my $key = "It's just a passphrase"; my $encrypted = do { my $k = Crypt::RC4->new($key); my @pieces = split /(?=\s+|(?!\n)\Z)/, $message; join "", map $k->RC4($_), @pieces; }; my $failed; # Merely some various chunking sizes. for my $split_size (1, 4, 5, 10, 30, 9999) { my $k = Crypt::RC4->new($key); my @pieces = $message =~ /(.{1,$split_size})/sg; # no /o! my $trial = join "", map $k->RC4($_), @pieces; if ($trial ne $encrypted) { $failed = $split_size; last; } } print "# Failed at split=$failed\nnot " if $failed; print "ok 8\n"; } { # Testing $MAX_CHUNK_SIZE local $Crypt::RC4::MAX_CHUNK_SIZE = 1000; my $message = RC4("passphrase", "message"); $Crypt::RC4::MAX_CHUNK_SIZE = 1; print "not " unless RC4("passphrase", "message") eq $message; print "ok 9\n"; } }