Pbkdf2 (pbkdf2_elixir v1.3.0) View Source
Elixir wrapper for the Pbkdf2 password hashing function.
For a lower-level API, see Pbkdf2.Base.
Configuration
The following parameter can be set in the config file:
- rounds - computational cost
- the number of rounds
- 160_000 is the default
If you are hashing passwords in your tests, it can be useful to add
the following to the config/test.exs
file:
config :pbkdf2_elixir,
rounds: 1
NB. do not use this value in production.
Pbkdf2
Pbkdf2 is a password-based key derivation function that uses a password, a variable-length salt and an iteration count and applies a pseudorandom function to these to produce a key.
The original implementation used SHA-1 as the pseudorandom function, but this version uses HMAC-SHA-512, the default, or HMAC-SHA-256.
Warning
It is recommended that you set a maximum length for the password when using Pbkdf2. This maximum length should not prevent valid users from setting long passwords. It is instead needed to combat denial-of-service attacks. As an example, Django sets the maximum length to 4096 bytes. For more information, see this link.
Link to this section Summary
Functions
Hashes a password, using hash_pwd_salt/2
, and returns the password hash in a map.
Checks the password, using verify_pass/2
, by comparing the hash with
the password hash found in a user struct, or map.
Generates a random salt.
Hashes a password with a randomly generated salt.
Runs the password hash function, but always returns false.
Verifies a password by hashing the password and comparing the hashed value with a stored hash.
Link to this section Functions
Hashes a password, using hash_pwd_salt/2
, and returns the password hash in a map.
This is a convenience function that is especially useful when used with Ecto changesets.
Options
In addition to the :hash_key
option show below, this function also takes
options that are then passed on to the hash_pwd_salt/2
function in this
module.
See the documentation for hash_pwd_salt/2
for further details.
:hash_key
- the password hash identifier- the default is
:password_hash
- the default is
Example with Ecto
The put_pass_hash
function below is an example of how you can use
add_hash
to add the password hash to the Ecto changeset.
defp put_pass_hash(%Ecto.Changeset{valid?: true, changes:
%{password: password}} = changeset) do
change(changeset, add_hash(password))
end
defp put_pass_hash(changeset), do: changeset
This function will return a changeset with %{password_hash: password_hash}
added to the changes
map.
Checks the password, using verify_pass/2
, by comparing the hash with
the password hash found in a user struct, or map.
This is a convenience function that takes a user struct, or map, as input and seemlessly handles the cases where no user is found.
Options
:hash_key
- the password hash identifier- this does not need to be set if the key is
:password_hash
or:encrypted_password
- this does not need to be set if the key is
:hide_user
- run theno_user_verify/1
function if no user is found- the default is true
Example
The following is an example of using this function to verify a user's password:
def verify_user(%{"password" => password} = params) do
params
|> Accounts.get_by()
|> check_pass(password)
end
The Accounts.get_by
function in this example takes the user parameters
(for example, email and password) as input and returns a user struct or nil.
Specs
Generates a random salt.
This function takes one optional argument - a keyword list (see below for options) or an integer with the salt length (in bytes).
Options
The following options are available:
:salt_len
- the length of the random salt- the default is 16 bytes
- for more information, see the 'Salt length recommendations' section below
:format
- the length of the random salt- the default is
:modular
(modular crypt format) - the other available options are
:django
and:hex
- the default is
Examples
Here is an example of generating a salt with the default salt length and format:
Pbkdf2.gen_salt()
To generate a different length salt:
Pbkdf2.gen_salt(salt_len: 32)
And to generate a salt in django output format:
Pbkdf2.gen_salt(format: :django)
Salt length recommendations
In most cases, 16 bytes is a suitable length for the salt. It is not recommended to use a salt that is shorter than this (see below for details and references).
According to the Pbkdf2 standard, the salt should be at least 8 bytes long, but according to NIST recommendations, the minimum salt length should be 16 bytes.
Hashes a password with a randomly generated salt.
Options
In addition to the options for gen_salt/1
(:salt_len
and :format
),
this function also takes options that are then passed on to the
hash_password
function in the Pbkdf2.Base
module.
See the documentation for Pbkdf2.Base.hash_password/3
for further details.
Examples
The following examples show how to hash a password with a randomly-generated salt and then verify a password:
iex> hash = Pbkdf2.hash_pwd_salt("password")
...> Pbkdf2.verify_pass("password", hash)
true
iex> hash = Pbkdf2.hash_pwd_salt("password")
...> Pbkdf2.verify_pass("incorrect", hash)
false
The next examples show how to use some of the various available options:
iex> hash = Pbkdf2.hash_pwd_salt("password", rounds: 100_000)
...> Pbkdf2.verify_pass("password", hash)
true
iex> hash = Pbkdf2.hash_pwd_salt("password", digest: :sha256)
...> Pbkdf2.verify_pass("password", hash)
true
iex> hash = Pbkdf2.hash_pwd_salt("password", digest: :sha256, format: :django)
...> Pbkdf2.verify_pass("password", hash)
true
Runs the password hash function, but always returns false.
This function is intended to make it more difficult for any potential attacker to find valid usernames by using timing attacks. This function is only useful if it is used as part of a policy of hiding usernames.
Options
This function should be called with the same options as those used by
hash_pwd_salt/2
.
Hiding usernames
In addition to keeping passwords secret, hiding the precise username can help make online attacks more difficult. An attacker would then have to guess a username / password combination, rather than just a password, to gain access.
This does not mean that the username should be kept completely secret. Adding a short numerical suffix to a user's name, for example, would be sufficient to increase the attacker's work considerably.
If you are implementing a policy of hiding usernames, it is important to make sure that the username is not revealed by any other part of your application.
Verifies a password by hashing the password and comparing the hashed value with a stored hash.
See the documentation for hash_pwd_salt/2
for examples of using this function.