| Crates.io | vitaminc-aead |
| lib.rs | vitaminc-aead |
| version | 0.1.0-pre4 |
| created_at | 2025-11-20 11:57:10.412013+00 |
| updated_at | 2025-11-23 23:07:39.124431+00 |
| description | Authenticated Encryption with Associated Data (AEAD) primitives. Part of the Vitamin-C cryptographic suite. |
| homepage | https://cipherstash.com |
| repository | https://github.com/cipherstash/vitaminc |
| max_upload_size | |
| id | 1941858 |
| size | 47,666 |
Authenticated Encryption with Associated Data (AEAD) primitives for building secure encryption systems.
This crate is part of the Vitamin C framework to make cryptography code healthy.
AEAD (Authenticated Encryption with Associated Data) is a form of encryption that provides both confidentiality and authenticity. It ensures that:
This crate provides traits and types for implementing AEAD operations in a safe and ergonomic way.
Encrypt] and [Decrypt] traits provide a type-safe interface for encryption operationsIntoAad] trait allows multiple types to be used as additional authenticated datavitaminc-protected types to handle sensitive dataUnspecified] error type that reveals no information about failuresTo use this crate, you need to implement the [Cipher] trait for your AEAD algorithm:
use vitaminc_aead::{Cipher, Unspecified, IntoAad, LocalCipherText};
struct MyCipher {
// Your cipher implementation
}
impl Cipher for MyCipher {
fn encrypt_slice<'a, A>(
&self,
plaintext: &'a [u8],
aad: A,
) -> Result<LocalCipherText, Unspecified>
where
A: IntoAad<'a>
{
// Your encryption implementation
todo!()
}
fn encrypt_vec<'a, A>(
&self,
plaintext: Vec<u8>,
aad: A,
) -> Result<LocalCipherText, Unspecified>
where
A: IntoAad<'a>
{
// Your encryption implementation
todo!()
}
fn decrypt_vec<'a, A>(
&self,
ciphertext: LocalCipherText,
aad: A,
) -> Result<Vec<u8>, Unspecified>
where
A: IntoAad<'a>
{
// Your decryption implementation
todo!()
}
}
Once you have a [Cipher] implementation, you can use the [Encrypt] trait to encrypt various types:
use vitaminc_aead::{Encrypt, Cipher};
fn encrypt_data<C: Cipher>(cipher: &C) -> Result<(), Box<dyn std::error::Error>> {
// Encrypt a string
let encrypted_string = "secret message".encrypt(cipher)?;
// Encrypt with additional authenticated data
let encrypted_with_aad = "secret".encrypt_with_aad(cipher, "context data")?;
// Encrypt a byte array
let data = [1, 2, 3, 4, 5];
let encrypted_bytes = data.encrypt(cipher)?;
Ok(())
}
Use the [Decrypt] trait to decrypt ciphertext back to the original type:
use vitaminc_aead::{Decrypt, Cipher, LocalCipherText};
fn decrypt_data<C: Cipher>(
cipher: &C,
ciphertext: LocalCipherText
) -> Result<String, Box<dyn std::error::Error>> {
// Decrypt back to a String
let plaintext = String::decrypt(ciphertext, cipher)?;
Ok(plaintext)
}
Many types can be used as AAD through the [IntoAad] trait:
# fn main() -> Result<(), Box<dyn std::error::Error>> {
use vitaminc_aead::{Encrypt, Cipher};
use vitaminc_encrypt::{Key, Aes256Cipher};
use vitaminc_protected::Protected;
use vitaminc_random::{Generatable, SafeRand, SeedableRng};
let key = Key::random(&mut SafeRand::from_entropy())?;
let cipher = Aes256Cipher::new(&key)?;
// Use a string as AAD
"my-secret".encrypt_with_aad(&cipher, "user_id:123")?;
// Use a byte slice as AAD
"my-secret".encrypt_with_aad(&cipher, &b"metadata"[..])?;
// Use a u64 as AAD
"my-secret".encrypt_with_aad(&cipher, 42u64)?;
// Use a tuple to combine multiple AAD values
"my-secret".encrypt_with_aad(&cipher, ("user_id", "session_token"))?;
// Use no AAD
"my-secret".encrypt_with_aad(&cipher, ())?;
# Ok(())
# }
The crate integrates with vitaminc-protected to handle sensitive data safely:
# fn main() -> Result<(), Box<dyn std::error::Error>> {
use vitaminc_aead::{Encrypt, Cipher};
use vitaminc_encrypt::{Key, Aes256Cipher};
use vitaminc_protected::Protected;
use vitaminc_random::{Generatable, SafeRand, SeedableRng};
let key = Key::random(&mut SafeRand::from_entropy())?;
let cipher = Aes256Cipher::new(&key)?;
let sensitive_data = Protected::new([1, 2, 3, 4, 5]);
let encrypted = sensitive_data.encrypt(&cipher)?;
# Ok(())
# }
You can implement [Encrypt] and [Decrypt] for your own types to enable selective encryption:
use vitaminc_aead::{Encrypt, Decrypt, Cipher, IntoAad, Unspecified, LocalCipherText};
struct User {
id: u64,
email: String,
password_hash: String,
}
struct EncryptedUser {
id: u64,
email: String,
password_hash: LocalCipherText, // Only encrypt the password hash
}
impl Encrypt for User {
type Encrypted = EncryptedUser;
fn encrypt_with_aad<'a, C, A>(
self,
cipher: &C,
aad: A,
) -> Result<Self::Encrypted, Unspecified>
where
C: Cipher,
A: IntoAad<'a>,
{
Ok(EncryptedUser {
id: self.id,
email: self.email,
password_hash: self.password_hash.encrypt_with_aad(cipher, aad)?,
})
}
}
impl Decrypt for User {
type Encrypted = EncryptedUser;
fn decrypt_with_aad<'a, C, A>(
encrypted: Self::Encrypted,
cipher: &C,
aad: A,
) -> Result<Self, Unspecified>
where
C: Cipher,
A: IntoAad<'a>,
{
Ok(User {
id: encrypted.id,
email: encrypted.email,
password_hash: String::decrypt_with_aad(encrypted.password_hash, cipher, aad)?,
})
}
}
The crate provides nonce generation utilities for AEAD operations:
# fn main() -> Result<(), Box<dyn std::error::Error>> {
use vitaminc_aead::{NonceGenerator, RandomNonceGenerator};
// Create a random nonce generator for 12-byte nonces
let generator = RandomNonceGenerator::<12>::init();
let nonce = generator.generate()?;
# Ok(())
# }
Unspecified] error type is used to prevent side-channel attacks by not revealing information about failuresVitamin C is brought to you by the team at CipherStash.
License: MIT