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 mode. The ExCrypto module attempts to reduce complexity by providing some sane default values for common operations.
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 AES in GCM mode
Join the three parts of an encrypted payload and encode using Base.url_encode64
Same as encrypt/4
except the initialization_vector
is automatically
Encrypt a binary
with AES in GCM mode
Returns an AES key
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
Functions
Specs
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
Specs
decrypt(binary, binary, binary, binary, binary) ::
{:ok, binary} |
{: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
Specs
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
Specs
encrypt(binary, binary, binary) ::
{:ok, {binary, {binary, binary, binary}}} |
{:error, binary}
Same as encrypt/4
except the initialization_vector
is automatically.
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
Specs
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
Specs
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
Specs
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
Specs
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
Specs
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 < 20)
true
iex> rand_int = ExCrypto.rand_int(23, 99)
iex> assert(rand_int > 23)
true
iex> assert(rand_int < 99)
true
iex> rand_int = ExCrypto.rand_int(212, 736)
iex> assert(rand_int > 212)
true
iex> assert(rand_int < 736)
true