pan
August 17, 2019, 4:57pm
#1
Which hashing algorithm does mastodon use for passwords? And where in the source code would I go to change it? For instance if I wanted to use PBKDF2 or SHA256
saper
August 28, 2019, 7:19pm
#2
I think we are using Devise and it’s devise-two-factor module:
def valid?
super && ::Devise.pam_authentication
end
end
end
Devise.setup do |config|
config.warden do |manager|
manager.default_strategies(scope: :user).unshift :ldap_authenticatable if Devise.ldap_authentication
manager.default_strategies(scope: :user).unshift :pam_authenticatable if Devise.pam_authentication
manager.default_strategies(scope: :user).unshift :two_factor_authenticatable
manager.default_strategies(scope: :user).unshift :two_factor_backupable
end
# The secret key used by Devise. Devise uses this key to generate
# random tokens. Changing this key will render invalid all existing
# confirmation, reset password and unlock tokens in the database.
# Devise will use the `secret_key_base` on Rails 4+ applications as its `secret_key`
# by default. You can change it below and use your own secret key.
# config.secret_key = '2f86974c4dd7735170fd70fbf399f7a477ffd635ef240d07a22cf4bd7cd13dbae17c4383a2996d0c1e79a991ec18a91a17424c53e4771adb75a8b21904bd1403'
which uses, among others, Devise’s standard database authentication:
module Devise
module Strategies
class TwoFactorAuthenticatable < Devise::Strategies::DatabaseAuthenticatable
def authenticate!
resource = mapping.to.find_for_database_authentication(authentication_hash)
# We authenticate in two cases:
# 1. The password and the OTP are correct
# 2. The password is correct, and OTP is not required for login
# We check the OTP, then defer to DatabaseAuthenticatable
if validate(resource) { validate_otp(resource) }
super
end
That component has a useful comment:
which seems to lead to the code that uses bcrypt
# frozen_string_literal: true
require 'bcrypt'
module Devise
module Encryptor
def self.digest(klass, password)
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
::BCrypt::Password.create(password, cost: klass.stretches).to_s
end
def self.compare(klass, hashed_password, password)
return false if hashed_password.blank?
bcrypt = ::BCrypt::Password.new(hashed_password)
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
Devise.secure_compare(password, hashed_password)