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   1502667 use strict;
  13         30  
  13         536  
12 13     13   62 use warnings;
  13         23  
  13         774  
13              
14 13     13   77 use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
  13         21  
  13         37963  
15              
16             require Exporter;
17              
18             @ISA = qw(Exporter);
19             @EXPORT_OK = qw(encrypt decrypt encrypt_hex decrypt_hex);
20             $VERSION = '2.23';
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 2335033 my $class = shift;
33              
34 1879         11297 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         4486 bless $self, $class;
49              
50 1879 100       3981 if ($_[0])
51             {
52 1868         2403 my $options;
53              
54             # options Crypt::CBC style
55 1868 100       5119 if ($_[0] =~ /^-[a-zA-Z]+$/)
    100          
56             {
57 6         22 my %tmp = @_;
58 6         43 $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         4303 $options->{key} = shift;
71 1861   50     3851 $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         6205 $self->$_( $options->{$_} ) foreach qw(cipher keysize key blocksize padding);
77             }
78              
79 1879         3670 return $self;
80             }
81              
82             #
83             # set attributes if argument given, return attribute value
84             #
85 3     3 1 13 sub module (\$) { return $_[0]->{module} }
86 1881 100   1881 1 8449 sub keysize (\$;$) { $_[0]->{keysize} = $_[1] if $_[1]; return $_[0]->{keysize} }
  1881         6470  
87 1872 100   1872 1 4335 sub blocksize (\$;$) { $_[0]->{blocksize} = $_[1] if $_[1]; return $_[0]->{blocksize} }
  1872         4938  
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 2650 my $self = shift;
96              
97 1882 100       4175 if (my $key = shift)
98             {
99 1875         2620 $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         2784 $self->{_cipherobj} = '';
104             }
105              
106 1882         5563 return $self->{key};
107             }
108              
109             #
110             # sets padding method if argument given
111             #
112             sub padding (\$;$)
113             {
114 3784     3784 1 14089 my $self = shift;
115              
116 3784 100       7563 if (my $padding = shift)
117             {
118             # if given a custom padding...
119 1916 100       3782 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         28 for my $i (0 .. $bs-1)
126             {
127 25         35 my $plain = ' ' x $i;
128              
129 25   100     38 my $padded = $padding->($plain, $bs, 'e') || '';
130 25 100       173 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       157 die "Provided padding method does not truncate properly: Expected '$plain', got '$trunc'.\n"
135             unless ($trunc eq $plain);
136             }
137             }
138             }
139              
140 1915         3189 $self->{padding} = $padding;
141             }
142              
143 3783         11608 return $self->{padding};
144             }
145              
146             #
147             # sets and loads crypting module if argument given
148             #
149             sub cipher (\$;$)
150             {
151 2128     2128 1 27280132 my $self = shift;
152              
153 2128 100       5173 if (my $cipher = shift)
154             {
155 2120         2825 my $module;
156              
157             # if a cipher object is provided...
158 2120 100       4163 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 2119 50       5479 $module = $cipher=~/^Crypt/ ? $cipher : "Crypt::$cipher";
173              
174 2119         136414 eval "require $module";
175 2119 100       15744 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         4327 $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       9978 unless ($module->can('blocksize')) { $module=$cipher }
  0         0  
188              
189 1879 50 33     8280 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         8715 $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       10242 $self->{keysize} = $module->can('keysize') ? $module->keysize : '';
200              
201 1879         6050 $self->{module} = $module;
202 1879         3127 $self->{cipher} = $cipher;
203             }
204              
205 1887         7943 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 7166 my $self = shift;
221 3791         5508 my $mode = shift;
222              
223             die "Not yet finished existing crypting process. Call finish() before calling start() anew.\n"
224 3791 100       8006 if $self->{_buffer};
225              
226 3790 100       12376 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       8400 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       4812 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       3304 unless $self->{module};
242              
243             # initialize cipher obj doing the actual en-/decryption
244 1871         5008 $self->{_cipherobj} = $self->{module}->new( $self->{key} );
245             }
246              
247 3787 100       28628 $self->{mode} = ($mode=~/^d/i) ? "decrypt" : "encrypt";
248              
249 3787         5943 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 5895 my $self = shift;
259 3848         5238 my $data = shift;
260            
261 3848 100 100     11603 $data = ($_ || '') unless defined $data;
262              
263 3848         6648 my $bs = $self->{blocksize};
264 3848         5265 my $mode = $self->{mode};
265              
266 3848 100       6524 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         7364 $data = $self->{_buffer}.$data;
271              
272             # data is split into blocks of proper size which is reported
273             # by the cipher module
274 3847         37316 my @blocks = $data=~/(.{1,$bs})/gs;
275              
276             # last block goes into buffer
277 3847         18615 $self->{_buffer} = pop @blocks;
278              
279 3847         7534 my ($cipher, $text) = ($self->{_cipherobj}, '');
280 3847         10343 $text .= $cipher->$mode($_) foreach (@blocks);
281 3847         29540 return $text;
282             }
283              
284             #
285             #
286             #
287             sub finish (\$)
288             {
289 3788     3788 1 8768 my $self = shift;
290              
291 3788         5330 my $bs = $self->{blocksize};
292 3788         5555 my $mode = $self->{mode};
293 3788         5610 my $data = $self->{_buffer};
294 3788         5056 my $result = '';
295              
296 3788 100       6602 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         5497 $self->{mode} = '';
302 3787         10682 $self->{_buffer} = '';
303              
304 3787 100       6422 return '' unless defined $data;
305              
306 3747         5509 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       8558 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         7566 $data = pack("a$bs",$data);
317              
318 1420         9618 $result = $cipher->$mode($data);
319 1420         14437 $result = $self->_truncate($result);
320             }
321             else
322             {
323             # if length is smaller than blocksize, just pad the block
324 2327 100       4681 if (length($data) < $bs)
325             {
326 2245         4289 $data = $self->_pad($data);
327 2243         6338 $result = $cipher->$mode($data);
328             }
329             # else append another block (depending on padding chosen)
330             else
331             {
332 82         375 $result = $cipher->$mode($data);
333 82 100       1038 $self->_pad('') &&
334             ($result .= $cipher->$mode( $self->_pad('') ));
335             }
336             }
337              
338 3742         26714 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   3242 my $self = shift;
352 2376         7163 my $data = shift;
353              
354 2376         3204 my $bs = $self->{blocksize};
355 2376         3369 my $padding = $self->{padding};
356              
357 2376         3483 my $pad = $bs - length $data;
358              
359 2376         4943 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     9949 $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         5425 return $data;
375             }
376              
377             #
378             # truncates result to correct length
379             #
380             sub _truncate (\$$)
381             {
382 1420     1420   2013 my $self = shift;
383 1420         1943 my $data = shift;
384              
385 1420         2133 my $bs = $self->{blocksize};
386 1420         2804 my $padding = $self->{padding};
387              
388 1420 100       4237 if ($padding =~ /^(standard|zeroes|random)$/)
389             {
390 561         1271 my $trunc = ord(substr $data, -1);
391              
392 561 100       1231 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       2370 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       1340 die "Block doesn't look $padding padded.\n" unless $expected eq substr($data, -$trunc);
400              
401 559         1112 substr($data, -$trunc) = '';
402             }
403             else
404             {
405 859 100       5519 $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         3339 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   6272 my ($mode, $self, $key, $cipher, $data, $padding);
430              
431 3784 100       7208 if (ref $_[1])
432             {
433 1924         4390 ($mode, $self, $data) = @_;
434             }
435             else
436             {
437 1860         4262 ($mode, $key, $cipher, $data, $padding) = @_;
438              
439 1860         4465 $self = __PACKAGE__->new($key => $cipher);
440 1860 50       4925 $self->padding($padding) if $padding;
441              
442 1860 100       6018 $data = $_ unless length($data);
443             }
444              
445 3784         8821 $self->start($mode);
446 3784         7137 my $text = $self->crypt($data) . $self->finish;
447              
448 3779         20402 return $text;
449             }
450              
451             #
452             # convenience encrypt and decrypt functions/methods
453             #
454 2350     2350 1 157691 sub encrypt ($$;$$) { _crypt('encrypt', @_) }
455 1434     1434 1 159531 sub decrypt ($$;$$) { _crypt('decrypt', @_) }
456              
457             #
458             # calls encrypt, returns hex packed data
459             #
460             sub encrypt_hex ($$;$$)
461             {
462 1396 100   1396 1 343449 if (ref $_[0])
463             {
464 931         1608 my $self = shift;
465 931         2363 join('',unpack('H*',$self->encrypt(shift)));
466             }
467             else
468             {
469 465         1009 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 151335 if (ref $_[0])
479             {
480 468         804 my $self = shift;
481 468         2090 $self->decrypt(pack('H*',shift));
482             }
483             else
484             {
485 465         2291 decrypt($_[0], $_[1], pack('H*',$_[2]), $_[3]);
486             }
487             }
488              
489              
490             ########################################
491             # finally, to satisfy require
492             ########################################
493              
494             'The End...';
495             __END__