Packages

Argon2 password hashing library for Gleam, using the reference C implementation.

Current section

Files

Jump to
argus src argus.erl
Raw

src/argus.erl

-module(argus).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-define(FILEPATH, "src/argus.gleam").
-export([hasher/0, hasher_argon2i/0, algorithm/2, time_cost/2, memory_cost/2, parallelism/2, hash_length/2, gen_salt/0, hash/3, verify/2]).
-export_type([argon2_algorithm/0, hasher/0, hashes/0, hash_error/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-type argon2_algorithm() :: argon2d | argon2i | argon2id.
-opaque hasher() :: {hasher,
argon2_algorithm(),
integer(),
integer(),
integer(),
integer()}.
-type hashes() :: {hashes, bitstring(), binary()}.
-type hash_error() :: output_pointer_is_null |
output_too_short |
output_too_long |
password_too_short |
password_too_long |
salt_too_short |
salt_too_long |
associated_data_too_short |
associated_data_too_long |
secret_too_short |
secret_too_long |
time_cost_too_small |
time_cost_too_large |
memory_cost_too_small |
memory_cost_too_large |
too_few_lanes |
too_many_lanes |
password_pointer_mismatch |
salt_pointer_mismatch |
secret_pointer_mismatch |
associated_data_pointer_mismatch |
memory_allocation_error |
free_memory_callback_null |
allocate_memory_callback_null |
incorrect_parameter |
incorrect_type |
invalid_algorithm |
output_pointer_mismatch |
too_few_threads |
too_many_threads |
not_enough_memory |
encoding_failed |
decoding_failed |
thread_failure |
decoding_length_failure |
verification_failure |
unknown_error_code.
-file("src/argus.gleam", 71).
?DOC(
" Create a new hasher with default settings based on the\n"
" [OWASP recommendations](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id).\n"
"\n"
" Note: if you change the algorithm to Argon2i, you will need to change the\n"
" `memory_cost` to 12_228 (12 mebibytes) or less for performance reasons.\n"
"\n"
" The `hasher_argon2i` function is provided with the recommended settings for\n"
" Argon2i.\n"
).
-spec hasher() -> hasher().
hasher() ->
{hasher, argon2id, 2, 19456, 1, 32}.
-file("src/argus.gleam", 85).
?DOC(
" Create a new hasher with default settings based on the\n"
" [OWASP recommendations](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id) for\n"
" Argon2i.\n"
).
-spec hasher_argon2i() -> hasher().
hasher_argon2i() ->
{hasher, argon2i, 3, 12228, 1, 32}.
-file("src/argus.gleam", 97).
?DOC(" Set the algorithm to use for the hasher.\n").
-spec algorithm(hasher(), argon2_algorithm()) -> hasher().
algorithm(Hasher, Algorithm) ->
_record = Hasher,
{hasher,
Algorithm,
erlang:element(3, _record),
erlang:element(4, _record),
erlang:element(5, _record),
erlang:element(6, _record)}.
-file("src/argus.gleam", 102).
?DOC(" Set the time cost to use for the hasher.\n").
-spec time_cost(hasher(), integer()) -> hasher().
time_cost(Hasher, Time_cost) ->
_record = Hasher,
{hasher,
erlang:element(2, _record),
Time_cost,
erlang:element(4, _record),
erlang:element(5, _record),
erlang:element(6, _record)}.
-file("src/argus.gleam", 107).
?DOC(" Set the memory cost to use for the hasher.\n").
-spec memory_cost(hasher(), integer()) -> hasher().
memory_cost(Hasher, Memory_cost) ->
_record = Hasher,
{hasher,
erlang:element(2, _record),
erlang:element(3, _record),
Memory_cost,
erlang:element(5, _record),
erlang:element(6, _record)}.
-file("src/argus.gleam", 112).
?DOC(" Set the parallelism to use for the hasher.\n").
-spec parallelism(hasher(), integer()) -> hasher().
parallelism(Hasher, Parallelism) ->
_record = Hasher,
{hasher,
erlang:element(2, _record),
erlang:element(3, _record),
erlang:element(4, _record),
Parallelism,
erlang:element(6, _record)}.
-file("src/argus.gleam", 117).
?DOC(" Set the hash length to use for the hasher.\n").
-spec hash_length(hasher(), integer()) -> hasher().
hash_length(Hasher, Hash_length) ->
_record = Hasher,
{hasher,
erlang:element(2, _record),
erlang:element(3, _record),
erlang:element(4, _record),
erlang:element(5, _record),
Hash_length}.
-file("src/argus.gleam", 167).
?DOC(" Generate a random salt of at least 64 bytes.\n").
-spec gen_salt() -> binary().
gen_salt() ->
argus_nif:gen_salt().
-file("src/argus.gleam", 139).
?DOC(
" Hash a password using the provided hasher.\n"
" \n"
" ## Examples\n"
" \n"
" ```gleam\n"
" import argus\n"
" \n"
" let assert Ok(hashes) =\n"
" argus.hasher()\n"
" |> argus.algorithm(argus.Argon2id)\n"
" |> argus.time_cost(3)\n"
" |> argus.memory_cost(12228)\n"
" |> argus.parallelism(1)\n"
" |> argus.hash_length(32)\n"
" |> argus.hash(\"password\", gen_salt())\n"
" \n"
" let assert Ok(True) = argus.verify(hashes.encoded_hash, \"password\")\n"
" ```\n"
).
-spec hash(hasher(), binary(), binary()) -> {ok, hashes()} |
{error, hash_error()}.
hash(Hasher, Password, Salt) ->
Result = argus_nif:hash(
Password,
Salt,
erlang:element(2, Hasher),
erlang:element(3, Hasher),
erlang:element(4, Hasher),
erlang:element(5, Hasher),
erlang:element(6, Hasher)
),
case Result of
{ok, {Raw_hash, Encoded_hash}} ->
{ok, {hashes, Raw_hash, Encoded_hash}};
{error, Error} ->
{error, Error}
end.
-file("src/argus.gleam", 161).
?DOC(" Verify a password using the provided encoded hash.\n").
-spec verify(binary(), binary()) -> {ok, boolean()} | {error, hash_error()}.
verify(Encoded_hash, Password) ->
jargon:verify(Encoded_hash, Password).