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   204189 use strict;
  13         18  
  13         300  
12 13     13   40 use warnings;
  13         15  
  13         321  
13              
14 13     13   37 use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
  13         16  
  13         22662  
15              
16             require Exporter;
17              
18             @ISA = qw(Exporter);
19             @EXPORT_OK = qw(encrypt decrypt encrypt_hex decrypt_hex);
20             $VERSION = '2.20';
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 1971 my $class = shift;
33              
34 1879         8022 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         1982 bless $self, $class;
49              
50 1879 100       3118 if ($_[0])
51             {
52 1868         1296 my $options;
53              
54             # options Crypt::CBC style
55 1868 100       3782 if ($_[0] =~ /^-[a-zA-Z]+$/)
    100          
56             {
57 6         19 my %tmp = @_;
58 6         41 $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         2744 $options->{key} = shift;
71 1861   50     3244 $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         4621 $self->$_( $options->{$_} ) foreach qw(cipher keysize key blocksize padding);
77             }
78              
79 1879         2074 return $self;
80             }
81              
82             #
83             # set attributes if argument given, return attribute value
84             #
85 3     3 1 11 sub module (\$) { return $_[0]->{module} }
86 1881 100   1881 1 4088 sub keysize (\$;$) { $_[0]->{keysize} = $_[1] if $_[1]; return $_[0]->{keysize} }
  1881         4385  
87 1872 100   1872 1 3342 sub blocksize (\$;$) { $_[0]->{blocksize} = $_[1] if $_[1]; return $_[0]->{blocksize} }
  1872         3927  
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 1806 my $self = shift;
96              
97 1882 100       2539 if (my $key = shift)
98             {
99 1875         1411 $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         1543 $self->{_cipherobj} = '';
104             }
105              
106 1882         3729 return $self->{key};
107             }
108              
109             #
110             # sets padding method if argument given
111             #
112             sub padding (\$;$)
113             {
114 3784     3784 1 10674 my $self = shift;
115              
116 3784 100       5435 if (my $padding = shift)
117             {
118             # if given a custom padding...
119 1916 100       2966 if (ref $padding eq 'CODE')
120             {
121             # ...for different block sizes...
122 2         5 for my $bs ((8, 16))
123             {
124             # ...check whether it works as expected
125 3         6 for my $i (0 .. $bs-1)
126             {
127 25         28 my $plain = ' ' x $i;
128              
129 25   100     30 my $padded = $padding->($plain, $bs, 'e') || '';
130 25 100       132 die "Provided padding method does not pad properly: Expected $bs bytes, got ", length $padded, ".\n"
131             unless (length $padded == $bs);
132              
133 24   100     27 my $trunc = $padding->($padded, $bs, 'd') || '';
134 24 50       150 die "Provided padding method does not truncate properly: Expected '$plain', got '$trunc'.\n"
135             unless ($trunc eq $plain);
136             }
137             }
138             }
139              
140 1915         2166 $self->{padding} = $padding;
141             }
142              
143 3783         5534 return $self->{padding};
144             }
145              
146             #
147             # sets and loads crypting module if argument given
148             #
149             sub cipher (\$;$)
150             {
151 2152     2152 1 3041255 my $self = shift;
152              
153 2152 100       3490 if (my $cipher = shift)
154             {
155 2144         1505 my $module;
156              
157             # if a cipher object is provided...
158 2144 100       2684 if (ref $cipher)
159             {
160             # ...use it
161 1         1 $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 2143 50       3874 $module = $cipher=~/^Crypt/ ? $cipher : "Crypt::$cipher";
173              
174 2143         92295 eval "require $module";
175 2143 100       10309 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         2785 $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       6873 unless ($module->can('blocksize')) { $module=$cipher }
  0         0  
188              
189 1879 50 33     6414 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         7478 $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       7133 $self->{keysize} = $module->can('keysize') ? $module->keysize : '';
200              
201 1879         3878 $self->{module} = $module;
202 1879         1921 $self->{cipher} = $cipher;
203             }
204              
205 1887         5581 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 4448 my $self = shift;
221 3791         2894 my $mode = shift;
222              
223             die "Not yet finished existing crypting process. Call finish() before calling start() anew.\n"
224 3791 100       5809 if $self->{_buffer};
225              
226 3790 100       8231 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       5058 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       2504 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       2352 unless $self->{module};
242              
243             # initialize cipher obj doing the actual en-/decryption
244 1871         3292 $self->{_cipherobj} = $self->{module}->new( $self->{key} );
245             }
246              
247 3787 100       16026 $self->{mode} = ($mode=~/^d/i) ? "decrypt" : "encrypt";
248              
249 3787         3549 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 3088 my $self = shift;
259 3848         2950 my $data = shift;
260            
261 3848 100 100     5019 $data = ($_ || '') unless defined $data;
262              
263 3848         3049 my $bs = $self->{blocksize};
264 3848         3080 my $mode = $self->{mode};
265              
266 3848 100       4664 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         5751 $data = $self->{_buffer}.$data;
271              
272             # data is split into blocks of proper size which is reported
273             # by the cipher module
274 3847         15530 my @blocks = $data=~/(.{1,$bs})/gs;
275              
276             # last block goes into buffer
277 3847         4133 $self->{_buffer} = pop @blocks;
278              
279 3847         3620 my ($cipher, $text) = ($self->{_cipherobj}, '');
280 3847         7196 $text .= $cipher->$mode($_) foreach (@blocks);
281 3847         16693 return $text;
282             }
283              
284             #
285             #
286             #
287             sub finish (\$)
288             {
289 3788     3788 1 3199 my $self = shift;
290              
291 3788         3081 my $bs = $self->{blocksize};
292 3788         2723 my $mode = $self->{mode};
293 3788         3071 my $data = $self->{_buffer};
294 3788         2527 my $result = '';
295              
296 3788 100       4759 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         2840 $self->{mode} = '';
302 3787         2672 $self->{_buffer} = '';
303              
304 3787 100       4512 return '' unless defined $data;
305              
306 3747         2870 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       5773 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         3026 $data = pack("a$bs",$data);
317              
318 1420         2273 $result = $cipher->$mode($data);
319 1420         7608 $result = $self->_truncate($result);
320             }
321             else
322             {
323             # if length is smaller than blocksize, just pad the block
324 2327 100       2786 if (length($data) < $bs)
325             {
326 2245         2472 $data = $self->_pad($data);
327 2243         4157 $result = $cipher->$mode($data);
328             }
329             # else append another block (depending on padding chosen)
330             else
331             {
332 82         166 $result = $cipher->$mode($data);
333 82 100       511 $self->_pad('') &&
334             ($result .= $cipher->$mode( $self->_pad('') ));
335             }
336             }
337              
338 3742         15327 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   1719 my $self = shift;
352 2376         1617 my $data = shift;
353              
354 2376         1965 my $bs = $self->{blocksize};
355 2376         1982 my $padding = $self->{padding};
356              
357 2376         2115 my $pad = $bs - length $data;
358              
359 2376         3732 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     7354 $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         3293 return $data;
375             }
376              
377             #
378             # truncates result to correct length
379             #
380             sub _truncate (\$$)
381             {
382 1420     1420   1123 my $self = shift;
383 1420         1041 my $data = shift;
384              
385 1420         1133 my $bs = $self->{blocksize};
386 1420         1178 my $padding = $self->{padding};
387              
388 1420 100       3290 if ($padding =~ /^(standard|zeroes|random)$/)
389             {
390 561         709 my $trunc = ord(substr $data, -1);
391              
392 561 100       874 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       1408 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       957 die "Block doesn't look $padding padded.\n" unless $expected eq substr($data, -$trunc);
400              
401 559         796 substr($data, -$trunc) = '';
402             }
403             else
404             {
405 859 100       3406 $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         1933 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   2915 my ($mode, $self, $key, $cipher, $data, $padding);
430              
431 3784 100       4604 if (ref $_[1])
432             {
433 1924         2869 ($mode, $self, $data) = @_;
434             }
435             else
436             {
437 1860         3130 ($mode, $key, $cipher, $data, $padding) = @_;
438              
439 1860         3499 $self = __PACKAGE__->new($key => $cipher);
440 1860 50       3555 $self->padding($padding) if $padding;
441              
442 1860 100       2797 $data = $_ unless length($data);
443             }
444              
445 3784         5131 $self->start($mode);
446 3784         4257 my $text = $self->crypt($data) . $self->finish;
447              
448 3779         11494 return $text;
449             }
450              
451             #
452             # convenience encrypt and decrypt functions/methods
453             #
454 2350     2350 1 125103 sub encrypt ($$;$$) { _crypt('encrypt', @_) }
455 1434     1434 1 122660 sub decrypt ($$;$$) { _crypt('decrypt', @_) }
456              
457             #
458             # calls encrypt, returns hex packed data
459             #
460             sub encrypt_hex ($$;$$)
461             {
462 1396 100   1396 1 203171 if (ref $_[0])
463             {
464 931         832 my $self = shift;
465 931         1319 join('',unpack('H*',$self->encrypt(shift)));
466             }
467             else
468             {
469 465         729 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 122551 if (ref $_[0])
479             {
480 468         327 my $self = shift;
481 468         1053 $self->decrypt(pack('H*',shift));
482             }
483             else
484             {
485 465         1841 decrypt($_[0], $_[1], pack('H*',$_[2]), $_[3]);
486             }
487             }
488              
489              
490             ########################################
491             # finally, to satisfy require
492             ########################################
493              
494             'The End...';
495             __END__