summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/mfa.ex2
-rw-r--r--lib/pleroma/password/pbkdf2.ex55
-rw-r--r--lib/pleroma/user.ex2
-rw-r--r--lib/pleroma/web/plugs/authentication_plug.ex2
4 files changed, 58 insertions, 3 deletions
diff --git a/lib/pleroma/mfa.ex b/lib/pleroma/mfa.ex
index f43e03a54..02dce7d49 100644
--- a/lib/pleroma/mfa.ex
+++ b/lib/pleroma/mfa.ex
@@ -71,7 +71,7 @@ defmodule Pleroma.MFA do
@spec generate_backup_codes(User.t()) :: {:ok, list(binary)} | {:error, String.t()}
def generate_backup_codes(%User{} = user) do
with codes <- BackupCodes.generate(),
- hashed_codes <- Enum.map(codes, &Pbkdf2.hash_pwd_salt/1),
+ hashed_codes <- Enum.map(codes, &Pleroma.Password.Pbkdf2.hash_pwd_salt/1),
changeset <- Changeset.cast_backup_codes(user, hashed_codes),
{:ok, _} <- User.update_and_set_cache(changeset) do
{:ok, codes}
diff --git a/lib/pleroma/password/pbkdf2.ex b/lib/pleroma/password/pbkdf2.ex
new file mode 100644
index 000000000..2fd5f4491
--- /dev/null
+++ b/lib/pleroma/password/pbkdf2.ex
@@ -0,0 +1,55 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Password.Pbkdf2 do
+ @moduledoc """
+ This module implements Pbkdf2 passwords in terms of Plug.Crypto.
+ """
+
+ alias Plug.Crypto.KeyGenerator
+
+ def decode64(str) do
+ str
+ |> String.replace(".", "+")
+ |> Base.decode64!(padding: false)
+ end
+
+ def encode64(bin) do
+ bin
+ |> Base.encode64(padding: false)
+ |> String.replace("+", ".")
+ end
+
+ def verify_pass(password, hash) do
+ ["pbkdf2-" <> digest, iterations, salt, hash] = String.split(hash, "$", trim: true)
+
+ salt = decode64(salt)
+
+ iterations = String.to_integer(iterations)
+
+ digest = String.to_atom(digest)
+
+ binary_hash =
+ KeyGenerator.generate(password, salt, digest: digest, iterations: iterations, length: 64)
+
+ encode64(binary_hash) == hash
+ end
+
+ def hash_pwd_salt(password, opts \\ []) do
+ salt =
+ Keyword.get_lazy(opts, :salt, fn ->
+ :crypto.strong_rand_bytes(16)
+ end)
+
+ digest = Keyword.get(opts, :digest, :sha512)
+
+ iterations =
+ Keyword.get(opts, :iterations, Pleroma.Config.get([:password, :iterations], 160_000))
+
+ binary_hash =
+ KeyGenerator.generate(password, salt, digest: digest, iterations: iterations, length: 64)
+
+ "$pbkdf2-#{digest}$#{iterations}$#{encode64(salt)}$#{encode64(binary_hash)}"
+ end
+end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index cd0c64acc..6a81adfd6 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -2187,7 +2187,7 @@ defmodule Pleroma.User do
defp put_password_hash(
%Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset
) do
- change(changeset, password_hash: Pbkdf2.hash_pwd_salt(password))
+ change(changeset, password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt(password))
end
defp put_password_hash(changeset), do: changeset
diff --git a/lib/pleroma/web/plugs/authentication_plug.ex b/lib/pleroma/web/plugs/authentication_plug.ex
index c3e13858a..8d58169cf 100644
--- a/lib/pleroma/web/plugs/authentication_plug.ex
+++ b/lib/pleroma/web/plugs/authentication_plug.ex
@@ -48,7 +48,7 @@ defmodule Pleroma.Web.Plugs.AuthenticationPlug do
end
def checkpw(password, "$pbkdf2" <> _ = password_hash) do
- Pbkdf2.verify_pass(password, password_hash)
+ Pleroma.Password.Pbkdf2.verify_pass(password, password_hash)
end
def checkpw(_password, _password_hash) do