TinyAES
View SourceTinyAES is a lightweight, dependency-free Elixir wrapper for AES-256-GCM encryption and decryption using Erlang's :crypto
module. It provides robust error handling, support for Additional Authenticated Data (AAD), and a simple API. The encryption key is securely retrieved from the ENCRYPTION_KEY
environment variable.
Features
- Lightweight: Less than 50 lines of core code.
- Dependency-Free: Relies only on Erlang's
:crypto
module. - Robust Error Handling: Covers returned
:error
, raised{etag, reason, stack}
exceptions, and key validation errors. - AES-256-GCM: Secure, authenticated encryption with 16-byte IV and tag.
- AAD Support: Optional Additional Authenticated Data for enhanced security.
- Key Management: Environment-based key retrieval with Base64 encoding.
- 3-tuples Compatible: Handles the latest
:crypto
exception format introduced with Erlang OTP 25.
Installation
Add TinyAES to your mix.exs
dependencies:
{:tiny_aes, "~> 0.1"}
Run mix deps.get
to fetch the dependency.
Setup
Generate a 32-byte encryption key, and add it to your .env
file:
mix run -e 'TinyAES.puts_generate_key_env()'
# Copy the output to .env:
ENCRYPTION_KEY=your_base64_encoded_key_here
The function outputs a base64-encoded key, e.g., OuaO+dtNNgxJjQLGHMLJ9m8rSQDsVdqkGrf7ySSj3Yg=
. Add the key to your .env
file:
Ensure the ENCRYPTION_KEY
environment variable is set in your application (e.g., using env_loader
or dotenv
).
Usage
Encrypt and decrypt data without optional AAD::
# Encrypt a message
plaintext = "Sensitive data"
ciphertext = TinyAES.encrypt(plaintext)
# Decrypt it
{:ok, decrypted} = TinyAES.decrypt(ciphertext)
assert decrypted == plaintext
Encrypt and decrypt data with optional AAD (e.g., user or session ID)
# Encrypt a message
plaintext = "Sensitive data"
ciphertext = TinyAES.encrypt(plaintext, "optional_aad")
# Decrypt it
{:ok, decrypted} = TinyAES.decrypt(ciphertext, "optional_aad")
assert decrypted == plaintext
Handle edge cases:
# Handle invalid input
TinyAES.decrypt("not a binary")
# {:error, "Ciphertext must be a binary with at least 32 bytes"}
# Handle missing key
System.delete_env("ENCRYPTION_KEY")
TinyAES.encrypt("test")
# {:error, "Encryption key not found in environment variable ENCRYPTION_KEY"}
API
TinyAES.encrypt(plaintext, aad \\ "")
:- Encrypts plaintext, returning
<<iv::binary-16, tag::binary-16, ciphertext::binary>>
or{:error, reason}
.
- Encrypts plaintext, returning
TinyAES.decrypt(ciphertext, aad \\ "")
:- Decrypts ciphertext, returning
{:ok, plaintext}
or{:error, reason}
.
- Decrypts ciphertext, returning
TinyAES.puts_generate_key_env()
:- Generates, prints, and returns
:ok
for a Base64-encoded 32-byte key.
- Generates, prints, and returns
TinyAES.generate_key_env()
:- Generates a Base64-encoded 32-byte key.
TinyAES.get_key_env()
:- Retrieves and decodes the key from
ENCRYPTION_KEY
returning{:ok, key}
or{:error, reason}
.
- Retrieves and decodes the key from
See HexDocs for full documentation.
Contributing
Contributions are welcome! Please open an issue or pull request on GitHub. For major changes, discuss them in an issue first. Ensure tests pass with mix test
.
License
Released under the MIT License. See the LICENSE file for details.
Acknowledgments
Developed with the help of Grok, created by xAI. Thanks to Erlang's :crypto
for providing a solid foundation.