File Coverage

blib/lib/Crypt/RC5.pm
Criterion Covered Total %
statement 15 68 22.0
branch 0 14 0.0
condition n/a
subroutine 5 14 35.7
pod 0 9 0.0
total 20 105 19.0


line stmt bran cond sub pod time code
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              
17             package Crypt::RC5;
18              
19 1     1   7723 use Exporter;
  1         3  
  1         42  
20 1     1   1008 use integer;
  1         11  
  1         6  
21 1     1   25 use strict;
  1         7  
  1         33  
22 1     1   5 no strict 'refs';
  1         1  
  1         28  
23 1     1   4 use vars qw/ $VERSION @EXPORT_OK @ISA @S /;
  1         2  
  1         973  
24              
25             @ISA = qw(Exporter);
26             @EXPORT_OK = qw($VERSION RC5);
27             $VERSION = '2.00';
28              
29             sub new ($$$) {
30 0     0 0   my ( $class, $key, $rounds ) = @_;
31 0           my $self = bless {}, $class;
32 0           my @temp = unpack( "C*", $key );
33 0           my $newKey;
34 0           foreach my $temp ( @temp ) {
35 0           $temp = sprintf( "%lx", $temp );
36 0 0         if ( length( $temp ) < 2 ) {
37 0           $temp = "0" . $temp;
38             }
39 0           $newKey .= $temp;
40             }
41 0           my @L = unpack "V*", pack "H*x3", $newKey;
42 0           my $T = 0xb7e15163;
43 0           @S = ( M( $T ), map { $T = M( $T + 0x9e3779b9 ) } 0 .. 2 * $rounds );
  0            
44 0           my ( $A, $B ) = ( 0, 0 );
45 0 0         for ( 0 .. 3 * ( @S > @L ? @S : @L ) - 1 ) {
46 0           $A = $S[ $_ % @S ] = ROTL( 3, M( $S[ $_ % @S ] ) + M( $A + $B ) );
47 0           $B = $L[ $_ % @L ] = ROTL( M( $A + $B ), M( $L[ $_ % @L ] ) + M( $A + $B ) );
48             }
49 0           return $self;
50             }
51              
52             sub encrypt ($$) {
53 0     0 0   my ( $self, $text ) = @_;
54 0           return $self->RC5( $text );
55             }
56              
57             sub decrypt ($$) {
58 0     0 0   my ( $self, $text ) = @_;
59 0           return $self->RC5( $text, 1 );
60             }
61              
62             sub decrypt_iv ($$$) {
63 0     0 0   my ( $self, $text, $iv ) = @_;
64 0 0         die "iv must be 8 bytes long" if length( $iv ) != 8;
65              
66 0           my @ivnum = unpack( 'C*', $iv . $text );
67 0           my @plain = unpack( 'C*', $self->RC5( $text, 1 ) );
68 0           for ( 0 .. @plain ) { $plain[ $_ ] ^= $ivnum[ $_ ]; }
  0            
69 0           return pack( 'C*', @plain );
70             }
71              
72             sub RC5 ($$) {
73 0     0 0   my ( $self, $text, $decrypt ) = @_;
74 0           my $last;
75 0           my $processed = '';
76 0           while ( $text =~ /(.{8})/gs ) {
77 0           $last = $';
78 0           $processed .= Process( $1, $decrypt );
79             }
80 0 0         if ( length( $text ) % 8 ) {
81 0           $processed .= Process( $last, $decrypt );
82             }
83 0           return $processed;
84             }
85              
86             sub M ($) {
87 0     0 0   return unpack( 'V', pack( 'V', pop ) );
88             }
89              
90             sub ROTL ($$) {
91 0     0 0   my ( $x, $n );
92 0           ( $x = pop ) << ( $n = 31 & pop ) | 2**$n - 1 & $x >> 32 - $n;
93             }
94              
95             sub ROTR ($$) {
96 0     0 0   ROTL( 32 - ( 31 & shift ), shift );
97             }
98              
99             sub Process ($$) {
100 0     0 0   my ( $block, $decrypt ) = @_;
101 0           my ( $A, $B ) = unpack "V2", $block . "\0" x 3;
102 0           $_ = '$A = M( $A+$S[0] );$B = M( $B+$S[1] )';
103 0 0         $decrypt || eval;
104 0           for ( 1 .. @S - 2 ) {
105 0 0         if ( $decrypt ) {
106 0           $B = $A ^ ROTR( $A, M( $B - $S[ @S - $_ ] ) );
107             } else {
108 0           $A = M( $S[ $_ + 1 ] + ROTL( $B, $A ^ $B ) );
109             }
110 0           $A ^= $B ^= $A ^= $B;
111             }
112 0 0         $decrypt && ( y/+/-/, eval );
113 0           return pack "V2", $A, $B;
114             }
115              
116             1;
117             __END__