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