Created
December 30, 2018 13:01
-
-
Save rhbvkleef/f44c4b70f9a064b5480ffa613fe73dc5 to your computer and use it in GitHub Desktop.
A concept for improving the usability of Comeonin. It may be a good idea to make the hashing modules check the requirements for rehashing so that algorithm-specific settings can be checked as well. This is just a concept for what I would like to see added in comeonin.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Comeonin.Auto do | |
if Application.get_env(:comeonin, :hash_algo) == Plain do | |
:elixir_errors.warn __ENV__.line, __ENV__.file, | |
"You are using the plain hashing algorithm! This results in passwords being plainly visible in the database! DO NOT USE THIS IN PRODUCTION!" | |
end | |
defp get_hash_mod hash do | |
cond do | |
String.starts_with?(hash, "$plain") -> Comeonin.Plain | |
String.starts_with?(hash, "$argon2") -> Comeonin.Argon2 | |
String.starts_with?(hash, "$2") -> Comeonin.Bcrypt | |
String.starts_with?(hash, "$pbkdf2") -> Comeonin.Pbkdf2 | |
end | |
end | |
defp algo do | |
Module.concat(Comeonin, Application.get_env(:comeonin, :hash_algo)) | |
end | |
def passwd_hash pass, opts \\ [] do | |
algo().hashpwsalt pass, opts | |
end | |
def passwd_verify hash, pass, opts \\ [] do | |
get_hash_mod(hash).checkpw pass, hash, opts | |
end | |
def dummy_passwd_verify opts \\ [] do | |
get_hash_mod(hash).dummy_checkpw opts | |
end | |
def needs_rehash hash do | |
get_hash_mod(hash) != algo() | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Comeonin.Plain do | |
defp get_hash(%{password_hash: hash}, nil), do: {:ok, hash} | |
defp get_hash(%{encrypted_password: hash}, nil), do: {:ok, hash} | |
defp get_hash(_, nil), do: nil | |
defp get_hash(user, hash_key), do: Map.get(user, hash_key) |> get_hash() | |
defp get_hash(nil), do: nil | |
defp get_hash(hash), do: {:ok, hash} | |
def add_hash(password, opts \\ []) do | |
hash_key = opts[:hash_key] || :password_hash | |
%{hash_key => hashpwsalt(password, opts), :password => nil} | |
end | |
def check_pass(user, password, opts \\ []) | |
def check_pass(user, password, opts) do | |
case get_hash(user, opts[:hash_key]) do | |
{:ok, hash} -> | |
(checkpw(password, hash) and {:ok, user}) || | |
{:error, "invalid password"} | |
_ -> | |
{:error, "no password hash found in the user struct"} | |
end | |
end | |
def hashpwsalt password, opts \\ [] do | |
"$plain$" <> password | |
end | |
def checkpw password, hash do | |
("$plain$" <> password) == hash | |
end | |
def dummy_checkpw opts \\ [] do | |
false | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment