password_hash.rb 1.5 KB

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