File Coverage

blib/lib/DBIx/Class/EncodedColumn/Digest.pm
Criterion Covered Total %
statement 40 40 100.0
branch 7 12 58.3
condition 12 17 70.5
subroutine 9 9 100.0
pod 2 2 100.0
total 70 80 87.5


line stmt bran cond sub pod time code
1             package DBIx::Class::EncodedColumn::Digest;
2              
3 2     2   7 use strict;
  2         4  
  2         61  
4 2     2   7 use warnings;
  2         3  
  2         38  
5 2     2   52 use Digest;
  2         3  
  2         883  
6              
7             our $VERSION = '0.00001';
8              
9             my %digest_lengths =
10             (
11             'MD2' => { base64 => 22, binary => 16, hex => 32 },
12             'MD4' => { base64 => 22, binary => 16, hex => 32 },
13             'MD5' => { base64 => 22, binary => 16, hex => 32 },
14              
15             'SHA-1' => { base64 => 27, binary => 20, hex => 40 },
16             'SHA-256' => { base64 => 43, binary => 32, hex => 64 },
17             'SHA-384' => { base64 => 64, binary => 48, hex => 96 },
18             'SHA-512' => { base64 => 86, binary => 64, hex => 128 },
19              
20             'CRC-CCITT' => { base64 => 2, binary => 3, hex => 3 },
21             'CRC-16' => { base64 => 6, binary => 5, hex => 4 },
22             'CRC-32' => { base64 => 14, binary => 10, hex => 8 },
23              
24             'Adler-32' => { base64 => 6, binary => 4, hex => 8 },
25             'Whirlpool' => { base64 => 86, binary => 64, hex => 128 },
26             'Haval-256' => { base64 => 44, binary => 32, hex => 64 },
27             );
28             my @salt_pool = ('A' .. 'Z', 'a' .. 'z', 0 .. 9, '+','/','=');
29              
30             sub make_encode_sub {
31 7     7 1 8 my($class, $col, $args) = @_;
32 7   100     28 my $for = $args->{format} ||= 'base64';
33 7   100     17 my $alg = $args->{algorithm} ||= 'SHA-256';
34 7   100     22 my $slen = $args->{salt_length} ||= 0;
35              
36 7 50       32 die("Valid Digest formats are 'binary', 'hex' or 'base64'. You used '$for'.")
37             unless $for =~ /^(?:hex|base64|binary)$/;
38 7 50       5 defined(my $object = eval{ Digest->new($alg) }) ||
  7         24  
39             die("Can't use Digest algorithm ${alg}: $@");
40              
41 7 100       235 my $format_method = $for eq 'binary' ? 'digest' :
    50          
42             ($for eq 'hex' ? 'hexdigest' : 'b64digest');
43             #thanks Haval for breaking the standard. thanks!
44 7 50 33     14 $format_method = 'base64digest 'if ($alg eq 'Haval-256' && $for eq 'base64');
45              
46             my $encoder = sub {
47 18     18   93 my ($plain_text, $salt) = @_;
48 18   100     84 $salt ||= join('', map { $salt_pool[int(rand(65))] } 1 .. $slen);
  28         63  
49 18         57 $object->reset()->add($plain_text.$salt);
50 18         298 my $digest = $object->$format_method;
51             #print "${plain_text}\t ${salt}:\t${digest}${salt}\n" if $salt;
52 18         80 return $digest.$salt;
53 7         24 };
54              
55             #in case i didn't prepopulate it
56 7   33     17 $digest_lengths{$alg}{$for} ||= length($encoder->('test1'));
57 7         51 return $encoder;
58             }
59              
60             sub make_check_sub {
61 5     5 1 8 my($class, $col, $args) = @_;
62              
63             #this is the digest length
64 5         9 my $len = $digest_lengths{$args->{algorithm}}{$args->{format}};
65 5 50       13 die("Unable to find digest length") unless defined $len;
66              
67             #fast fast fast
68 5   50 1   483 return eval qq^ sub {
  1     1   6  
  1     1   34  
  1         24  
  1         25337  
  1         34  
  1         25  
  1         5  
  1         36  
  1         25  
69             my \$col_v = \$_[0]->get_column('${col}');
70             my \$salt = substr(\$col_v, ${len});
71             \$_[0]->_column_encoders->{${col}}->(\$_[1], \$salt) eq \$col_v;
72             } ^ || die($@);
73             }
74              
75             1;
76              
77             __END__;