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   209022 use strict;
  13         21  
  13         320  
12 13     13   44 use warnings;
  13         15  
  13         380  
13              
14 13     13   41 use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
  13         19  
  13         22719  
15              
16             require Exporter;
17              
18             @ISA = qw(Exporter);
19             @EXPORT_OK = qw(encrypt decrypt encrypt_hex decrypt_hex);
20             $VERSION = '2.21';
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 2130 my $class = shift;
33              
34 1879         8266 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         2043 bless $self, $class;
49              
50 1879 100       3056 if ($_[0])
51             {
52 1868         1248 my $options;
53              
54             # options Crypt::CBC style
55 1868 100       3817 if ($_[0] =~ /^-[a-zA-Z]+$/)
    100          
56             {
57 6         14 my %tmp = @_;
58 6         40 $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         2767 $options->{key} = shift;
71 1861   50     3277 $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         4654 $self->$_( $options->{$_} ) foreach qw(cipher keysize key blocksize padding);
77             }
78              
79 1879         2531 return $self;
80             }
81              
82             #
83             # set attributes if argument given, return attribute value
84             #
85 3     3 1 12 sub module (\$) { return $_[0]->{module} }
86 1881 100   1881 1 4107 sub keysize (\$;$) { $_[0]->{keysize} = $_[1] if $_[1]; return $_[0]->{keysize} }
  1881         4384  
87 1872 100   1872 1 3491 sub blocksize (\$;$) { $_[0]->{blocksize} = $_[1] if $_[1]; return $_[0]->{blocksize} }
  1872         4148  
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 1750 my $self = shift;
96              
97 1882 100       2578 if (my $key = shift)
98             {
99 1875         1634 $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         1966 $self->{_cipherobj} = '';
104             }
105              
106 1882         4055 return $self->{key};
107             }
108              
109             #
110             # sets padding method if argument given
111             #
112             sub padding (\$;$)
113             {
114 3784     3784 1 8566 my $self = shift;
115              
116 3784 100       5840 if (my $padding = shift)
117             {
118             # if given a custom padding...
119 1916 100       2974 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         7 for my $i (0 .. $bs-1)
126             {
127 25         24 my $plain = ' ' x $i;
128              
129 25   100     28 my $padded = $padding->($plain, $bs, 'e') || '';
130 25 100       135 die "Provided padding method does not pad properly: Expected $bs bytes, got ", length $padded, ".\n"
131             unless (length $padded == $bs);
132              
133 24   100     26 my $trunc = $padding->($padded, $bs, 'd') || '';
134 24 50       147 die "Provided padding method does not truncate properly: Expected '$plain', got '$trunc'.\n"
135             unless ($trunc eq $plain);
136             }
137             }
138             }
139              
140 1915         1890 $self->{padding} = $padding;
141             }
142              
143 3783         5666 return $self->{padding};
144             }
145              
146             #
147             # sets and loads crypting module if argument given
148             #
149             sub cipher (\$;$)
150             {
151 2140     2140 1 2756626 my $self = shift;
152              
153 2140 100       3373 if (my $cipher = shift)
154             {
155 2132         1410 my $module;
156              
157             # if a cipher object is provided...
158 2132 100       2982 if (ref $cipher)
159             {
160             # ...use it
161 1         2 $self->{_cipherobj} = $cipher;
162              
163 1         1 $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       4175 $module = $cipher=~/^Crypt/ ? $cipher : "Crypt::$cipher";
173              
174 2131         91820 eval "require $module";
175 2131 100       10004 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         3067 $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       6983 unless ($module->can('blocksize')) { $module=$cipher }
  0         0  
188              
189 1879 50 33     6742 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         8134 $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       7446 $self->{keysize} = $module->can('keysize') ? $module->keysize : '';
200              
201 1879         3581 $self->{module} = $module;
202 1879         2088 $self->{cipher} = $cipher;
203             }
204              
205 1887         6176 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 3546 my $self = shift;
221 3791         2566 my $mode = shift;
222              
223             die "Not yet finished existing crypting process. Call finish() before calling start() anew.\n"
224 3791 100       5269 if $self->{_buffer};
225              
226 3790 100       8712 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       5585 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       2670 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       2174 unless $self->{module};
242              
243             # initialize cipher obj doing the actual en-/decryption
244 1871         3602 $self->{_cipherobj} = $self->{module}->new( $self->{key} );
245             }
246              
247 3787 100       16042 $self->{mode} = ($mode=~/^d/i) ? "decrypt" : "encrypt";
248              
249 3787         3487 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 2961 my $self = shift;
259 3848         2680 my $data = shift;
260            
261 3848 100 100     5219 $data = ($_ || '') unless defined $data;
262              
263 3848         2953 my $bs = $self->{blocksize};
264 3848         2950 my $mode = $self->{mode};
265              
266 3848 100       4371 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         6284 $data = $self->{_buffer}.$data;
271              
272             # data is split into blocks of proper size which is reported
273             # by the cipher module
274 3847         16205 my @blocks = $data=~/(.{1,$bs})/gs;
275              
276             # last block goes into buffer
277 3847         4213 $self->{_buffer} = pop @blocks;
278              
279 3847         4115 my ($cipher, $text) = ($self->{_cipherobj}, '');
280 3847         7279 $text .= $cipher->$mode($_) foreach (@blocks);
281 3847         17205 return $text;
282             }
283              
284             #
285             #
286             #
287             sub finish (\$)
288             {
289 3788     3788 1 3250 my $self = shift;
290              
291 3788         3338 my $bs = $self->{blocksize};
292 3788         2565 my $mode = $self->{mode};
293 3788         2946 my $data = $self->{_buffer};
294 3788         2547 my $result = '';
295              
296 3788 100       4726 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         2809 $self->{mode} = '';
302 3787         2687 $self->{_buffer} = '';
303              
304 3787 100       4762 return '' unless defined $data;
305              
306 3747         3058 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       5987 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         2938 $data = pack("a$bs",$data);
317              
318 1420         2335 $result = $cipher->$mode($data);
319 1420         7736 $result = $self->_truncate($result);
320             }
321             else
322             {
323             # if length is smaller than blocksize, just pad the block
324 2327 100       3054 if (length($data) < $bs)
325             {
326 2245         2616 $data = $self->_pad($data);
327 2243         4255 $result = $cipher->$mode($data);
328             }
329             # else append another block (depending on padding chosen)
330             else
331             {
332 82         200 $result = $cipher->$mode($data);
333 82 100       525 $self->_pad('') &&
334             ($result .= $cipher->$mode( $self->_pad('') ));
335             }
336             }
337              
338 3742         15434 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   1625 my $self = shift;
352 2376         1718 my $data = shift;
353              
354 2376         2041 my $bs = $self->{blocksize};
355 2376         1992 my $padding = $self->{padding};
356              
357 2376         2361 my $pad = $bs - length $data;
358              
359 2376         4113 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     7764 $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         3478 return $data;
375             }
376              
377             #
378             # truncates result to correct length
379             #
380             sub _truncate (\$$)
381             {
382 1420     1420   1109 my $self = shift;
383 1420         1074 my $data = shift;
384              
385 1420         1109 my $bs = $self->{blocksize};
386 1420         1138 my $padding = $self->{padding};
387              
388 1420 100       2545 if ($padding =~ /^(standard|zeroes|random)$/)
389             {
390 561         769 my $trunc = ord(substr $data, -1);
391              
392 561 100       810 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       1268 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       904 die "Block doesn't look $padding padded.\n" unless $expected eq substr($data, -$trunc);
400              
401 559         669 substr($data, -$trunc) = '';
402             }
403             else
404             {
405 859 100       3576 $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         1979 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   2847 my ($mode, $self, $key, $cipher, $data, $padding);
430              
431 3784 100       4728 if (ref $_[1])
432             {
433 1924         2921 ($mode, $self, $data) = @_;
434             }
435             else
436             {
437 1860         3341 ($mode, $key, $cipher, $data, $padding) = @_;
438              
439 1860         3343 $self = __PACKAGE__->new($key => $cipher);
440 1860 50       3915 $self->padding($padding) if $padding;
441              
442 1860 100       2700 $data = $_ unless length($data);
443             }
444              
445 3784         5190 $self->start($mode);
446 3784         4981 my $text = $self->crypt($data) . $self->finish;
447              
448 3779         12244 return $text;
449             }
450              
451             #
452             # convenience encrypt and decrypt functions/methods
453             #
454 2350     2350 1 101943 sub encrypt ($$;$$) { _crypt('encrypt', @_) }
455 1434     1434 1 99917 sub decrypt ($$;$$) { _crypt('decrypt', @_) }
456              
457             #
458             # calls encrypt, returns hex packed data
459             #
460             sub encrypt_hex ($$;$$)
461             {
462 1396 100   1396 1 175235 if (ref $_[0])
463             {
464 931         857 my $self = shift;
465 931         1238 join('',unpack('H*',$self->encrypt(shift)));
466             }
467             else
468             {
469 465         750 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 100266 if (ref $_[0])
479             {
480 468         340 my $self = shift;
481 468         1062 $self->decrypt(pack('H*',shift));
482             }
483             else
484             {
485 465         1822 decrypt($_[0], $_[1], pack('H*',$_[2]), $_[3]);
486             }
487             }
488              
489              
490             ########################################
491             # finally, to satisfy require
492             ########################################
493              
494             'The End...';
495             __END__