开发者

Verifying salted hashes with Perls unpack()

开发者 https://www.devze.com 2023-01-31 09:59 出处:网络
I\'m trying to verify salted passwords with Perl and am stuck with unpack. I\'ve got a salted hashed password, e.g. for SHA256: SSHA256 = SHA256(\'password\' + \'salt\') + \'salt\'

I'm trying to verify salted passwords with Perl and am stuck with unpack.

I've got a salted hashed password, e.g. for SHA256: SSHA256 = SHA256('password' + 'salt') + 'salt' Base64 encoded that gets ' {SSHA256}eje4XIkY6sGakInA+loqtNzj+QUo3N7sEIsj3fNge5lzYWx0'.

I store this string in my user database. When a user logs in need to separate t开发者_如何学Che salt from the hash to hash the supplied password with the salt and compare the result to the one retrieved from the db. This is where I'm stuck. I don't seem to have the right unpack template separate the hash (8-bit binary, fixed length, in this case 32 byte) from the salt (8-bit binary, variable length).

I have tried something like

my ($hash, $salt) = unpack('N32 N*', $data);

but that doesn't seem to work out.

My question is: How can I unpack this hash (after it has been Base64 decoded) to get the fixed length hash in one and the variable length salt in another variable?


I think you're needlessly re-inventing the wheel.

You could use e.g. Crypt::SaltedHash to easily verify it, for instance:

my $password_entered = $cgi->param('password');
my $valid = Crypt::SaltedHash->validate($salted, $password_entered);

A longer example, showing using Crypt::SaltedHash to generate the salted password in the first instance, too:

my $csh = Crypt::SaltedHash->new(algorithm => 'SHA-256');
$csh->add('secretpassword');
my $salted =  $csh->generate;
# $salted will contain the salted hash (Crypt::SaltedHash picks random
# salt for you automatically)

# for example:
  DB x $salted = $csh->generate;
0  '{SSHA256}H1WaxHcyAB81iyIPwib/cCUtjqCm2sxQNA1QvGeh/iT3m51w'

# validating that against the plaintext 'secretpassword' shows it's right:
  DB x Crypt::SaltedHash->validate($salted, 'secretpassword');
0  1

# and trying it with an incorrect password:
  DB x Crypt::SaltedHash->validate($salted, 'wrongpassword');
0  ''

No reason to re-invent all of this yourself.


You seem to be doing RFC2307 the hard way and also manage to introduce bugs. Those + do not mean what you think.

Subclass Authen::Passphrase::SaltedDigest instead.


Not sure the whole picture is present, but the unpack template you have specified -'N32 N*'- is for 32 unsigned long (32-bit) (big-endian) integers (see pack docs).

Looks like you may instead need unsigned chars: '32C C*'

0

精彩评论

暂无评论...
验证码 换一张
取 消