apoc v0.1.2 Apoc.AES View Source

Implementation of the AES block encryption standard as per FIPS PUB 197.

The functions in this module operate in GCM (Galois/Counter Mode) to provide fast Authenticated Encryption. See Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC.

Additionally, three block sizes are support (128, 192 and 256). For those particularly paranoid users, a block size of 256 is recommended for defense against Shore’s algorithm. Use a 32 byte key for a 256 bit block size. See encrypt/2.

Link to this section Summary

Functions

Decrypt a cipher text that has been encrypted under the given key

Encrypt a message using AES under the given key

Link to this section Types

Link to this type aes_key() View Source
aes_key() :: <<_::16, _::_*8>> | <<_::24, _::_*8>> | <<_::32, _::_*8>>

Link to this section Functions

Link to this function decrypt(payload, key) View Source
decrypt(String.t(), aes_key()) :: binary()

Decrypt a cipher text that has been encrypted under the given key.

Example

{:ok, plaintext} = Apoc.AES.decrypt(ciphertext, key)
Link to this function encrypt(msg, key) View Source
encrypt(String.t(), aes_key()) :: binary()

Encrypt a message using AES under the given key

The key should be a 16, 24 or 32 byte binary string

Example

Apoc.AES.encrypt("a secret message", Apoc.rand_bytes(16))

It’s important that the key be as uniformly random as possible. Consequently, avoid the temptation to do this:

# Don't do this
k = Apoc.rand_bytes(16) |> Base.encode16
byte_size(k) # => 32
Apoc.AES.encrypt(message, k)

As the bytesize of the encoded key in this example is 32 bytes the 256 bit block size will be used. However, this is not a uniformly random key in {0,1}^32. Specifically, the probability of a key containing a character other than [0-9a-f] is zero.

To avoid this issue, don’t use ASCII (e.g. hex of base 64 encoded strings) as the key. By all means, encode the key for storage purposes but make sure your key has been generated with the correct number of bytes.

k = Apoc.rand_bytes(32)
Apoc.AES.encrypt(message, k)

Apoc.encode(k) # => base 64 encoded for storage somewhere safe