cryptainer 2.1.0

tiny encrypted byte array container (Argon2id + AES256-GCM)
Documentation

cryptainer

Small, password-based authenticated encryption for Rust.

Encrypt byte slices or Serde-compatible structs with Argon2id and AES-256-GCM, then decrypt them with a simple, typed API. cryptainer is no_std-friendly and keeps file I/O optional.

Crates.io Documentation License

Features

  • Password-based encryption with Argon2id
  • AES-256-GCM authenticated encryption
  • no_std support with alloc
  • Optional derived-key zeroization
  • Optional file helpers through std
  • Optional bincode-backed struct encryption through derive

Quick start

Add the crate with its standard-library defaults:

[dependencies]
cryptainer = "2.1"

Encrypt bytes

use cryptainer::{decrypt_data, encrypt_data};

let mut rng = rand::rng();
let encrypted = encrypt_data("correct horse battery staple", b"hello world", &mut rng)?;
let plaintext = decrypt_data(&encrypted, "correct horse battery staple")?;

encrypt_data returns a CryptData value containing the salt, nonce, and ciphertext. Keep it together until you are ready to persist it or decrypt it.

Encrypt structs

Enable the derive feature:

[dependencies]
cryptainer = { version = "2.1", features = ["derive"] }
serde = { version = "1", features = ["derive"] }

Then derive Cryptainer alongside Serde:

use cryptainer::Cryptainer;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Cryptainer)]
struct Secret {
    message: String,
}

let mut rng = rand::rng();
let secret = Secret { message: "hello world".into() };
let encrypted = secret.encrypt("password", &mut rng)?;
let decrypted = Secret::decrypt(&encrypted, "password")?;

The derive generates encrypt and decrypt methods. Serialization uses bincode 2; encrypted data is still authenticated by AES-GCM.

Save and load files

use cryptainer::{decrypt_file, encrypt_data, save_file};

let mut rng = rand::rng();
let encrypted = encrypt_data("password", b"secret", &mut rng)?;
save_file("secret.stuff", &encrypted)?;
let plaintext = decrypt_file("secret.stuff", "password")?;

Format and security

Encrypted output is stored as:

salt (16 bytes) || nonce (12 bytes) || ciphertext

The ciphertext includes the AES-GCM authentication tag. Passwords are processed with Argon2id to derive a 256-bit encryption key. A fresh salt and nonce are generated for every call to encrypt_data; callers must provide a cryptographically secure RNG.

When enabled, the zeroize feature clears derived keys and temporary serialization buffers when they are dropped. It cannot clear passwords, caller-owned plaintext, decrypted return values, or encrypted data retained for persistence.

cryptainer does not provide password storage, password strength checking, key rotation, or secure password transport. Applications should handle those concerns separately.

API at a glance

  • encrypt_data(password, plaintext, rng) -> Result<CryptData, CryptError>
  • decrypt_data(data, password) -> Result<Vec<u8>, CryptError>
  • decrypt_bytes(data, password) -> Result<Vec<u8>, CryptError>
  • encrypt_value(value, password, rng) -> Result<CryptData, CryptError> (with derive)
  • decrypt_value(data, password) -> Result<T, CryptError> (with derive)
  • save_file(file_path, data) -> Result<(), CryptError> (std only)
  • decrypt_file(file_path, password) -> Result<Vec<u8>, CryptError> (std only)

Features

  • std (default): enables file I/O and standard library integration
  • zeroize (default): zeroizes derived keys and temporary serialized plaintext buffers where supported
  • derive: enables bincode-backed struct encryption and the Cryptainer derive

License

MIT