View Source MishkaDeveloperTools.Helper.Crypto (Mishka developer tools v0.1.7)
In reality, this module serves as a support for other libraries in addition to Erlang's built-in functions for encryption, hashing, and other topics that are associated with the language.
It should be brought to your attention that certain functions necessitate the addition of their dependencies to the primary project. Consequently, prior to making use of these functionalities, establish the appropriate dependence within the project in accordance with your requirements.
These functions are custom or wrappers, Copy from:
- https://hexdocs.pm/plug_crypto/2.0.0/Plug.Crypto.html
- https://hexdocs.pm/phoenix/Phoenix.Token.html
- https://github.com/dashbitco/nimble_totp/blob/master/lib/nimble_totp.ex
- https://dashbit.co/blog/introducing-nimble-totp
- https://hex.pm/packages/bcrypt_elixir
- https://hex.pm/packages/pbkdf2_elixir
- https://password-hashing.net/
- https://hex.pm/packages/argon2_elixir
- https://github.com/malach-it/boruta_auth
- https://github.com/joken-elixir/joken
- https://hexdocs.pm/phoenix/mix_phx_gen_auth.html
- https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Secret.html
Summary
Functions
For information See valid_otp?/3
and valid_otp?/2
For information See valid_otp?/3
and valid_otp?/2
Bcrypt
bcrypt_elixir
: https://hex.pm/packages/bcrypt_elixirLICENSE
: https://github.com/riverrun/comeonin/blob/master/LICENSE
Use cases information
Make sure you have a
C compiler
installed. See the Comeonin wiki for details. Wiki link: https://github.com/riverrun/comeonin/wiki/Requirements
For information See create_otp_link_and_secret/2
For information See create_otp_link/3
Generates an OTP authentication URL with a given secret, issuer, and label.
Generates an OTP authentication URL with a given issuer, and label.
Decrypts the original data from the token and verifies its integrity.
Its usage is identical to verify/4
but for encrypted tokens.
Generate a binary composed of random bytes.
Encodes and signs data into a token you can send to clients.
For information See simple_hash/2
and simple_hash/3
.
This is a straightforward data hashing function that does not differentiate between
symmetric
and asymmetric
functions according to their characteristics. Take, for instance,
the use of checksums
or codes associated with nonce
, c_hash
, at_hash
,
short-lived Access Token
, and other similar concepts.
Checks if a provided OTP is valid for the given secret.
Checks if a provided OTP is valid for the given secret which is based32.
For information See valid_otp?/3
and valid_otp?/2
Decodes the original data from the token and verifies its integrity.
For information See create_hash_password/2
.
Types
@type based32_url() :: <<_::64, _::_*8>>
Functions
For information See valid_otp?/3
and valid_otp?/2
@spec base32_valid_otp?(binary(), String.t(), NimbleTOTP.time()) :: boolean()
For information See valid_otp?/3
and valid_otp?/2
Bcrypt
bcrypt_elixir
: https://hex.pm/packages/bcrypt_elixirLICENSE
: https://github.com/riverrun/comeonin/blob/master/LICENSE
Use cases information
Make sure you have a
C compiler
installed. See the Comeonin wiki for details. Wiki link: https://github.com/riverrun/comeonin/wiki/Requirements
Bcrypt is a key derivation function for passwords designed by Niels Provos and David Mazières. Bcrypt is an adaptive function, which means that it can be configured to remain slow and resistant to brute-force attacks even as computational power increases.
Bcrypt has no known vulnerabilities and has been widely tested for over 15 years. However, as it has a low memory use, it is susceptible to GPU cracking attacks.
You are required to make use of this function in order to generate an irreversible (hashed) duplicate of the user's password when you are storing your password.
Additionally, you should save it in the database together with other unique features of your unique program.
Exmple:
create_hash_password("USER_HARD_PASSWORD", :bcrypt)
Pbkdf2
pbkdf2
- pbkdf2_elixir https://hex.pm/packages/pbkdf2_elixirLICENSE
: https://github.com/riverrun/pbkdf2_elixir/blob/master/LICENSE.md
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.
Pbkdf2 has no known vulnerabilities and has been widely tested for over 15 years. However, like Bcrypt, as it has a low memory use, it is susceptible to GPU cracking attacks.
The original implementation of Pbkdf2 used SHA-1 as the pseudorandom function, but this version uses HMAC-SHA-512, the default, or HMAC-SHA-256.
Exmple:
create_hash_password("USER_HARD_PASSWORD", :pbkdf2)
Argon2
Argon2 is the winner of the Password Hashing Competition (PHC).
- https://password-hashing.net/
argon2
: argon2_elixir https://hex.pm/packages/argon2_elixir (recommended)- https://github.com/riverrun/argon2_elixir/blob/master/LICENSE.md
Argon2 is a memory-hard password hashing function which can be used to hash passwords for credential storage, key derivation, or other applications.
Being memory-hard means that it is not only computationally expensive, but it also uses a lot of memory (which can be configured). This means that it is much more difficult to attack Argon2 hashes using GPUs or dedicated hardware.
Use cases information
Make sure you have a
C compiler
installed. See the Comeonin wiki for details. Wiki link: https://github.com/riverrun/comeonin/wiki/Requirements
Configuration
The following four parameters can be set in the config file (these can all be overridden using keyword options):
t_cost - time cost
the amount of computation, given in number of iterations
3 is the default
m_cost - memory usage
16 is the default - this will produce a memory usage of 64 MiB (2 ^ 16 KiB)
parallelism - number of parallel threads
4 is the default
- argon2_type - argon2 variant to use
0 (Argon2d), 1 (Argon2i) or 2 (Argon2id)
2 is the default (Argon2id)
For verifing you can use like this:
verify_password(hash, "USER_HARD_PASSWORD", :bcrypt)
verify_password(hash, "USER_HARD_PASSWORD", :pbkdf2)
verify_password(hash, "USER_HARD_PASSWORD", :argon2)
For information See create_otp_link_and_secret/2
@spec create_otp(binary(), String.t(), String.t()) :: %{ secret: String.t(), url: based32_url() }
For information See create_otp_link/3
@spec create_otp_link(binary(), String.t(), String.t()) :: %{ secret: String.t(), url: based32_url() }
Generates an OTP authentication URL with a given secret, issuer, and label.
Parameters:
- secret (binary): The secret key used to generate the OTP,
it should be
:crypto.strong_rand_bytes/1
. - issuer (String): The name of the issuer. This helps to identify which service the OTP is associated with.
- label (String): A label used to identify the specific account or user.
Returns:
It returns a map containing:
:secret
(string) - It should be:crypto.strong_rand_bytes/1
output which is converted tobase32
.:url
(String) - The complete OTP authentication URL.
Example:
secret = :crypto.strong_rand_bytes(20)
create_otp_link(secret, "Mishka", "user_test")
Use cases information
You are able to generate a QR code from the URL that you have made and then provide it to the user. The majority of devices are able to scan it and utilize it as a two-factor authentication one-time password with ease.
@spec create_otp_link_and_secret(String.t(), String.t()) :: %{ secret: String.t(), url: based32_url() }
Generates an OTP authentication URL with a given issuer, and label.
Parameters:
- issuer (String): The name of the issuer. This helps to identify which service the OTP is associated with.
- label (String): A label used to identify the specific account or user.
Returns:
It returns a map containing:
:secret
(string) - It should be:crypto.strong_rand_bytes/1
output which is converted tobase32
.:url
(String) - The complete OTP authentication URL.
Example:
create_otp_link_and_secret("Mishka", "user_test")
Use cases information
You are able to generate a QR code from the URL that you have made and then provide it to the user. The majority of devices are able to scan it and utilize it as a two-factor authentication one-time password with ease.
Decrypts the original data from the token and verifies its integrity.
Its usage is identical to verify/4
but for encrypted tokens.
Options
:key_iterations
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to 1000:key_length
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to 32:key_digest
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to:sha256
:max_age
- verifies the token only if it has been generated "max age" ago in seconds. Defaults to the max age signed in the token byencrypt/4
.
Encodes, encrypts, and signs data into a token you can send to
clients. Its usage is identical to that of sign/4
, but the data
is extracted using decrypt/4
, rather than verify/4
.
Options
:key_iterations
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to 1000:key_length
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to 32:key_digest
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to:sha256
:signed_at
- set the timestamp of the token in seconds. Defaults toSystem.system_time(:second)
:max_age
- the default maximum age of the token. Defaults to 86400 seconds (1 day) and it may be overridden ondecrypt/4
.
@spec no_user_verify_password(String.t(), :argon2 | :bcrypt | :pbkdf2) :: false
Generate a binary composed of random bytes.
The number of bytes is defined by the size
argument. Default is 20
per the
HOTP RFC.
based on: https://github.com/dashbitco/nimble_totp/blob/master/lib/nimble_totp.ex
Examples
alias MishkaDeveloperTools.Helper.Crypto
Crypto.secret()
#=> <<178, 117, 46, 7, 172, 202, 108, 127, 186, 180, ...>>
Encodes and signs data into a token you can send to clients.
Options
:key_iterations
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to 1000:key_length
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to 32:key_digest
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to:sha256
:signed_at
- set the timestamp of the token in seconds. Defaults toSystem.system_time(:second)
:max_age
- the default maximum age of the token. Defaults to 86400 seconds (1 day) and it may be overridden onverify/4
.
Example:
key_base = random_key_base()
sign(key_base, "user-secret", {:elixir, :terms})
For information See simple_hash/2
and simple_hash/3
.
This is a straightforward data hashing function that does not differentiate between
symmetric
and asymmetric
functions according to their characteristics. Take, for instance,
the use of checksums
or codes associated with nonce
, c_hash
, at_hash
,
short-lived Access Token
, and other similar concepts.
Security issue
It is not recommended to use this function for hashing passwords or JWTs.
I inspired the initial code from this path:
Example:
simple_hash("Your text", "RS512")
simple_hash("Your text", "RS512", 32)
# OR
simple_hash()
simple_hash(32)
This function in all types of input and output is as follows
{URL Encode64, Binary}
Checks if a provided OTP is valid for the given secret.
Parameters:
- secret (binary): The secret key used to generate the OTP,
it should be
:crypto.strong_rand_bytes/1
. otp
(String): The OTP to verify, for example"581234"
.
Example:
valid_otp?(secret, "581234")
# Or, you might put the time when the token was used for the last time to
# prohibit the user from using it again.
last_used = System.os_time(:second)
valid_otp?(secret, "581234", last_used)
Use cases information
One thing to keep in mind is that you ought to have already kept the secret of each user in a location such as a database.
@spec valid_otp?(binary(), String.t(), :base32 | NimbleTOTP.time()) :: boolean()
Checks if a provided OTP is valid for the given secret which is based32.
Parameters:
- secret (binary): The secret key used to generate the OTP,
it should be
:crypto.strong_rand_bytes/1
. otp
(String): The OTP to verify, for example"581234"
.
Example:
valid_otp?(secret, "581234", :base32)
# Or, you might put the time when the token was used for the last time to
# prohibit the user from using it again.
last_used = System.os_time(:second)
valid_otp?(secret, "581234", last_used, :base32)
Use cases information
One thing to keep in mind is that you ought to have already kept the secret of each user in a location such as a database.
@spec valid_otp?(binary(), String.t(), NimbleTOTP.time(), :base32) :: boolean()
For information See valid_otp?/3
and valid_otp?/2
Decodes the original data from the token and verifies its integrity.
Examples
In this scenario we will create a token, sign it, then provide it to a client application.
iex> user_id = 99
iex> secret = "kjoy3o1zeidquwy1398juxzldjlksahdk3"
iex> namespace = "user auth"
iex> token = sign(secret, namespace, user_id)
The mechanism for passing the token to the client is typically through a cookie, a JSON response body, or HTTP header. For now, assume the client has received a token it can use to validate requests for protected resources.
When the server receives a request, it can use verify/4
to determine if it
should provide the requested resources to the client:
iex> verify(secret, namespace, token, max_age: 86400)
{:ok, 99}
In this example, we know the client sent a valid token because verify/4
returned a tuple of type {:ok, user_id}
. The server can now proceed with
the request.
However, if the client had sent an expired token, an invalid token, or nil
,
verify/4
would have returned an error instead:
iex> verify(secret, namespace, expired, max_age: 86400)
{:error, :expired}
iex> verify(secret, namespace, invalid, max_age: 86400)
{:error, :invalid}
iex> verify(secret, namespace, nil, max_age: 86400)
{:error, :missing}
Options
:key_iterations
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to 1000:key_length
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to 32:key_digest
- option passed toPlug.Crypto.KeyGenerator
when generating the encryption and signing keys. Defaults to:sha256
:max_age
- verifies the token only if it has been generated "max age" ago in seconds. Defaults to the max age signed in the token bysign/4
.
For information See create_hash_password/2
.