ExCrypto v0.10.0 ExCrypto

The ExCrypto module exposes a subset of functionality from the Erlang crypto module with the goal of making it easier to include strong cryptography in your Elixir applications.

This module provides functions for symmetric-key cryptographic operations using AES in GCM and CBC mode. The ExCrypto module attempts to reduce complexity by providing some sane default values for common operations.

Link to this section Summary

Functions

Split and decode the three parts of an encrypted payload and encode using Base.url_decode64

Returns a clear-text string decrypted with AES256 in CBC mode

Returns a clear-text string decrypted with AES in GCM mode

Join the three parts of an encrypted payload and encode using Base.url_encode64

Encrypt a binary with AES in CBC mode

Same as encrypt/4 except the initialization_vector is automatically generated

Returns a string of random where the length is equal to integer

Returns random characters. Each character represents 6 bits of entropy

Returns a random integer between low and high

Link to this section Functions

Link to this function

decode_payload(encoded_parts)
decode_payload(binary()) ::
  {:ok, {binary(), binary(), binary()}} | {:error, binary()}

Split and decode the three parts of an encrypted payload and encode using Base.url_decode64.

Examples

iex> clear_text = "my-clear-text"
iex> auth_data = "my-auth-data"
iex> {:ok, aes_256_key} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, {_ad, {init_vec, cipher_text, cipher_tag}}} = ExCrypto.encrypt(aes_256_key, auth_data, clear_text)
iex> {:ok, encoded_payload} = ExCrypto.encode_payload(init_vec, cipher_text, cipher_tag)
iex> assert(String.valid?(encoded_payload))
true
iex> {:ok, {d_init_vec, d_cipher_text, d_cipher_tag}} = ExCrypto.decode_payload(encoded_payload)
iex> assert(d_init_vec == init_vec)
true
iex> assert(d_cipher_text == cipher_text)
true
iex> assert(d_cipher_tag == cipher_tag)
true
Link to this function

decrypt(key, initialization_vector, cipher_text)
decrypt(binary(), binary(), binary()) ::
  {:ok, binary()} | {:error, :decrypt_failed} | {:error, binary()}

Returns a clear-text string decrypted with AES256 in CBC mode.

At a high level decryption using AES in CBC mode looks like this:

key + init_vec + cipher_text  -> clear_text

Examples

iex> clear_text = "my-clear-text"
iex> {:ok, aes_256_key} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, {init_vec, cipher_text}} = ExCrypto.encrypt(aes_256_key, clear_text)
iex> {:ok, val} = ExCrypto.decrypt(aes_256_key, init_vec, cipher_text)
iex> assert(val == clear_text)
true
Link to this function

decrypt(key, authentication_data, initialization_vector, cipher_text, cipher_tag)
decrypt(binary(), binary(), binary(), binary(), binary()) ::
  {:ok, binary()} | {:error, :decrypt_failed} | {:error, binary()}

Returns a clear-text string decrypted with AES in GCM mode.

At a high level decryption using AES in GCM mode looks like this:

key + init_vec + auth_data + cipher_text + cipher_tag -> clear_text

Examples

iex> clear_text = "my-clear-text"
iex> auth_data = "my-auth-data"
iex> {:ok, aes_256_key} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, {_ad, payload}} = ExCrypto.encrypt(aes_256_key, auth_data, clear_text)
iex> {init_vec, cipher_text, cipher_tag} = payload
iex> {:ok, val} = ExCrypto.decrypt(aes_256_key, auth_data, init_vec, cipher_text, cipher_tag)
iex> assert(val == clear_text)
true
Link to this function

encode_payload(initialization_vector, cipher_text, cipher_tag)
encode_payload(binary(), binary(), binary()) ::
  {:ok, binary()} | {:error, binary()}

Join the three parts of an encrypted payload and encode using Base.url_encode64.

This produces a Unicode payload string like this:

init_vec   <> cipher_text <> cipher_tag
[128 bits] <>  [?? bits]  <> [128 bits]

This format is convenient to include in HTTP request bodies. It can also be used with JSON transport formats.

Examples

iex> clear_text = "my-clear-text"
iex> auth_data = "my-auth-data"
iex> {:ok, aes_256_key} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, {_ad, {init_vec, cipher_text, cipher_tag}}} = ExCrypto.encrypt(aes_256_key, auth_data, clear_text)
iex> {:ok, encoded_payload} = ExCrypto.encode_payload(init_vec, cipher_text, cipher_tag)
iex> assert(String.valid?(encoded_payload))
true
Link to this function

encrypt(key, clear_text)
encrypt(binary(), binary()) :: {:ok, {binary(), binary()}} | {:error, binary()}

Encrypt a binary with AES in CBC mode.

Returns a tuple containing the initialization_vector, and cipher_text.

At a high level encryption using AES in CBC mode looks like this:

key + clear_text -> init_vec + cipher_text

Examples

iex> clear_text = "my-clear-text"
iex> {:ok, aes_256_key} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, {_iv, cipher_text}} = ExCrypto.encrypt(aes_256_key, clear_text)
iex> assert(is_bitstring(cipher_text))
true
Link to this function

encrypt(key, clear_text, clear_text)
encrypt(binary(), binary(), %{initialization_vector: binary()}) ::
  {:ok, {binary(), {binary(), binary(), binary()}}}
  | {:ok, {binary(), binary()}}
  | {:error, any()}
encrypt(binary(), binary(), binary()) ::
  {:ok, {binary(), {binary(), binary(), binary()}}} | {:error, binary()}

Same as encrypt/4 except the initialization_vector is automatically generated.

A 128 bit initialization_vector is generated automatically by encrypt/3. It returns a tuple containing the initialization_vector, the cipher_text and the cipher_tag.

Examples

iex> clear_text = "my-clear-text"
iex> auth_data = "my-auth-data"
iex> {:ok, aes_256_key} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, {_ad, payload}} = ExCrypto.encrypt(aes_256_key, auth_data, clear_text)
iex> {_init_vec, cipher_text, cipher_tag} = payload
iex> assert(is_bitstring(cipher_text))
true
iex> assert(bit_size(cipher_tag) == 128)
true
Link to this function

encrypt(key, authentication_data, initialization_vector, clear_text)
encrypt(binary(), binary(), binary(), binary()) ::
  {:ok, {binary(), {binary(), binary(), binary()}}} | {:error, binary()}

Encrypt a binary with AES in GCM mode.

Returns a tuple containing the initialization_vector, the cipher_text and the cipher_tag.

At a high level encryption using AES in GCM mode looks like this:

key + init_vec + auth_data + clear_text -> cipher_text + cipher_tag

Examples

iex> clear_text = "my-clear-text"
iex> auth_data = "my-auth-data"
iex> {:ok, aes_256_key} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, iv} = ExCrypto.rand_bytes(16)
iex> {:ok, {_ad, payload}} = ExCrypto.encrypt(aes_256_key, auth_data, iv, clear_text)
iex> {_iv, cipher_text, cipher_tag} = payload
iex> assert(is_bitstring(cipher_text))
true
iex> assert(bit_size(cipher_tag) == 128)
true
Link to this function

generate_aes_key(key_type, key_format)
generate_aes_key(atom(), atom()) :: {:ok, binary()} | {:error, binary()}

Returns an AES key.

Accepts a key_type (:aes_128|:aes_192|:aes_256) and key_format (:base64|:bytes) to determine type of key to produce.

Examples

iex> {:ok, key} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> assert bit_size(key) == 256
true

iex> {:ok, key} = ExCrypto.generate_aes_key(:aes_256, :base64)
iex> assert String.length(key) == 44
true

iex> {:ok, key} = ExCrypto.generate_aes_key(:aes_192, :bytes)
iex> assert bit_size(key) == 192
true

iex> {:ok, key} = ExCrypto.generate_aes_key(:aes_192, :base64)
iex> assert String.length(key) == 32
true

iex> {:ok, key} = ExCrypto.generate_aes_key(:aes_128, :bytes)
iex> assert bit_size(key) == 128
true

iex> {:ok, key} = ExCrypto.generate_aes_key(:aes_128, :base64)
iex> assert String.length(key) == 24
true
Link to this function

pad(data, block_size)

Link to this function

rand_bytes(length)
rand_bytes(integer()) :: {:ok, binary()} | {:error, binary()}

Returns a string of random where the length is equal to integer.

Examples

iex> {:ok, rand_bytes} = ExCrypto.rand_bytes(16)
iex> assert(byte_size(rand_bytes) == 16)
true
iex> assert(bit_size(rand_bytes) == 128)
true

iex> {:ok, rand_bytes} = ExCrypto.rand_bytes(24)
iex> assert(byte_size(rand_bytes) == 24)
true
iex> assert(bit_size(rand_bytes) == 192)
true

iex> {:ok, rand_bytes} = ExCrypto.rand_bytes(32)
iex> assert(byte_size(rand_bytes) == 32)
true
iex> assert(bit_size(rand_bytes) == 256)
true
Link to this function

rand_bytes!(length)
rand_bytes!(integer()) :: binary()

Link to this function

rand_chars(num_chars)
rand_chars(integer()) :: String.t()

Returns random characters. Each character represents 6 bits of entropy.

Accepts an integer to determine the number of random characters to return.

Examples

iex> rand_string = ExCrypto.rand_chars(24)
iex> assert(String.length(rand_string) == 24)
true

iex> rand_string = ExCrypto.rand_chars(32)
iex> assert(String.length(rand_string) == 32)
true

iex> rand_string = ExCrypto.rand_chars(44)
iex> assert(String.length(rand_string) == 44)
true
Link to this function

rand_int(low, high)
rand_int(integer(), integer()) :: integer()

Returns a random integer between low and high.

Accepts two integer arguments for the low and high boundaries. The low argument must be less than the high argument.

Examples

iex> rand_int = ExCrypto.rand_int(2, 20)
iex> assert(rand_int > 1)
true
iex> assert(rand_int < 21)
true

iex> rand_int = ExCrypto.rand_int(23, 99)
iex> assert(rand_int > 22)
true
iex> assert(rand_int < 99)
true

iex> rand_int = ExCrypto.rand_int(212, 736)
iex> assert(rand_int > 211)
true
iex> assert(rand_int < 737)
true