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:

Summary

Functions

Bcrypt

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

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.

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.

Generate a binary composed of random bytes.

Encodes and signs data into a token you can send to clients.

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.

Decodes the original data from the token and verifies its integrity.

Types

@type based32_url() :: <<_::64, _::_*8>>

Functions

Link to this function

base32_valid_otp?(secret, otp)

View Source
@spec base32_valid_otp?(binary(), String.t()) :: boolean()

For information See valid_otp?/3 and valid_otp?/2

Link to this function

base32_valid_otp?(secret, otp, last_used)

View Source
@spec base32_valid_otp?(binary(), String.t(), NimbleTOTP.time()) :: boolean()

For information See valid_otp?/3 and valid_otp?/2

Link to this function

create_hash_password(password, atom)

View Source
@spec create_hash_password(String.t(), :argon2 | :bcrypt | :pbkdf2) :: String.t()

Bcrypt

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 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).

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)
Link to this function

create_otp(issuer, label)

View Source
@spec create_otp(binary(), String.t()) :: %{
  secret: String.t(),
  url: <<_::64, _::_*8>>
}

For information See create_otp_link_and_secret/2

Link to this function

create_otp(secret, issuer, label)

View Source
@spec create_otp(binary(), String.t(), String.t()) :: %{
  secret: String.t(),
  url: based32_url()
}

For information See create_otp_link/3

Link to this function

create_otp_link(secret, issuer, label)

View Source
@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 to base32.
  • :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.

Link to this function

decrypt(key_base, secret, token, opts \\ [])

View Source

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 to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 1000
  • :key_length - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 32
  • :key_digest - option passed to Plug.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 by encrypt/4.
Link to this function

encrypt(key_base, secret, data, opts \\ [])

View Source

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 to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 1000
  • :key_length - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 32
  • :key_digest - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to :sha256
  • :signed_at - set the timestamp of the token in seconds. Defaults to System.system_time(:second)
  • :max_age - the default maximum age of the token. Defaults to 86400 seconds (1 day) and it may be overridden on decrypt/4.
Link to this function

no_user_verify_password(password, atom)

View Source
@spec no_user_verify_password(String.t(), :argon2 | :bcrypt | :pbkdf2) :: false
@spec secret(integer()) :: any()

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, ...>>
Link to this function

sign(key_base, salt, data, opts \\ [])

View Source

Encodes and signs data into a token you can send to clients.

Options

  • :key_iterations - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 1000
  • :key_length - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 32
  • :key_digest - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to :sha256
  • :signed_at - set the timestamp of the token in seconds. Defaults to System.system_time(:second)
  • :max_age - the default maximum age of the token. Defaults to 86400 seconds (1 day) and it may be overridden on verify/4.

Example:

key_base = random_key_base()
sign(key_base, "user-secret", {:elixir, :terms})
Link to this function

simple_hash(rand_size \\ 32)

View Source

For information See simple_hash/2 and simple_hash/3.

Link to this function

simple_hash(text, alg, truncated \\ nil)

View Source

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}
@spec valid_otp?(binary(), String.t()) :: boolean()

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.

Link to this function

valid_otp?(secret, otp, last_used)

View Source
@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.

Link to this function

valid_otp?(secret, otp, last_used, atom)

View Source
@spec valid_otp?(binary(), String.t(), NimbleTOTP.time(), :base32) :: boolean()

For information See valid_otp?/3 and valid_otp?/2

Link to this function

verify(key_base, salt, token, opts \\ [])

View Source

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 to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 1000
  • :key_length - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 32
  • :key_digest - option passed to Plug.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 by sign/4.
Link to this function

verify_password(hash, password, atom)

View Source
@spec verify_password(binary(), String.t(), :argon2 | :bcrypt | :bcrypt_2b | :pbkdf2) ::
  boolean()

For information See create_hash_password/2.