File Coverage

blib/lib/Crypt/OpenPGP/S2k.pm
Criterion Covered Total %
statement 92 131 70.2
branch 6 20 30.0
condition 1 3 33.3
subroutine 19 27 70.3
pod 3 5 60.0
total 121 186 65.0


line stmt bran cond sub pod time code
1             package Crypt::OpenPGP::S2k;
2 10     10   215 use strict;
  10         23  
  10         419  
3 10     10   54 use warnings;
  10         21  
  10         837  
4              
5             our $VERSION = '1.19'; # VERSION
6              
7 10     10   66 use Crypt::OpenPGP::Buffer;
  10         22  
  10         365  
8 10     10   2723 use Crypt::OpenPGP::Digest;
  10         36  
  10         343  
9 10     10   74 use Crypt::OpenPGP::ErrorHandler;
  10         19  
  10         268  
10 10     10   49 use Crypt::OpenPGP::Util;
  10         18  
  10         677  
11 10     10   87 use base qw( Crypt::OpenPGP::ErrorHandler );
  10         21  
  10         8337  
12              
13             our %TYPES = (
14             0 => 'Simple',
15             1 => 'Salted',
16             3 => 'Salt_Iter',
17             );
18              
19             sub new {
20 66     66 1 156 my $class = shift;
21 66         161 my $type = shift;
22 66   33     493 $type = $TYPES{ $type } || $type;
23 66 50       217 return $class->error("Invalid type of S2k") unless $type;
24 66         252 my $pkg = join '::', __PACKAGE__, $type;
25 66         337 my $s2k = bless { }, $pkg;
26 66         313 $s2k->init(@_);
27             }
28              
29             sub parse {
30 51     51 1 197 my $class = shift;
31 51         169 my($buf) = @_;
32 51         160 my $id = $buf->get_int8;
33 51         916 my $type = $TYPES{$id};
34 51         223 $class->new($type, $buf);
35             }
36              
37 0     0 0 0 sub init { $_[0] }
38             sub generate {
39 44     44 1 100 my $s2k = shift;
40 44         147 my($passphrase, $keysize) = @_;
41 44         117 my($material, $pass) = ('', 0);
42 44         105 my $hash = $s2k->{hash};
43 44         176 while (length($material) < $keysize) {
44 79         220 my $pad = '' . chr(0) x $pass;
45 79         345 $material .= $s2k->s2k($passphrase, $pad);
46 79         577 $pass++;
47             }
48 44         344 substr($material, 0, $keysize);
49             }
50             sub set_hash {
51 0     0 0 0 my $s2k = shift;
52 0         0 my($hash_alg) = @_;
53 0 0       0 $s2k->{hash} = ref($hash_alg) ? $hash_alg :
54             Crypt::OpenPGP::Digest->new($hash_alg);
55             }
56              
57             package Crypt::OpenPGP::S2k::Simple;
58 10     10   89 use base qw( Crypt::OpenPGP::S2k );
  10         34  
  10         1439  
59              
60 10     10   69 use Crypt::OpenPGP::Constants qw( DEFAULT_DIGEST );
  10         44  
  10         102  
61              
62             sub init {
63 0     0   0 my $s2k = shift;
64 0         0 my($buf) = @_;
65 0 0       0 if ($buf) {
66 0         0 $s2k->{hash_alg} = $buf->get_int8;
67             }
68             else {
69 0         0 $s2k->{hash_alg} = DEFAULT_DIGEST;
70             }
71 0 0       0 if ($s2k->{hash_alg}) {
72 0         0 $s2k->{hash} = Crypt::OpenPGP::Digest->new($s2k->{hash_alg});
73             }
74 0         0 $s2k;
75             }
76              
77 0     0   0 sub s2k { $_[0]->{hash}->hash($_[2] . $_[1]) }
78              
79             sub save {
80 0     0   0 my $s2k = shift;
81 0         0 my $buf = Crypt::OpenPGP::Buffer->new;
82 0         0 $buf->put_int8(1);
83 0         0 $buf->put_int8($s2k->{hash_alg});
84 0         0 $buf->bytes;
85             }
86              
87             package Crypt::OpenPGP::S2k::Salted;
88 10     10   196 use base qw( Crypt::OpenPGP::S2k );
  10         25  
  10         1206  
89              
90 10     10   90 use Crypt::OpenPGP::Constants qw( DEFAULT_DIGEST );
  10         20  
  10         74  
91              
92             sub init {
93 0     0   0 my $s2k = shift;
94 0         0 my($buf) = @_;
95 0 0       0 if ($buf) {
96 0         0 $s2k->{hash_alg} = $buf->get_int8;
97 0         0 $s2k->{salt} = $buf->get_bytes(8);
98             }
99             else {
100 0         0 $s2k->{hash_alg} = DEFAULT_DIGEST;
101 0         0 $s2k->{salt} = Crypt::OpenPGP::Util::get_random_bytes(8);
102             }
103 0 0       0 if ($s2k->{hash_alg}) {
104 0         0 $s2k->{hash} = Crypt::OpenPGP::Digest->new($s2k->{hash_alg});
105             }
106 0         0 $s2k;
107             }
108              
109 0     0   0 sub s2k { $_[0]->{hash}->hash($_[0]->{salt} . $_[2] . $_[1]) }
110              
111             sub save {
112 0     0   0 my $s2k = shift;
113 0         0 my $buf = Crypt::OpenPGP::Buffer->new;
114 0         0 $buf->put_int8(2);
115 0         0 $buf->put_int8($s2k->{hash_alg});
116 0         0 $buf->put_bytes($s2k->{salt});
117 0         0 $buf->bytes;
118             }
119              
120             package Crypt::OpenPGP::S2k::Salt_Iter;
121 10     10   85 use base qw( Crypt::OpenPGP::S2k );
  10         44  
  10         1373  
122              
123 10     10   78 use Crypt::OpenPGP::Constants qw( DEFAULT_DIGEST );
  10         21  
  10         83  
124              
125             sub init {
126 66     66   154 my $s2k = shift;
127 66         201 my($buf) = @_;
128 66 100       257 if ($buf) {
129 51         193 $s2k->{hash_alg} = $buf->get_int8;
130 51         1031 $s2k->{salt} = $buf->get_bytes(8);
131 51         1810 $s2k->{count} = $buf->get_int8;
132             }
133             else {
134 15         87 $s2k->{hash_alg} = DEFAULT_DIGEST;
135 15         79 $s2k->{salt} = Crypt::OpenPGP::Util::get_random_bytes(8);
136 15         1485 $s2k->{count} = 96;
137             }
138 66 50       1043 if ($s2k->{hash_alg}) {
139 66         466 $s2k->{hash} = Crypt::OpenPGP::Digest->new($s2k->{hash_alg});
140             }
141 66         398 $s2k;
142             }
143              
144             sub s2k {
145 79     79   211 my $s2k = shift;
146 79         267 my($pass, $pad) = @_;
147 79         225 my $salt = $s2k->{salt};
148 79         314 my $count = (16 + ($s2k->{count} & 15)) << (($s2k->{count} >> 4) + 6);
149 79         158 my $len = length($pass) + 8;
150 79 50       246 if ($count < $len) {
151 0         0 $count = $len;
152             }
153 79         147 my $res = $pad;
154 79         194 while ($count > $len) {
155 407239         547207 $res .= $salt . $pass;
156 407239         703717 $count -= $len;
157             }
158 79 50       353 if ($count < 8) {
159 79         239 $res .= substr($salt, 0, $count);
160             } else {
161 0         0 $res .= $salt;
162 0         0 $count -= 8;
163 0         0 $res .= substr($pass, 0, $count);
164             }
165 79         970 $s2k->{hash}->hash($res);
166             }
167              
168             sub save {
169 11     11   28 my $s2k = shift;
170 11         52 my $buf = Crypt::OpenPGP::Buffer->new;
171 11         105 $buf->put_int8(3);
172 11         95 $buf->put_int8($s2k->{hash_alg});
173 11         119 $buf->put_bytes($s2k->{salt});
174 11         142 $buf->put_int8($s2k->{count});
175 11         81 $buf->bytes;
176             }
177              
178             1;
179             __END__