Packages
argon2_elixir
0.10.1
4.1.3
4.1.2
4.1.1
4.1.0
4.0.0
3.2.1
3.2.0
3.1.0
3.0.0
2.4.1
2.4.0
2.3.0
2.2.1
2.2.0
2.1.2
2.1.1
2.1.0
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.3.3
1.3.1
1.3.0
1.2.14
1.2.13
1.2.12
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
0.12.0
0.11.4
0.11.3
0.11.2
0.11.0
0.10.1
0.10.0
0.9.1
0.9.0
0.8.0
Argon2 password hashing algorithm for Elixir
Current section
Files
Jump to
Current section
Files
lib/argon2/base.ex
defmodule Argon2.Base do
@moduledoc """
Lower-level api for Argon2.
These functions can be useful if you want more control over some
of the options.
"""
@compile {:autoload, false}
@on_load {:init, 0}
def init do
path = :filename.join(:code.priv_dir(:argon2_elixir), 'argon2_nif')
:erlang.load_nif(path, 0)
end
def hash_nif(t_cost, m_cost, parallelism, password, salt, raw, hashlen, encodedlen, argon2_type, argon2_version)
def hash_nif(_, _, _, _, _, _, _, _, _, _), do: exit(:nif_library_not_loaded)
def verify_nif(stored_hash, password, argon2_type)
def verify_nif(_, _, _), do: exit(:nif_library_not_loaded)
def error_nif(error_code)
def error_nif(_), do: exit(:nif_library_not_loaded)
def encodedlen_nif(t_cost, m_cost, parallelism, saltlen, hashlen, argon2_type)
def encodedlen_nif(_, _, _, _, _, _), do: exit(:nif_library_not_loaded)
@doc """
Hash a password using Argon2.
## Options
There are six options:
* t_cost - time cost, or number of iterations
* 3 is the default
* m_cost - memory cost
* 12 is the default - this will produce a memory cost of 2 ^ 12 KiB
* parallelism - number of threads
* 1 is the default
* format - output format
* this value can be :raw_hash, :report or :encoded
* :encoded is the default
* hashlen - length of the hash (in bytes)
* the default is 32
* argon2_type - Argon2 type
* this value should be 0 (Argon2d), 1 (Argon2i) or 2 (Argon2id)
* the default is 1 (Argon2i)
"""
def hash_password(password, salt, opts \\ [])
def hash_password(password, salt, opts) when is_binary(password) and is_binary(salt) do
{t, m, p, raw_hash, encoded_hash, hashlen, argon2_type} = options = get_opts(opts)
encodedlen = if encoded_hash,
do: encodedlen_nif(t, m, p, byte_size(salt), hashlen, argon2_type), else: 0
hash_nif(t, m, p, password, salt, raw_hash, hashlen, encodedlen, argon2_type, 0)
|> handle_result(options)
end
def hash_password(_, _, _) do
raise ArgumentError, "Wrong type - password and salt should be strings"
end
defp get_opts(opts) do
{raw_hash, encoded_hash} = case opts[:format] do
:raw_hash -> {1, false}
:report -> {1, true}
_ -> {0, true}
end
{Keyword.get(opts, :t_cost, 3),
Keyword.get(opts, :m_cost, 12),
Keyword.get(opts, :parallelism, 1),
raw_hash,
encoded_hash,
Keyword.get(opts, :hashlen, 32),
Keyword.get(opts, :argon2_type, 1)}
end
defp handle_result(result, _) when is_integer(result) do
msg = error_nif(result) |> :binary.list_to_bin
raise ArgumentError, msg
end
defp handle_result({[], encoded}, _), do: :binary.list_to_bin(encoded)
defp handle_result({raw, []}, _), do: :binary.list_to_bin(raw)
defp handle_result({raw, encoded}, options) do
{:binary.list_to_bin(raw), :binary.list_to_bin(encoded), options}
end
end