Expand description
§XChaCha20-BLAKE3-SIV
A fast, deterministic Authenticated Encryption with Associated Data (AEAD) construction combining:
- XChaCha20 for stream-cipher confidentiality (192-bit nonce, software-efficient)
- BLAKE3 in keyed SIV (Synthetic Initialization Vector) mode for integrity and nonce-misuse resistance
§Design
This crate implements the SIV (Synthetic IV) construction defined informally as MAC-then-Encrypt:
- Derive the SIV — A 24-byte tag is produced by running keyed BLAKE3 over
(context, nonce, len(AD), len(plaintext), AD, plaintext). The domain-separation context string"XCHACHA20-BLAKE3-SIV-01"is mixed in at key-setup time, so the MAC key is bound to this specific scheme version. - Encrypt — The 24-byte SIV is used directly as the XChaCha20 nonce, producing ciphertext of exactly the same length as the plaintext (no padding).
- Authenticate — On decryption the SIV is recomputed from the recovered plaintext and compared in constant time against the stored tag. A mismatch causes the plaintext buffer to be zeroized before the error is returned.
Ciphertext layout:
┌──────────────────────┬──────────────────────────────┐
│ SIV / Tag (24 B) │ Ciphertext (= plaintext len) │
└──────────────────────┴──────────────────────────────┘§Security Properties
| Property | Guarantee |
|---|---|
| Confidentiality | XChaCha20 stream cipher |
| Integrity | BLAKE3 keyed MAC, constant-time verification |
| Nonce-misuse resistance | Nonce reuse reveals only that the same plaintext was sent |
| Deterministic | Same (key, nonce, AD, plaintext) → same ciphertext (useful for dedup) |
| Memory safety | zeroize wipes keys and failed-decryption buffers; #![forbid(unsafe_code)] |
§Quick Start
§Allocating API
The simplest interface — allocates a Vec<u8> for the ciphertext/plaintext:
use xchacha20_blake3_siv::{Cipher, Key, Nonce};
// Keys must be exactly 64 bytes: first 32 for encryption, last 32 for the MAC.
// In real code, derive this from a KDF or CSPRNG.
let key: Key = [0u8; 64];
let nonce: Nonce = [1u8; 24];
let ad = b"invoice-id:7f3a9c"; // optional context bound to the ciphertext
let plaintext = b"Amount: $9999.00";
let cipher = Cipher::new(&key)?;
let ciphertext = cipher.encrypt(&nonce, plaintext, ad)?;
// ciphertext is TAG_LEN (24) + plaintext.len() bytes — no padding.
let recovered = cipher.decrypt(&nonce, &ciphertext, ad)?;
assert_eq!(recovered, plaintext);§In-Place (Zero-Copy) API
Avoids extra allocations by operating directly on a caller-supplied buffer.
The buffer must be pre-sized to TAG_LEN + plaintext_len and the plaintext
must start at offset TAG_LEN:
use xchacha20_blake3_siv::{Cipher, TAG_LEN};
let key = [0u8; 64];
let nonce = [1u8; 24];
let msg = b"Hello, zero-copy world!";
let cipher = Cipher::new(&key)?;
// Allocate buffer with room for the tag prefix.
let mut buffer = vec![0u8; TAG_LEN + msg.len()];
buffer[TAG_LEN..].copy_from_slice(msg);
// Encrypt: writes the SIV into `buffer[..TAG_LEN]` and encrypts the rest.
cipher.encrypt_in_place(&mut buffer, msg.len(), &nonce, b"")?;
// Decrypt: returns a sub-slice of `buffer` containing the plaintext.
let plaintext = cipher.decrypt_in_place(&mut buffer, &nonce, b"")?;
assert_eq!(plaintext, msg);§When to Use This Crate
- WebAssembly: Both XChaCha20 and BLAKE3 are pure-software primitives with no
dependency on hardware AES instructions (
AES-NI/VAES). - Large payloads: BLAKE3’s internal parallelism means this construction matches or exceeds AES-256-GCM throughput for payloads larger than ~256 KiB.
- Deterministic / deduplication: If you need the same plaintext to always produce the same ciphertext (e.g., content-addressable encrypted storage), SIV is the right tool.
- Nonce-misuse resilience: Accidental nonce reuse is catastrophic for GCM but only leaks equality information under SIV.
§Security Warnings
- Key generation: always use a cryptographically secure RNG (e.g.
getrandom). - Determinism: encrypting the same
(nonce, AD, plaintext)twice reveals that you did so. Use unique nonces when traffic-analysis resistance is required. - No built-in nonce management: the caller is responsible for nonce uniqueness.
This construction is particularly well-suited for WebAssembly (WASM) environments and systems lacking hardware AES acceleration.
Structs§
- Cipher
- A SIV (Synthetic Initialization Vector) AEAD cipher using XChaCha20 and BLAKE3.
Enums§
Constants§
- KEY_LEN
- The required length of the master key in bytes (64 bytes).
- NONCE_
LEN - The length of the external nonce in bytes (24 bytes).
- TAG_LEN
- The length of the authentication tag (SIV) prepended to every ciphertext, in bytes (24 bytes).