Class: CryptCheckpass::PBKDF2
- Inherits:
-
CryptCheckpass
- Object
- CryptCheckpass
- CryptCheckpass::PBKDF2
- Extended by:
- PHCStringFormat
- Defined in:
- lib/crypt_checkpass/pbkdf2.rb
Overview
PBKDF2 is the most beloved algorithm by security professionals.
Newhash:
You can use crypto_newhash
to create a new password hash using PBKDF2:
crypt_newhash(password, id: 'pbkdf2-sha1', rounds: 1024)
where:
password
is the raw binary password that you want to digest.id
is "pbkdf2-digest". You can specify sha1 / sha256 / sha512. Unlike plain SHA1, PBKDF2 + SHA1 combination still has no known weakness as of writing so specifying pbkdf-sha1 should just suffice normally.rounds
is for iteration rounds.
The generated password hash has following format.
Format:
This algorithm does not have a standard hash format. Here we follow npm's @phc/pbkdf2.
%r{
(?<id> pbkdf2-[\w\d]+ ){0}
(?<i> i=[1-9][0-9]* ){0}
(?<salt> [a-zA-Z0-9+/]* ){0}
(?<csum> [a-zA-Z0-9+/]* ){0}
\A [$] \g<id>
[$] \g<i>
[$] \g<salt>
[$] \g<csum>
\z
}x
This is a strict PHC string format. See also PHCStringFormat
The
id
can either be "pbkdf2-sha1", "pbkdf2-sha256", or "pbkdf2-sha512".The only parameter
i
is the iteration (rounds) of the calculation.
Other formats:
Python Passlib generates something different, in the same $pbkdf2-{digest}$
id. Passlib's and @phc/pbkdf2's are distinguishable because Passlib does not
follow PHC String Format.
Class Method Summary collapse
-
.checkpass?(pass, hash) ⇒ true, false
Checks if the given password matches the hash.
-
.newhash(pass, id: 'pbkdf2-sha1', rounds: 1024) ⇒ String
Generate a new password hash string.
-
.provide?(id) ⇒ true, false
Checks if the given ID can be handled by this class.
-
.understand?(str) ⇒ true, false
Checks if the given hash string can be handled by this class.
Methods inherited from CryptCheckpass
crypt_checkpass?, crypt_newhash
Class Method Details
.checkpass?(pass, hash) ⇒ true, false
Checks if the given password matches the hash.
110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/crypt_checkpass/pbkdf2.rb', line 110 def self.checkpass? pass, hash require 'consttime_memequal' json = phcdecode hash id = json[:id] i = json[:params][:i] salt = json[:salt] expected = json[:csum] dklen = expected.bytesize actual = __derive_key id, i, salt, pass, dklen return consttime_memequal? expected, actual end |
.newhash(pass, id: 'pbkdf2-sha1', rounds: 1024) ⇒ String
There is no way to specify salt. That's a bad idea.
Generate a new password hash string.
138 139 140 141 142 |
# File 'lib/crypt_checkpass/pbkdf2.rb', line 138 def self.newhash pass, id: 'pbkdf2-sha1', rounds: 1024 salt = SecureRandom.random_bytes 16 csum = __derive_key id, rounds, salt, pass return phcencode id, { i: rounds }, salt, csum end |
.provide?(id) ⇒ true, false
Checks if the given ID can be handled by this class. A class is free to handle several IDs, like 'argon2i', 'argon2d', ...
125 126 127 128 129 130 131 |
# File 'lib/crypt_checkpass/pbkdf2.rb', line 125 def self.provide? id case id when 'pbkdf2-sha1', 'pbkdf2-sha256', 'pbkdf2-sha512' then return true else return false end end |
.understand?(str) ⇒ true, false
Checks if the given hash string can be handled by this class.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/crypt_checkpass/pbkdf2.rb', line 94 def self.understand? str return match? str, %r{ (?<id> pbkdf2-sha(1|256|512) ){0} (?<i> i=[1-9][0-9]* ){0} (?<salt> [a-zA-Z0-9+/]* ){0} (?<csum> [a-zA-Z0-9+/]* ){0} \A [$] \g<id> [$] \g<i> [$] \g<salt> [$] \g<csum> \z }x end |