Revision c157c911
Von Moritz Bunkus vor fast 9 Jahren hinzugefügt
SL/Auth/Password.pm | ||
---|---|---|
5 | 5 |
use Carp; |
6 | 6 |
use Digest::MD5 (); |
7 | 7 |
use Digest::SHA (); |
8 |
use Encode (); |
|
9 |
use PBKDF2::Tiny (); |
|
10 |
|
|
11 |
sub hash_pkkdf2 { |
|
12 |
my ($class, %params) = @_; |
|
13 |
|
|
14 |
# PBKDF2::Tiny expects data to be in octets. Therefore we must |
|
15 |
# encode everything we hand over (login, password) to UTF-8. |
|
16 |
|
|
17 |
# This hash method uses a random hash and not just the user's login |
|
18 |
# for its salt. This is due to the official recommendation that at |
|
19 |
# least eight octets of random data should be used. Therefore we |
|
20 |
# must store the salt together with the hashed password. The format |
|
21 |
# in the database is: |
|
22 |
|
|
23 |
# {PBKDF2}salt-in-hex:hash-in-hex |
|
24 |
|
|
25 |
my $salt; |
|
26 |
|
|
27 |
if ((defined $params{stored_password}) && ($params{stored_password} =~ m/^\{PBKDF2\} ([0-9a-f]+) :/x)) { |
|
28 |
$salt = (split m{:}, Encode::encode('utf-8', $1), 2)[0]; |
|
29 |
|
|
30 |
} else { |
|
31 |
my @login = map { ord } split m{}, Encode::encode('utf-8', $params{login}); |
|
32 |
my @random = map { int(rand(256)) } (0..16); |
|
33 |
|
|
34 |
$salt = join '', map { sprintf '%02x', $_ } @login, @random; |
|
35 |
} |
|
36 |
|
|
37 |
my $hashed = "{PBKDF2}${salt}:" . join('', map { sprintf '%02x', ord } split m{}, PBKDF2::Tiny::derive('SHA-256', $salt, Encode::encode('utf-8', $params{password}))); |
|
38 |
|
|
39 |
return $hashed; |
|
40 |
} |
|
8 | 41 |
|
9 | 42 |
sub hash { |
10 | 43 |
my ($class, %params) = @_; |
11 | 44 |
|
12 |
$params{algorithm} ||= 'SHA256S';
|
|
45 |
$params{algorithm} ||= 'PBKDF2';
|
|
13 | 46 |
|
14 | 47 |
my $salt = $params{algorithm} =~ m/S$/ ? $params{login} : ''; |
15 | 48 |
|
... | ... | |
25 | 58 |
} elsif ($params{algorithm} eq 'CRYPT') { |
26 | 59 |
return '{CRYPT}' . crypt($params{password}, substr($params{login}, 0, 2)); |
27 | 60 |
|
61 |
} elsif ($params{algorithm} =~ m/^PBKDF2/) { |
|
62 |
return $class->hash_pkkdf2(password => $params{password}, stored_password => $params{stored_password}); |
|
63 |
|
|
28 | 64 |
} else { |
29 | 65 |
croak 'Unsupported hash algorithm ' . $params{algorithm}; |
30 | 66 |
} |
Auch abrufbar als: Unified diff
Passwörter: Hash-Verfahren PBKDF2 unterstützen und als Standard nutzen
Der aktuelle Stand der Technik sind die SHA-*-Varianten schon lange
nicht mehr. In der Zwischenzeit wurden der PBKDF2-Mechanismus
entwickelt, um schnelles Berechnen zu erschweren. Noch neuer und in
ASICs noch schwerer umsetzbar sind BCrypt und SCrypt, für die es aber
noch keine weit verbreiteten Perl-Module gibt.