Module: Veri::Password::Pbkdf2

Defined in:
lib/veri/password/pbkdf2.rb

Constant Summary collapse

ITERATIONS =
210_000
SALT_BYTES =
64
HASH_BYTES =
64
DIGEST =
"sha512"

Class Method Summary collapse

Class Method Details

.create(password) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/veri/password/pbkdf2.rb', line 15

def create(password)
  salt = SecureRandom.random_bytes(SALT_BYTES)
  hash = OpenSSL::KDF.pbkdf2_hmac(
    password,
    salt:,
    iterations: ITERATIONS,
    length: HASH_BYTES,
    hash: DIGEST
  )

  "#{DIGEST}$#{ITERATIONS}$#{HASH_BYTES}$#{Base64.strict_encode64(salt)}$#{Base64.strict_encode64(hash)}"
end

.match?(hashed_password) ⇒ Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/veri/password/pbkdf2.rb', line 46

def match?(hashed_password)
  hashed_password.start_with?("#{DIGEST}$")
end

.verify(password, hashed_password) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/veri/password/pbkdf2.rb', line 28

def verify(password, hashed_password)
  parts = hashed_password.split("$")
  digest, iterations, hash_bytes, encoded_salt, encoded_hash = parts[0], parts[1], parts[2], parts[3], parts[4]

  salt = Base64.strict_decode64(encoded_salt)
  hash = Base64.strict_decode64(encoded_hash)

  recalculated_hash = OpenSSL::KDF.pbkdf2_hmac(
    password,
    salt:,
    iterations: iterations.to_i,
    length: hash_bytes.to_i,
    hash: digest
  )

  OpenSSL.fixed_length_secure_compare(recalculated_hash, hash)
end