1 unstable release
| 0.1.0 | Dec 15, 2025 |
|---|
#1969 in Cryptography
Used in enigma-protocol
34KB
810 lines
enigma-ratchet
Rust implementation of a standalone Signal-style Double Ratchet optimized for reuse in asynchronous systems. The crate focuses on determinism, explicit error handling, strict serialization, and easy integration into higher level protocols.
Features
- X25519 Diffie-Hellman ratchet with HKDF-SHA256 based root and chain KDFs
- XChaCha20-Poly1305 authenticated encryption with caller-supplied associated data
- Stable binary message header format with canonical encoding tests
- Bounded skipped-key storage for out-of-order delivery and replay defense
- Zeroization of all secret material on drop
- Comprehensive unit tests covering protocol state, KDF behavior, framing, negative flows, and limit enforcement
Quickstart
use enigma_ratchet::{RatchetKeyPair, RatchetState};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let shared_secret = [42u8; 32];
let bob_keys = RatchetKeyPair::generate();
let bob_pub = bob_keys.public();
let mut alice = RatchetState::new_alice(shared_secret, bob_pub, b"handshake")?;
let mut bob = RatchetState::new_bob(shared_secret, bob_keys, b"handshake")?;
let packet = alice.encrypt(b"hello", b"ad")?;
let plaintext = bob.decrypt(&packet, b"ad")?;
assert_eq!(plaintext, b"hello");
let response = bob.encrypt(b"hi", b"ad")?;
let echoed = alice.decrypt(&response, b"ad")?;
assert_eq!(echoed, b"hi");
Ok(())
}
new_bob does not know the remote key at creation time. Its set_remote_dh helper allows the responder to preload a known DH public key before the first ciphertext if the surrounding handshake provides it.
Serialization and Framing
Each ciphertext is framed as len(header) || header || nonce || ciphertext+tag where the header length is encoded in a two-byte big-endian integer and header length is always forty bytes. Headers contain the sender Diffie-Hellman public key plus message counters and are included in the AEAD associated data along with the application-provided context hash. The deterministic encoding is exercised in both positive and negative tests.
Testing
Run the full suite with:
cargo test
The tests cover KDF rules, header encoding, packet framing, sequential and out-of-order delivery, skip-limit enforcement, replay detection, corrupted packets, and mismatched initialization secrets. All critical responsibilities have dedicated assertions. Refer to the documents in docs/ for deeper protocol, API, and security notes.
Dependencies
~3–4.5MB
~85K SLoC