defmodule Pleroma.Password do @moduledoc """ This module handles password hashing and verification. It will delegate to the appropriate module based on the password hash. It also handles upgrading of password hashes. """ alias Pleroma.User alias Pleroma.Password.Pbkdf2 require Logger @hashing_module Argon2 @spec hash_pwd_salt(String.t()) :: String.t() defdelegate hash_pwd_salt(pass), to: @hashing_module @spec checkpw(String.t(), String.t()) :: boolean() def checkpw(password, "$2" <> _ = password_hash) do # Handle bcrypt passwords for Mastodon migration Bcrypt.verify_pass(password, password_hash) end def checkpw(password, "$pbkdf2" <> _ = password_hash) do Pbkdf2.verify_pass(password, password_hash) end def checkpw(password, "$argon2" <> _ = password_hash) do Argon2.verify_pass(password, password_hash) end def checkpw(_password, _password_hash) do Logger.error("Password hash not recognized") false end @spec maybe_update_password(User.t(), String.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} def maybe_update_password(%User{password_hash: "$2" <> _} = user, password) do do_update_password(user, password) end def maybe_update_password(%User{password_hash: "$6" <> _} = user, password) do do_update_password(user, password) end def maybe_update_password(%User{password_hash: "$pbkdf2" <> _} = user, password) do do_update_password(user, password) end def maybe_update_password(user, _), do: {:ok, user} defp do_update_password(user, password) do User.reset_password(user, %{password: password, password_confirmation: password}) end end