line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Authen::Passphrase::Argon2; |
2
|
|
|
|
|
|
|
|
3
|
6
|
|
|
6
|
|
411889
|
use 5.014; |
|
6
|
|
|
|
|
69
|
|
4
|
6
|
|
|
6
|
|
35
|
use strict; |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
137
|
|
5
|
6
|
|
|
6
|
|
35
|
use warnings; |
|
6
|
|
|
|
|
15
|
|
|
6
|
|
|
|
|
274
|
|
6
|
6
|
|
|
6
|
|
2954
|
use Crypt::Argon2 qw/argon2id_pass argon2id_verify/; |
|
6
|
|
|
|
|
3367
|
|
|
6
|
|
|
|
|
372
|
|
7
|
6
|
|
|
6
|
|
2873
|
use MIME::Base64 qw(decode_base64 encode_base64); |
|
6
|
|
|
|
|
4037
|
|
|
6
|
|
|
|
|
387
|
|
8
|
6
|
|
|
6
|
|
2991
|
use Data::GUID; |
|
6
|
|
|
|
|
112601
|
|
|
6
|
|
|
|
|
39
|
|
9
|
6
|
|
|
6
|
|
1260
|
use Carp qw/croak/; |
|
6
|
|
|
|
|
16
|
|
|
6
|
|
|
|
|
328
|
|
10
|
6
|
|
|
6
|
|
3227
|
use Syntax::Construct qw( ?<> /a ); |
|
6
|
|
|
|
|
9490
|
|
|
6
|
|
|
|
|
38
|
|
11
|
|
|
|
|
|
|
|
12
|
6
|
|
|
6
|
|
3571
|
use parent 'Authen::Passphrase'; |
|
6
|
|
|
|
|
1729
|
|
|
6
|
|
|
|
|
36
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
our $VERSION = '0.08'; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our (%salts, %hashes, @argons); |
17
|
|
|
|
|
|
|
BEGIN { |
18
|
6
|
|
|
6
|
|
41
|
@argons = ( |
19
|
|
|
|
|
|
|
['salt'], |
20
|
|
|
|
|
|
|
[qw/cost 3/], |
21
|
|
|
|
|
|
|
[qw/factor 32M/], |
22
|
|
|
|
|
|
|
[qw/parallelism 1/], |
23
|
|
|
|
|
|
|
[qw/size 16/] |
24
|
|
|
|
|
|
|
); |
25
|
|
|
|
|
|
|
%salts = ( |
26
|
|
|
|
|
|
|
salt => sub { |
27
|
16
|
100
|
|
|
|
54
|
$_[0] = $salts{salt_random}() if "$_[0]" eq 'random'; |
28
|
16
|
100
|
|
|
|
1255
|
$_[0] =~ m#\A[\x00-\xff]{6}.*\z# |
29
|
|
|
|
|
|
|
or croak sprintf("%s is not a valid raw salt", $_[0]); |
30
|
13
|
|
|
|
|
44
|
$_[0]; |
31
|
|
|
|
|
|
|
}, |
32
|
|
|
|
|
|
|
salt_hex => sub { |
33
|
2
|
|
|
|
|
5
|
$_[0] = $salts{salt}($_[0]); |
34
|
2
|
|
|
|
|
7
|
unpack("H*", $_[0]); |
35
|
|
|
|
|
|
|
}, |
36
|
|
|
|
|
|
|
salt_base64 => sub { |
37
|
2
|
|
|
|
|
5
|
$_[0] = $salts{salt}($_[0]); |
38
|
2
|
|
|
|
|
7
|
encode_base64($_[0]); |
39
|
|
|
|
|
|
|
}, |
40
|
|
|
|
|
|
|
salt_random => sub { |
41
|
2
|
|
|
|
|
14
|
Data::GUID->new->as_string; |
42
|
|
|
|
|
|
|
}, |
43
|
6
|
|
|
|
|
58
|
); |
44
|
|
|
|
|
|
|
%hashes = ( |
45
|
|
|
|
|
|
|
hash => sub { |
46
|
15
|
100
|
|
|
|
580
|
$_[0] =~ m/^ |
47
|
|
|
|
|
|
|
\$argon2id |
48
|
|
|
|
|
|
|
\$v=\d+ |
49
|
|
|
|
|
|
|
\$m=(?\d+), |
50
|
|
|
|
|
|
|
t=(?\d+), |
51
|
|
|
|
|
|
|
p=(?\d+) |
52
|
|
|
|
|
|
|
\$ |
53
|
|
|
|
|
|
|
/ax or croak sprintf "not a valid raw hash - %s", $_[0]; |
54
|
6
|
|
|
6
|
|
30750
|
("$_[0]", %+); |
|
6
|
|
|
|
|
2776
|
|
|
6
|
|
|
|
|
898
|
|
|
11
|
|
|
|
|
196
|
|
55
|
|
|
|
|
|
|
}, |
56
|
|
|
|
|
|
|
hash_base64 => sub { |
57
|
5
|
|
|
|
|
16
|
($_[0]) = $hashes{hash}($_[0]); |
58
|
4
|
|
|
|
|
151
|
encode_base64($_[0]); |
59
|
|
|
|
|
|
|
}, |
60
|
|
|
|
|
|
|
hash_hex => sub { |
61
|
5
|
|
|
|
|
15
|
($_[0]) = $hashes{hash}($_[0]); |
62
|
4
|
|
|
|
|
35
|
unpack("H*", $_[0]); |
63
|
|
|
|
|
|
|
} |
64
|
6
|
|
|
|
|
6947
|
); |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub new { |
68
|
22
|
100
|
|
22
|
1
|
4987
|
my ($class, %args) = (shift, (scalar @_ == 1 ? %{$_[0]} : @_)); |
|
1
|
|
|
|
|
6
|
|
69
|
|
|
|
|
|
|
|
70
|
22
|
|
|
|
|
122
|
my $self = bless({ algorithm => 'Argon2' }, $class); |
71
|
|
|
|
|
|
|
|
72
|
22
|
100
|
|
|
|
83
|
$args{crypt} = delete $args{passphrase} if $args{passphrase}; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
exists $args{$_} ? ! $self->{salt} |
75
|
6
|
|
|
|
|
23
|
? do { $self->{salt} = $salts{$_}->($args{$_}) } |
76
|
|
|
|
|
|
|
: croak sprintf "salt specified redundantly - %s", $_ |
77
|
22
|
100
|
|
|
|
165
|
: next foreach (keys %salts); |
|
|
100
|
|
|
|
|
|
78
|
|
|
|
|
|
|
|
79
|
21
|
|
|
|
|
57
|
foreach (qw/hash base64 hex/) { |
80
|
63
|
100
|
|
|
|
164
|
if (exists $args{"stored_$_"}) { |
81
|
1
|
|
|
|
|
5
|
($args{"hash_$_"}) = delete $args{crypt}; |
82
|
1
|
|
|
|
|
4
|
last; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
$self->{$_->[0]} = $self->{$_->[0]} |
87
|
|
|
|
|
|
|
|| $args{$_->[0]} |
88
|
|
|
|
|
|
|
|| $_->[1] |
89
|
21
|
|
100
|
|
|
464
|
foreach @argons; |
90
|
|
|
|
|
|
|
|
91
|
21
|
100
|
|
|
|
65
|
unless ($args{crypt}) { |
92
|
|
|
|
|
|
|
exists $args{$_} ? ! $self->{crypt} |
93
|
|
|
|
|
|
|
? $self->$_($args{$_}) |
94
|
|
|
|
|
|
|
: croak sprintf "hash specified redundantly - %s", $_ |
95
|
16
|
100
|
|
|
|
79
|
: next foreach (keys %hashes); |
|
|
100
|
|
|
|
|
|
96
|
|
|
|
|
|
|
} else { |
97
|
5
|
|
|
|
|
22
|
$self->{crypt} = $self->_hash_of($args{crypt}); |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
20
|
|
|
|
|
122
|
return $self; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub match { |
104
|
10
|
|
|
10
|
1
|
40
|
my ($self, $passphrase) = @_; |
105
|
|
|
|
|
|
|
|
106
|
10
|
|
|
|
|
2317895
|
return argon2id_verify($self->{crypt}, $passphrase); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub from_crypt { |
110
|
3
|
|
|
3
|
1
|
676
|
my ($self, $crypt, $info) = (@_, {}); |
111
|
3
|
|
|
|
|
10
|
return $self->new(%{ $info }, 'passphrase', $hashes{hash}($crypt)); |
|
3
|
|
|
|
|
17
|
|
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub from_rfc2307 { |
115
|
2
|
|
|
2
|
1
|
9
|
my ( $class, $rfc2307, $info) = (@_, {}); |
116
|
|
|
|
|
|
|
|
117
|
2
|
100
|
|
|
|
246
|
croak "invalid Argon2 RFC2307 format" unless $rfc2307 =~ m/^{ARGON2}(.*)$/; |
118
|
|
|
|
|
|
|
|
119
|
1
|
|
|
|
|
5
|
return $class->from_crypt($1, $info); |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub as_crypt { |
123
|
16
|
|
|
16
|
1
|
65
|
my ($self, $val) = @_; |
124
|
|
|
|
|
|
|
|
125
|
16
|
100
|
|
|
|
68
|
$self->{crypt} = $self->_hash_of($val) if defined $val; |
126
|
|
|
|
|
|
|
|
127
|
16
|
|
|
|
|
80
|
return $self->{crypt}; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub as_hex { |
131
|
1
|
|
|
1
|
1
|
5
|
goto &hash_hex; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub as_base64 { |
135
|
1
|
|
|
1
|
1
|
7
|
goto &hash_base64; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub as_rfc2307 { |
139
|
2
|
|
|
2
|
1
|
21
|
my ($self, $val) = @_; |
140
|
|
|
|
|
|
|
|
141
|
2
|
|
|
|
|
8
|
return '{ARGON2}' . $self->as_crypt($val); |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
sub algorithm { |
145
|
2
|
|
|
2
|
1
|
20
|
my($self) = @_; |
146
|
|
|
|
|
|
|
|
147
|
2
|
|
|
|
|
15
|
return $self->{algorithm}; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub salt { |
151
|
16
|
|
|
16
|
1
|
54
|
my($self, $val) = @_; |
152
|
16
|
100
|
|
|
|
42
|
$self->{salt} = $salts{salt}($val) if $val; |
153
|
13
|
|
|
|
|
59
|
$self->{salt}; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub salt_hex { |
157
|
3
|
|
|
3
|
1
|
16
|
my($self, $val) = @_; |
158
|
3
|
100
|
|
|
|
16
|
$salts{salt_hex}($self->salt($val ? pack("H*", $val) : ())); |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub salt_base64 { |
162
|
3
|
|
|
3
|
1
|
16
|
my($self, $val) = @_; |
163
|
3
|
100
|
|
|
|
14
|
$salts{salt_base64}($self->salt($val ? decode_base64($val) : ())); |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub hash { |
167
|
8
|
|
|
8
|
1
|
38
|
my($self, $val) = @_; |
168
|
8
|
100
|
|
|
|
47
|
return $val ? $self->as_crypt($hashes{hash}($val)) : $self->{crypt}; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub hash_hex { |
172
|
5
|
|
|
5
|
1
|
25
|
my($self, $val) = @_; |
173
|
5
|
100
|
|
|
|
33
|
return $hashes{hash_hex}($self->as_crypt($val ? pack("H*", $val) : ())); |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub hash_base64 { |
177
|
5
|
|
|
5
|
1
|
21
|
my($self, $val) = @_; |
178
|
5
|
100
|
|
|
|
25
|
return $hashes{hash_base64}($self->as_crypt($val ? decode_base64($val) : ())); |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub _hash_of { |
182
|
13
|
|
|
13
|
|
39
|
my ($self, $pass, @params) = @_; |
183
|
13
|
100
|
|
|
|
68
|
return $pass if ($pass =~ m/\$argon2/); |
184
|
4
|
100
|
|
|
|
237
|
!$self->{$_->[0]} ? croak "$_->[0] not set" : push @params, $self->{$_->[0]} for @argons; |
185
|
3
|
|
|
|
|
715380
|
return argon2id_pass($pass, @params); |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
1; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
__END__ |