File Coverage

blib/lib/Crypt/ECB.pm
Criterion Covered Total %
statement 144 146 98.6
branch 101 110 91.8
condition 14 19 73.6
subroutine 20 21 95.2
pod 15 15 100.0
total 294 311 94.5


line stmt bran cond sub pod time code
1             package Crypt::ECB;
2              
3             # Copyright (C) 2000, 2005, 2008, 2016 Christoph Appel (Christoph.Appel@t-systems.com)
4             # see documentation for details
5              
6              
7             ########################################
8             # general module startup things
9             ########################################
10              
11 13     13   946268 use strict;
  13         127  
  13         384  
12 13     13   66 use warnings;
  13         22  
  13         411  
13              
14 13     13   63 use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
  13         23  
  13         33750  
15              
16             require Exporter;
17              
18             @ISA = qw(Exporter);
19             @EXPORT_OK = qw(encrypt decrypt encrypt_hex decrypt_hex);
20             $VERSION = '2.22';
21              
22              
23             ########################################
24             # public methods - setting up
25             ########################################
26              
27             #
28             # constructor, initialization of vars
29             #
30             sub new ($;$$$)
31             {
32 1879     1879 1 4551 my $class = shift;
33              
34 1879         10880 my $self =
35             {
36             padding => 'standard', # default padding method
37             mode => '',
38             key => '',
39             cipher => '',
40             module => '',
41             keysize => '',
42             blocksize => '',
43              
44             _cipherobj => '', # contains the block cipher object
45             _buffer => '', # internal buffer used by crypt() and finish()
46             };
47              
48 1879         3543 bless $self, $class;
49              
50 1879 100       4041 if ($_[0])
51             {
52 1868         2383 my $options;
53              
54             # options Crypt::CBC style
55 1868 100       5239 if ($_[0] =~ /^-[a-zA-Z]+$/)
    100          
56             {
57 6         22 my %tmp = @_;
58 6         56 $options->{substr(lc $_, 1)} = $tmp{$_} for keys %tmp;
59             }
60              
61             # options like in Crypt::CBC before 2.13
62             elsif (ref $_[0] eq 'HASH')
63             {
64 1         2 $options = shift;
65             }
66              
67             # and like Crypt::CBC before 2.0
68             else
69             {
70 1861         4068 $options->{key} = shift;
71 1861   50     3838 $options->{cipher} = shift || 'DES';
72             }
73              
74             # cipher has to be called before keysize and blocksize
75             # otherwise it would override values provided by the user
76 1868         5897 $self->$_( $options->{$_} ) foreach qw(cipher keysize key blocksize padding);
77             }
78              
79 1879         3582 return $self;
80             }
81              
82             #
83             # set attributes if argument given, return attribute value
84             #
85 3     3 1 15 sub module (\$) { return $_[0]->{module} }
86 1881 100   1881 1 5622 sub keysize (\$;$) { $_[0]->{keysize} = $_[1] if $_[1]; return $_[0]->{keysize} }
  1881         5791  
87 1872 100   1872 1 4723 sub blocksize (\$;$) { $_[0]->{blocksize} = $_[1] if $_[1]; return $_[0]->{blocksize} }
  1872         5240  
88 0     0 1 0 sub mode (\$) { return $_[0]->{mode} }
89              
90             #
91             # sets key if argument given
92             #
93             sub key (\$;$)
94             {
95 1882     1882 1 3215 my $self = shift;
96              
97 1882 100       3734 if (my $key = shift)
98             {
99 1875         2846 $self->{key} = $key;
100              
101             # forget cipher object to force creating a new one
102             # otherwise a key change would not be recognized
103 1875         2750 $self->{_cipherobj} = '';
104             }
105              
106 1882         5390 return $self->{key};
107             }
108              
109             #
110             # sets padding method if argument given
111             #
112             sub padding (\$;$)
113             {
114 3784     3784 1 13841 my $self = shift;
115              
116 3784 100       7116 if (my $padding = shift)
117             {
118             # if given a custom padding...
119 1916 100       3951 if (ref $padding eq 'CODE')
120             {
121             # ...for different block sizes...
122 2         7 for my $bs ((8, 16))
123             {
124             # ...check whether it works as expected
125 3         10 for my $i (0 .. $bs-1)
126             {
127 25         44 my $plain = ' ' x $i;
128              
129 25   100     41 my $padded = $padding->($plain, $bs, 'e') || '';
130 25 100       200 die "Provided padding method does not pad properly: Expected $bs bytes, got ", length $padded, ".\n"
131             unless (length $padded == $bs);
132              
133 24   100     36 my $trunc = $padding->($padded, $bs, 'd') || '';
134 24 50       219 die "Provided padding method does not truncate properly: Expected '$plain', got '$trunc'.\n"
135             unless ($trunc eq $plain);
136             }
137             }
138             }
139              
140 1915         2964 $self->{padding} = $padding;
141             }
142              
143 3783         8013 return $self->{padding};
144             }
145              
146             #
147             # sets and loads crypting module if argument given
148             #
149             sub cipher (\$;$)
150             {
151 2140     2140 1 16510171 my $self = shift;
152              
153 2140 100       4828 if (my $cipher = shift)
154             {
155 2132         2845 my $module;
156              
157             # if a cipher object is provided...
158 2132 100       3664 if (ref $cipher)
159             {
160             # ...use it
161 1         3 $self->{_cipherobj} = $cipher;
162              
163 1         2 $module = ref $cipher;
164 1         4 ($cipher = $module) =~ s/^Crypt:://;
165             }
166              
167             # else try to load the specified cipher module
168             else
169             {
170             # for compatibility with Crypt::CBC, cipher modules can be specified
171             # with or without the 'Crypt::' in front
172 2131 50       5823 $module = $cipher=~/^Crypt/ ? $cipher : "Crypt::$cipher";
173              
174 2131         117732 eval "require $module";
175 2131 100       15285 die "Couldn't load $module: $@"."Are you sure '$cipher' is correct? If so,"
176             . " install $module in the proper path or choose some other cipher.\n"
177             if $@;
178              
179             # delete possibly existing cipher obj from a previous crypt process
180             # otherwise changes in the cipher would not be recognized by start()
181 1878         4154 $self->{_cipherobj} = '';
182             }
183              
184             # some packages like Crypt::DES and Crypt::IDEA behave strange in the way
185             # that their methods do not belong to the Crypt::DES or Crypt::IDEA namespace
186             # but only DES or IDEA instead
187 1879 50       9107 unless ($module->can('blocksize')) { $module=$cipher }
  0         0  
188              
189 1879 50 33     8573 die "Can't work because Crypt::$cipher doesn't report blocksize."
190             . " Are you sure $cipher is a valid cipher module?\n"
191             unless ($module->can('blocksize') && $module->blocksize);
192              
193 1879         9430 $self->{blocksize} = $module->blocksize;
194              
195             # In opposition to the blocksize, the keysize need not be known by me,
196             # but by the one who provides the key. This is because some modules
197             # (e.g. Crypt::Blowfish) report keysize 0; in other cases several keysizes
198             # are admitted, so reporting just one number would anyway be to narrow
199 1879 50       10185 $self->{keysize} = $module->can('keysize') ? $module->keysize : '';
200              
201 1879         5577 $self->{module} = $module;
202 1879         3299 $self->{cipher} = $cipher;
203             }
204              
205 1887         7156 return $self->{cipher};
206             }
207              
208              
209             ########################################
210             # public methods - en-/decryption
211             ########################################
212              
213             #
214             # sets mode if argument given, either en- or decrypt
215             # checks, whether all required vars are set
216             # returns mode
217             #
218             sub start (\$$)
219             {
220 3791     3791 1 7092 my $self = shift;
221 3791         4673 my $mode = shift;
222              
223             die "Not yet finished existing crypting process. Call finish() before calling start() anew.\n"
224 3791 100       7179 if $self->{_buffer};
225              
226 3790 100       12801 die "Mode has to be either (e)ncrypt or (d)ecrypt.\n"
227             unless ($mode=~/^[de]/i);
228              
229             # unless a cipher object is provided (see cipher())...
230 3789 100       7931 unless ($self->{_cipherobj})
231             {
232             # make sure we have a key...
233             die "Key not set. Use '\$ecb->key ('some_key'). The key length is probably specified"
234             . " by the algorithm (for example the Crypt::IDEA module needs a sixteen byte key).\n"
235 1873 100       3496 unless $self->{key};
236              
237             # ...as well as a block cipher
238             die "Can't start() without cipher. Use '\$ecb->cipher(\$cipher)', \$cipher being some"
239             . " algorithm like for example 'DES', 'IDEA' or 'Blowfish'. Of course, the corresponding"
240             . " module 'Crypt::\$cipher' needs to be installed.\n"
241 1872 100       3281 unless $self->{module};
242              
243             # initialize cipher obj doing the actual en-/decryption
244 1871         4455 $self->{_cipherobj} = $self->{module}->new( $self->{key} );
245             }
246              
247 3787 100       25455 $self->{mode} = ($mode=~/^d/i) ? "decrypt" : "encrypt";
248              
249 3787         5655 return $self->{mode};
250             }
251              
252             #
253             # calls the crypting module
254             # returns the en-/decrypted data
255             #
256             sub crypt (\$;$)
257             {
258 3848     3848 1 5577 my $self = shift;
259 3848         5217 my $data = shift;
260            
261 3848 100 100     6994 $data = ($_ || '') unless defined $data;
262              
263 3848         5659 my $bs = $self->{blocksize};
264 3848         5107 my $mode = $self->{mode};
265              
266 3848 100       6200 die "You tried to use crypt() without calling start() before. Use '\$ecb->start(\$mode)'"
267             . " first, \$mode being one of 'decrypt' or 'encrypt'.\n"
268             unless $mode;
269              
270 3847         9515 $data = $self->{_buffer}.$data;
271              
272             # data is split into blocks of proper size which is reported
273             # by the cipher module
274 3847         20774 my @blocks = $data=~/(.{1,$bs})/gs;
275              
276             # last block goes into buffer
277 3847         8026 $self->{_buffer} = pop @blocks;
278              
279 3847         6949 my ($cipher, $text) = ($self->{_cipherobj}, '');
280 3847         9731 $text .= $cipher->$mode($_) foreach (@blocks);
281 3847         26084 return $text;
282             }
283              
284             #
285             #
286             #
287             sub finish (\$)
288             {
289 3788     3788 1 6174 my $self = shift;
290              
291 3788         5417 my $bs = $self->{blocksize};
292 3788         4925 my $mode = $self->{mode};
293 3788         5742 my $data = $self->{_buffer};
294 3788         4837 my $result = '';
295              
296 3788 100       6630 die "You tried to use finish() without calling start() before. Use '\$ecb->start(\$mode)'"
297             . " first, \$mode being one of 'decrypt' or 'encrypt'.\n"
298             unless $mode;
299              
300             # cleanup: forget mode, purge buffer
301 3787         5825 $self->{mode} = '';
302 3787         5374 $self->{_buffer} = '';
303              
304 3787 100       6759 return '' unless defined $data;
305              
306 3747         5507 my $cipher = $self->{_cipherobj};
307              
308             # now we have to distinguish between en- and decryption:
309             # when decrypting, data has to be truncated to correct size
310             # when encrypting, data has to be padded up to blocksize
311 3747 100       8978 if ($mode =~ /^d/i)
312             {
313             # pad data with binary 0 up to blocksize
314             # in fact, this should not be necessary because correctly
315             # encrypted data is always a multiple of the blocksize
316 1420         4399 $data = pack("a$bs",$data);
317              
318 1420         3316 $result = $cipher->$mode($data);
319 1420         13232 $result = $self->_truncate($result);
320             }
321             else
322             {
323             # if length is smaller than blocksize, just pad the block
324 2327 100       4253 if (length($data) < $bs)
325             {
326 2245         4403 $data = $self->_pad($data);
327 2243         6009 $result = $cipher->$mode($data);
328             }
329             # else append another block (depending on padding chosen)
330             else
331             {
332 82         244 $result = $cipher->$mode($data);
333 82 100       885 $self->_pad('') &&
334             ($result .= $cipher->$mode( $self->_pad('') ));
335             }
336             }
337              
338 3742         25254 return $result;
339             }
340              
341              
342             ########################################
343             # private methods
344             ########################################
345              
346             #
347             # pad block to blocksize
348             #
349             sub _pad (\$$)
350             {
351 2376     2376   3330 my $self = shift;
352 2376         3297 my $data = shift;
353              
354 2376         3328 my $bs = $self->{blocksize};
355 2376         3666 my $padding = $self->{padding};
356              
357 2376         3977 my $pad = $bs - length $data;
358              
359 2376         5698 my $message = "Your message length is not a multiple of $self->{cipher}'s blocksize ($bs bytes)."
360             . " Correct this by hand or tell me to handle padding.\n";
361              
362 2376 100 66     9071 $padding eq 'standard' ? $data .= chr($pad) x $pad :
    100 66        
    100 100        
    100          
    100          
    100          
    100          
    100          
363             $padding eq 'zeroes' ? $data .= "\0" x ($pad-1) . chr($pad) :
364             $padding eq 'oneandzeroes' ? $data .= "\x80" . "\0"x($pad-1) :
365             $padding eq 'rijndael_compat' ? (length $data) && ($data .= "\x80" . "\0"x($pad-1)) :
366             $padding eq 'null' ? $data .= "\0"x $pad :
367             $padding eq 'space' ? (length $data) && ($data .= " " x $pad) :
368             ref $padding eq 'CODE' ? $data = $padding ->($data, $bs, 'e') :
369             $padding eq 'none' ? (length($data) % $bs) && die $message :
370              
371             # still here?
372             die "Padding style '$padding' not defined.\n";
373              
374 2374         5687 return $data;
375             }
376              
377             #
378             # truncates result to correct length
379             #
380             sub _truncate (\$$)
381             {
382 1420     1420   1983 my $self = shift;
383 1420         2003 my $data = shift;
384              
385 1420         2175 my $bs = $self->{blocksize};
386 1420         2178 my $padding = $self->{padding};
387              
388 1420 100       3801 if ($padding =~ /^(standard|zeroes|random)$/)
389             {
390 561         1166 my $trunc = ord(substr $data, -1);
391              
392 561 100       1133 die "Asked to truncate $trunc bytes, which is greater than $self->{cipher}'s blocksize ($bs bytes).\n"
393             if $trunc > $bs;
394              
395 560 0       1908 my $expected = $padding eq 'standard' ? chr($trunc) x $trunc :
    50          
    100          
396             $padding eq 'zeroes' ? "\0" x ($trunc-1) . chr($trunc) :
397             $padding eq 'random' ? substr($data, -$trunc, $trunc-1) . chr($trunc) : 'WTF!?';
398              
399 560 100       1333 die "Block doesn't look $padding padded.\n" unless $expected eq substr($data, -$trunc);
400              
401 559         1030 substr($data, -$trunc) = '';
402             }
403             else
404             {
405 859 100       4641 $padding eq 'oneandzeroes' ? $data =~ s/\x80\0*$//s :
    100          
    100          
    100          
    100          
    100          
406             $padding eq 'rijndael_compat' ? $data =~ s/\x80\0*$//s :
407             $padding eq 'null' ? $data =~ s/\0+$//s :
408             $padding eq 'space' ? $data =~ s/ +$//s :
409             ref $padding eq 'CODE' ? $data = $padding->($data, $bs, 'd') :
410             $padding eq 'none' ? () :
411              
412             # still here?
413             die "Padding style '$padding' not defined.\n";
414             }
415              
416 1417         3560 return $data;
417             }
418              
419              
420             ########################################
421             # convenience functions/methods
422             ########################################
423              
424             #
425             # magic decrypt/encrypt function/method
426             #
427             sub _crypt
428             {
429 3784     3784   5781 my ($mode, $self, $key, $cipher, $data, $padding);
430              
431 3784 100       6580 if (ref $_[1])
432             {
433 1924         3835 ($mode, $self, $data) = @_;
434             }
435             else
436             {
437 1860         3972 ($mode, $key, $cipher, $data, $padding) = @_;
438              
439 1860         4287 $self = __PACKAGE__->new($key => $cipher);
440 1860 50       5138 $self->padding($padding) if $padding;
441              
442 1860 100       3544 $data = $_ unless length($data);
443             }
444              
445 3784         8264 $self->start($mode);
446 3784         6404 my $text = $self->crypt($data) . $self->finish;
447              
448 3779         16332 return $text;
449             }
450              
451             #
452             # convenience encrypt and decrypt functions/methods
453             #
454 2350     2350 1 144210 sub encrypt ($$;$$) { _crypt('encrypt', @_) }
455 1434     1434 1 142390 sub decrypt ($$;$$) { _crypt('decrypt', @_) }
456              
457             #
458             # calls encrypt, returns hex packed data
459             #
460             sub encrypt_hex ($$;$$)
461             {
462 1396 100   1396 1 275706 if (ref $_[0])
463             {
464 931         1496 my $self = shift;
465 931         1858 join('',unpack('H*',$self->encrypt(shift)));
466             }
467             else
468             {
469 465         964 join('',unpack('H*',encrypt($_[0], $_[1], $_[2], $_[3])));
470             }
471             }
472              
473             #
474             # calls decrypt, expected input is hex packed
475             #
476             sub decrypt_hex ($$;$$)
477             {
478 933 100   933 1 142116 if (ref $_[0])
479             {
480 468         642 my $self = shift;
481 468         1565 $self->decrypt(pack('H*',shift));
482             }
483             else
484             {
485 465         2364 decrypt($_[0], $_[1], pack('H*',$_[2]), $_[3]);
486             }
487             }
488              
489              
490             ########################################
491             # finally, to satisfy require
492             ########################################
493              
494             'The End...';
495             __END__