password_hash.rb 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. module PasswordHash
  3. include ApplicationLib
  4. class PasswordHash::Error < StandardError; end
  5. extend self
  6. def crypt(password)
  7. # take a fresh Argon2::Password instances to ensure randomized salt
  8. Argon2::Password.new(secret: secret).create(password)
  9. end
  10. def verified?(pw_hash, password)
  11. Argon2::Password.verify_password(password, pw_hash, secret)
  12. rescue
  13. false
  14. end
  15. def verified!(pw_hash, password)
  16. return if verified?(pw_hash, password)
  17. raise PasswordHash::Error, __('The password is invalid.')
  18. end
  19. def crypted?(pw_hash)
  20. return false if !pw_hash
  21. return true if hashed_argon2?(pw_hash)
  22. return true if hashed_sha2?(pw_hash)
  23. false
  24. end
  25. def legacy?(pw_hash, password)
  26. return false if pw_hash.blank?
  27. return false if !password
  28. return true if sha2?(pw_hash, password)
  29. return true if hashed_argon2i?(pw_hash, password)
  30. false
  31. end
  32. def hashed_sha2?(pw_hash)
  33. pw_hash.start_with?('{sha2}')
  34. end
  35. def hashed_argon2?(pw_hash)
  36. Argon2::Password.valid_hash?(pw_hash)
  37. end
  38. def hashed_argon2i?(pw_hash, password)
  39. # taken from: https://github.com/technion/ruby-argon2/blob/7e1f4a2634316e370ab84150e4f5fd91d9263713/lib/argon2.rb#L33
  40. return false if !pw_hash.match?(%r{^\$argon2i\$.{,112}})
  41. # Argon2::Password.verify_password verifies argon2i hashes, too
  42. verified?(pw_hash, password)
  43. end
  44. def sha2(password)
  45. crypted = Digest::SHA2.hexdigest(password)
  46. "{sha2}#{crypted}"
  47. end
  48. private
  49. def sha2?(pw_hash, password)
  50. return false if !hashed_sha2?(pw_hash)
  51. pw_hash == sha2(password)
  52. end
  53. def secret
  54. @secret ||= Setting.get('application_secret')
  55. end
  56. end