bcrypt has been a great choice for safely storing passwords. However, as time has passed, a better alternative has emerged: Argon2. OWASP now recommends Argon2 for new applications. With a little bit of code, you can use Argon2 with Devise.
Devise supports custom encryptors. However, it requires a separate column to store a salt, which isn’t needed as Argon2 stores the salt in the password hash (like bcrypt).
Instead, add argon2 to your Gemfile:
gem 'argon2', '>= 2'
And create config/initializers/devise_argon2.rb with:
module Argon2Encryptor
def digest(klass, password)
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
::Argon2::Password.create(password)
end
def compare(klass, hashed_password, password)
return false if hashed_password.blank?
if hashed_password.start_with?("$argon2")
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
::Argon2::Password.verify_password(password, hashed_password)
else
super
end
end
end
Devise::Encryptor.singleton_class.prepend(Argon2Encryptor)
All new passwords will be hashed with Argon2. For existing passwords, rotate to Argon2 when a user signs in. Add to your model:
class User < ApplicationRecord
def valid_password?(password)
valid = super
if valid && !encrypted_password.start_with?("$argon2")
self.password = password
save(validate: false)
end
valid
end
end
You can also rehash all passwords at once, but it’s a bit more complicated.
Congrats, your password storage is even stronger!
All code examples are public domain.
Use them however you’d like (licensed under CC0).

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.