-module(pinkdf2). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([get_salt/0, with_defaults/2, with_config/5]). -export_type([pbkdf2_keys/0, sha_digest_size/0, pbkdf2_algorithm/0, pbkdf2_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. ?MODULEDOC(" Gleam bindings to fast_pbkdf2 NIF of PBKDF2 (Password-Based Key Derivation Function 2) for Erlang.\n"). -type pbkdf2_keys() :: {pbkdf2_keys, bitstring(), binary()}. -type sha_digest_size() :: bits224 | bits256 | bits384 | bits512. -type pbkdf2_algorithm() :: {sha2, sha_digest_size()} | {sha3, sha_digest_size()} | sha224 | sha256 | sha384 | sha512. -type pbkdf2_error() :: alloc_failed | bad_block_counter | bad_hash | bad_iteration_count | bad_password | bad_salt | ctx_allocation_failed | ctx_copy_failed | digest_final_failed | digest_init_failed | digest_init_ex2_failed | digest_update_failed | hmac_init_failed. -file("src/pinkdf2.gleam", 82). ?DOC( " Generates a base64-encoded salt with a minimum size of 64 bytes.\n" " It is provided here for convenience, but it is based on the same underlying Erlang function as `crypto.strong_rand_bytes`.\n" ). -spec get_salt() -> binary(). get_salt() -> extern:get_salt(). -file("src/pinkdf2.gleam", 43). ?DOC( " Derives a key from a password and salt with default settings based on the\n" " (OWASP recommendations)[https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2].\n" ). -spec with_defaults(binary(), binary()) -> {ok, pbkdf2_keys()} | {error, pbkdf2_error()}. with_defaults(Password, Salt) -> case extern:fp_with_defaults(Password, Salt) of {ok, Raw} -> {ok, {pbkdf2_keys, Raw, gleam_stdlib:bit_array_base64_encode(Raw, false)}}; {error, E} -> {error, E} end. -file("src/pinkdf2.gleam", 66). ?DOC( " Derives a key using the provided configuration.\n" "\n" " `iterations` is the number of times to run the algorithm. Must be a positive integer.\n" " `d_len` is the target derived key length in bytes. Must be a positive integer.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " import pinkdf2.{Bits512,Sha2}\n" "\n" " let salt = pinkdf2.get_salt()\n" " let assert Ok(key) = pinkdf2.with_config(Sha2(Bits512), \"password\", salt, 210_000, 32)\n" " ```\n" ). -spec with_config(pbkdf2_algorithm(), binary(), binary(), integer(), integer()) -> {ok, pbkdf2_keys()} | {error, pbkdf2_error()}. with_config(Alg, Password, Salt, Iterations, D_len) -> case extern:fp_with_config(Alg, Password, Salt, Iterations, D_len) of {ok, Raw} -> {ok, {pbkdf2_keys, Raw, gleam_stdlib:bit_array_base64_encode(Raw, false)}}; {error, E} -> {error, E} end.