File Coverage

blib/lib/Crypt/CipherSaber.pm
Criterion Covered Total %
statement 79 79 100.0
branch 12 12 100.0
condition 5 5 100.0
subroutine 12 12 100.0
pod 5 5 100.0
total 113 113 100.0


line stmt bran cond sub pod time code
1             package Crypt::CipherSaber;
2              
3 7     7   32866 use strict;
  7         16  
  7         321  
4              
5 7     7   49 use Carp;
  7         21  
  7         576  
6 7     7   38 use Scalar::Util 'reftype';
  7         15  
  7         895  
7              
8 7     7   80 use vars '$VERSION';
  7         12  
  7         7962  
9              
10             $VERSION = '1.00';
11              
12             sub new
13             {
14 8     8 1 23327 my ($class, $key, $N) = @_;
15              
16             # CS-2 shuffles the state array N times, CS-1 once
17 8 100 100     69 if ( !( defined $N ) or ( $N < 1 ) )
18             {
19 7         17 $N = 1;
20             }
21 8         191 bless [ $key, [ 0 .. 255 ], $N ], $class;
22             }
23              
24             sub crypt
25             {
26 6     6 1 17 my ($self, $iv, $message) = @_;
27 6         20 $self->_setup_key($iv);
28              
29 6         15 my $state = $self->[1];
30 6         26 my $output = _do_crypt( $state, $message );
31 6         112 $self->[1] = [ 0 .. 255 ];
32 6         68 return $output;
33             }
34              
35             sub encrypt
36             {
37 2     2 1 72 my $self = shift;
38 2         9 my $iv = $self->_gen_iv();
39 2         9 return $iv . $self->crypt( $iv, @_ );
40             }
41              
42             sub decrypt
43             {
44 3     3 1 638 my $self = shift;
45 3         26 my ( $iv, $message ) = unpack( "a10a*", +shift );
46 3         13 return $self->crypt( $iv, $message );
47             }
48              
49             sub fh_crypt
50             {
51 7     7 1 2921 my ( $self, $in, $out, $iv ) = @_;
52              
53 7         23 for my $glob ($in, $out)
54             {
55 13   100     82 my $reftype = reftype( $glob ) || '';
56 13 100       50 unless ($reftype eq 'GLOB')
57             {
58 2         12 require Carp;
59 2         37 Carp::carp( 'Non-filehandle passed to fh_crypt()' );
60 2         1378 return;
61             }
62             }
63              
64 5         302 local *OUT = $out;
65 5 100       20 if ( defined($iv) )
66             {
67 2 100       12 $iv = $self->_gen_iv() if length($iv) == 1;
68 2         11 $self->_setup_key($iv);
69 2         24 print OUT $iv;
70             }
71              
72 5         17 my $state = $self->[1];
73              
74 5         9 my ( $buf, @vars );
75              
76 5         94 while (<$in>)
77             {
78 33 100       84 unless ($iv)
79             {
80 3         27 ( $iv, $_ ) = unpack( "a10a*", $_ );
81 3         14 $self->_setup_key($iv);
82             }
83 33         48 my $line;
84 33         89 ( $line, $state, @vars ) = _do_crypt( $state, $_, @vars );
85 33         571 print OUT $line;
86             }
87 5         174 $self->[1] = [ 0 .. 255 ];
88 5         92 return 1;
89             }
90              
91             ###################
92             #
93             # PRIVATE METHODS
94             #
95             ###################
96             sub _gen_iv
97             {
98 3     3   7 my $iv;
99 3         13 for ( 1 .. 10 )
100             {
101 30         813 $iv .= chr( int( rand(256) ) );
102             }
103 3         12 return $iv;
104             }
105              
106             sub _setup_key
107             {
108 11     11   26 my $self = shift;
109 11         51 my $key = $self->[0] . shift;
110 11         91 my @key = map { ord } split( //, $key );
  243         911  
111 11         50 my $state = $self->[1];
112 11         22 my $j = 0;
113 11         27 my $length = @key;
114              
115             # repeat N times, for CS-2
116 11         35 for ( 1 .. $self->[2] )
117             {
118 19         44 for my $i ( 0 .. 255 )
119             {
120 4864         5992 $j += ( $state->[$i] + ( $key[ $i % $length ] ) );
121 4864         5057 $j %= 256;
122 4864         9205 ( @$state[ $i, $j ] ) = ( @$state[ $j, $i ] );
123             }
124             }
125             }
126              
127             sub _do_crypt
128             {
129 39     39   95 my ( $state, $message, $i, $j, $n ) = @_;
130              
131 39         86 my $output = '';
132              
133 39         146 for ( 0 .. ( length($message) - 1 ) )
134             {
135 8265         15028 $i++;
136 8265         15307 $i %= 256;
137 8265         14852 $j += $state->[$i];
138 8265         18927 $j %= 256;
139 8265         19242 @$state[ $i, $j ] = @$state[ $j, $i ];
140 8265         35906 $n = $state->[$i] + $state->[$j];
141 8265         10706 $n %= 256;
142 8265         17089 $output .= chr( $state->[$n] ^ ord( substr( $message, $_, 1 ) ) );
143             }
144              
145 39 100       335 return wantarray ? ( $output, $state, $i, $j, $n ) : $output;
146             }
147              
148             1;
149              
150             __END__