1#---------------------------------------------------------------------------# 2# Crypt::RC5 3# Date Written: 23-Nov-2001 10:47:02 AM 4# Last Modified: 05-Nov-2002 09:52:18 AM 5# Author: Kurt Kincaid 6# Copyright (c) 2002, Kurt Kincaid 7# All Rights Reserved 8# 9# NOTICE: RC5 is a fast block cipher designed by Ronald Rivest 10# for RSA Data Security (now RSA Security) in 1994. It is a 11# parameterized algorithm with a variable block size, a variable 12# key size, and a variable number of rounds. This particular 13# implementation is 32 bit. As such, it is suggested that a minimum 14# of 12 rounds be performed. 15#---------------------------------------------------------------------------# 16 17package Crypt::RC5; 18 19use Exporter; 20use integer; 21use strict; 22no strict 'refs'; 23use vars qw/ $VERSION @EXPORT_OK @ISA @S /; 24 25@ISA = qw(Exporter); 26@EXPORT_OK = qw($VERSION RC5); 27$VERSION = '2.00'; 28 29sub new ($$$) { 30 my ( $class, $key, $rounds ) = @_; 31 my $self = bless {}, $class; 32 my @temp = unpack( "C*", $key ); 33 my $newKey; 34 foreach my $temp ( @temp ) { 35 $temp = sprintf( "%lx", $temp ); 36 if ( length( $temp ) < 2 ) { 37 $temp = "0" . $temp; 38 } 39 $newKey .= $temp; 40 } 41 my @L = unpack "V*", pack "H*x3", $newKey; 42 my $T = 0xb7e15163; 43 @S = ( M( $T ), map { $T = M( $T + 0x9e3779b9 ) } 0 .. 2 * $rounds ); 44 my ( $A, $B ) = ( 0, 0 ); 45 for ( 0 .. 3 * ( @S > @L ? @S : @L ) - 1 ) { 46 $A = $S[ $_ % @S ] = ROTL( 3, M( $S[ $_ % @S ] ) + M( $A + $B ) ); 47 $B = $L[ $_ % @L ] = ROTL( M( $A + $B ), M( $L[ $_ % @L ] ) + M( $A + $B ) ); 48 } 49 return $self; 50} 51 52sub encrypt ($$) { 53 my ( $self, $text ) = @_; 54 return $self->RC5( $text ); 55} 56 57sub decrypt ($$) { 58 my ( $self, $text ) = @_; 59 return $self->RC5( $text, 1 ); 60} 61 62sub decrypt_iv ($$$) { 63 my ( $self, $text, $iv ) = @_; 64 die "iv must be 8 bytes long" if length( $iv ) != 8; 65 66 my @ivnum = unpack( 'C*', $iv . $text ); 67 my @plain = unpack( 'C*', $self->RC5( $text, 1 ) ); 68 for ( 0 .. @plain ) { $plain[ $_ ] ^= $ivnum[ $_ ]; } 69 return pack( 'C*', @plain ); 70} 71 72sub RC5 ($$) { 73 my ( $self, $text, $decrypt ) = @_; 74 my $last; 75 my $processed = ''; 76 while ( $text =~ /(.{8})/gs ) { 77 $last = $'; 78 $processed .= Process( $1, $decrypt ); 79 } 80 if ( length( $text ) % 8 ) { 81 $processed .= Process( $last, $decrypt ); 82 } 83 return $processed; 84} 85 86sub M ($) { 87 return unpack( 'V', pack( 'V', pop ) ); 88} 89 90sub ROTL ($$) { 91 my ( $x, $n ); 92 ( $x = pop ) << ( $n = 31 & pop ) | 2**$n - 1 & $x >> 32 - $n; 93} 94 95sub ROTR ($$) { 96 ROTL( 32 - ( 31 & shift ), shift ); 97} 98 99sub Process ($$) { 100 my ( $block, $decrypt ) = @_; 101 my ( $A, $B ) = unpack "V2", $block . "\0" x 3; 102 $_ = '$A = M( $A+$S[0] );$B = M( $B+$S[1] )'; 103 $decrypt || eval; 104 for ( 1 .. @S - 2 ) { 105 if ( $decrypt ) { 106 $B = $A ^ ROTR( $A, M( $B - $S[ @S - $_ ] ) ); 107 } else { 108 $A = M( $S[ $_ + 1 ] + ROTL( $B, $A ^ $B ) ); 109 } 110 $A ^= $B ^= $A ^= $B; 111 } 112 $decrypt && ( y/+/-/, eval ); 113 return pack "V2", $A, $B; 114} 115 1161; 117__END__ 118 119 120=head1 NAME 121 122Crypt::RC5 - Perl implementation of the RC5 encryption algorithm. 123 124=head1 SYNOPSIS 125 126 use Crypt::RC5; 127 128 $ref = Crypt::RC5->new( $key, $rounds ); 129 $ciphertext = $ref->encrypt( $plaintext ); 130 131 $ref2 = Crypt::RC5->new( $key, $rounds ); 132 $plaintext2 = $ref2->decrypt( $ciphertext ); 133 134=head1 DESCRIPTION 135 136RC5 is a fast block cipher designed by Ronald Rivest for RSA Data Security (now RSA Security) in 1994. It is a parameterized algorithm with a variable block size, a variable key size, and a variable number of rounds. This particular implementation is 32 bit. As such, it is suggested that a minimum of 12 rounds be performed. 137 138Core logic based on "RC5 in 6 lines of perl" at http://www.cypherspace.org 139 140=head1 AUTHOR 141 142Kurt Kincaid (sifukurt@yahoo.com) 143 144Ronald Rivest for RSA Security, Inc. 145 146=head1 SEE ALSO 147 148L<perl>, L<http://www.cypherspace.org>, L<http://www.rsasecurity.com> 149 150=cut 151 152