# cryptography

Safe, portable Rust implementations of classical and modern ciphers written
directly from the published specifications.

Project-wide implementation rules for the **root crate**:

- safe, idiomatic Rust on every public API boundary
- no C/FFI escape hatches
- as few dependencies as practical
- one optional aarch64 fast path: SHA-3 dispatches to the FEAT_SHA3 keccak
  intrinsic when the CPU advertises it (`src/hash/sha3.rs`), and falls back
  to the pure-Rust permutation otherwise

Optional sibling crates under `fast/` (Apple-Silicon AES/GHASH/SHA-256, x86
PCLMULQDQ GHASH) provide architecture-specific kernels behind explicit
`is_supported()` capability checks.  They are out of the root crate's
"no architecture intrinsics" perimeter and are tested separately.

That policy applies to the symmetric, hash, CSPRNG, and public-key layers
of the root crate alike. The goal is to keep the code readable, portable,
and auditable in one language, and to add a dependency only when it clearly
buys real interoperability or maintenance value.

Security note:

- Public-key operations are variable-time **by policy** — writing
  constant-time public-key code at the bigint level is a research-grade
  effort and out of scope for this crate. Two equivalent paths reach the
  same types: `cryptography::vt::Ecdsa` (flat re-export, kept as a hint
  that the surface is variable-time) and `cryptography::public_key::ecdsa`
  (the natural module tree). Pick whichever reads better in your code.
  X25519 / X448 are exceptions and use the constant-time RFC 7748 ladder.
- Constant-time symmetric implementations are explicitly suffixed `Ct`
  (e.g. `Aes128Ct`, `Sm4Ct`, `Zuc128Ct`); the bare-named types
  (`Aes128`, `Sm4`, `Zuc128`) are reference table-driven implementations
  and are **not** constant-time. AEAD wrappers `Gcm`, `Gmac`, `GcmVt`, and
  `GmacVt` make the choice explicit per construction.
- This crate intentionally does **not** provide an OS entropy source.
  `CtrDrbgAes256` is deterministic once seeded. All key generation, randomized
  padding, and nonce-dependent operations inherit seed quality from caller-
  supplied external entropy. Obtain entropy from OS APIs (`getentropy`,
  `SecRandomCopyBytes`, `getrandom`, or platform equivalent), and do not invent
  your own entropy source.

## Related: entropy

The [`entropy`](https://github.com/darrelllong/entropy) repository depends on
this crate and provides everything outside the cryptographic core:

- Non-cryptographic generators (LCG, MT19937, PCG, xoshiro, SFC, WyRand, …)
- Stream-cipher RNGs wrapping ciphers from this crate (ChaCha20, Rabbit, ZUC, …)
- Block-cipher CTR-mode RNGs (AES, Camellia, Twofish, Serpent, SM4, …)
- Historical/broken generators for comparison (Dual_EC_DRBG, C stdlib variants)
- Statistical test batteries: NIST SP 800-22, DIEHARD, DIEHARDER

Implemented families:

- DES and Triple-DES
- AES (`Aes128/192/256`) plus software constant-time variants (`Aes*Ct`)
- CAST-128 / CAST5 plus `Cast128Ct`
- Camellia (`Camellia128/192/256`) plus software constant-time variants
- Serpent (`Serpent128/192/256`) plus software constant-time variants
- Twofish (`Twofish128/192/256`) plus software constant-time variants
- SEED plus `SeedCt`
- SIMON (all 10 published variants)
- SPECK (all 10 published variants)
- PRESENT (`Present80` / `Present128`) plus software constant-time variants
- Magma plus `MagmaCt`
- Grasshopper plus `GrasshopperCt`
- SM4 / SMS4 plus `Sm4Ct`
- ChaCha20 and XChaCha20
- Poly1305 (one-time authenticator)
- ChaCha20-Poly1305 (RFC 8439 AEAD)
- EAX, OCB3, SIV, and AES-GCM-SIV AEADs
- Salsa20
- Rabbit
- SNOW 3G plus `Snow3gCt`
- ZUC-128 plus `Zuc128Ct`

Supporting primitives:

- MD5 (`Md5`) for legacy compatibility
- RIPEMD-160 (`Ripemd160`) for legacy compatibility
- SHA-3 (`Sha3_224/256/384/512`)
- SHAKE (`Shake128`, `Shake256`)
- HMAC (`Hmac<H>`) and HKDF (`Hkdf<H>`)
- Generic block-cipher modes: `Ecb`, `Cbc`, `Cfb`, `Cfb8`, `Ofb`, `Ctr`,
  `Cmac`, `Ccm`, `Gcm`, `GcmVt`, `Gmac`, `GmacVt`, `Xts`, `AesKeyWrap`,
  `Eax`, `Ocb`, `Siv`, `Aes128GcmSiv`, `Aes256GcmSiv`
- SP 800-90A Rev. 1: `CtrDrbgAes256`

RFC 7748 constant-time ECDH (under `cryptography::vt`):

- `X25519` — Curve25519 ECDH, 32-byte scalar / u-coordinate / shared secret.
- `X448` — Curve448 ECDH, 56-byte scalar / u-coordinate / shared secret.

Both are constant-time in the secret scalar (mask-driven `cswap`, fixed-radix
limbs, no data-dependent branches or table lookups), and both are validated
against the full RFC 7748 §5.2 KAT set including the 1 000 000-iteration
vectors.

Asymmetric post-quantum work:

- ML-KEM (Kyber) under `cryptography::vt`:
  `MlKem`, `MlKemParameterSet`, typed key/ciphertext containers, strict
  encoding validation, and in-tree arithmetic (`keygen`/`encaps`/`decaps`).
- ML-DSA (Dilithium) under `cryptography::vt`:
  `MlDsa`, `MlDsaParameterSet`, typed key/signature containers, strict
  encoding validation, and in-tree arithmetic (`keygen`/`sign`/`verify`).

Documentation:

- [ANALYSIS.md](ANALYSIS.md): top-level overview, coverage, and experiment notes
- [SYMMETRIC.md](SYMMETRIC.md): symmetric ciphers, modes, hashes, and throughput
- [ASYMMETRIC.md](ASYMMETRIC.md): public-key primitives, wrappers, serialization, and latency
- [POSTQUANTUM.md](POSTQUANTUM.md): ML-KEM/ML-DSA APIs, design rationale, and PQ benchmarks

## HOWTO

### Keys, IVs, nonces, and counters

Most constructors encode the required key size in the type signature, so the
expected size is visible in the API:

- `Aes128`, `Sm4`, `Seed`, `Camellia128`, `Serpent128`, `Twofish128`, and many
  others take `&[u8; 16]`
- `Aes192`, `Camellia192`, `Serpent192`, `Twofish192` take `&[u8; 24]`
- `Aes256`, `Camellia256`, `Serpent256`, `Twofish256` take `&[u8; 32]`
- `Present80` takes `&[u8; 10]`; `Present128` takes `&[u8; 16]`
- `Des` uses an 8-byte DES key; `TripleDes::new_2key` uses 16 bytes; `TripleDes::new_3key` uses 24 bytes

The main variable-length exceptions are:

- `Cast128::with_key_bytes(&key)` for 5..=16-byte keys
- `Salsa20::with_key_bytes(&key, &nonce)` for 16- or 32-byte keys

Stream-cipher nonce/IV sizes are fixed by the constructor:

- `Salsa20`: 16- or 32-byte key, 8-byte nonce
- `Rabbit`: 16-byte key, 8-byte IV
- `ChaCha20`: 12-byte nonce, optional 32-bit block counter via `with_counter`
- `XChaCha20`: 24-byte nonce, optional 32-bit block counter via `with_counter`
- `Snow3g`: 16-byte key and 16-byte IV
- `Zuc128`: 16-byte key and 16-byte IV

The mode wrappers follow the block size or the standard profile:

- `Cbc`, `Cfb`, `Ofb`, and block-cipher `Ctr` take an IV/counter block exactly
  one cipher block long
- `Gcm` uses a 12-byte nonce in the 96-bit standard fast path
- `Xts` takes a 16-byte tweak value and two independent 128-bit block-cipher
  keys (for example two separate `Aes128` instances)

### Generic block-cipher example

All block ciphers implement the shared `BlockCipher` trait for in-place
operation on a mutable byte slice:

```rust
use cryptography::{Aes128, BlockCipher};

let key = [0u8; 16]; // AES-128 = 16-byte key
let cipher = Aes128::new(&key);
let mut block = [0u8; 16];

cipher.encrypt(&mut block);
cipher.decrypt(&mut block);
```

### Fixed-size block example

Each block cipher type also exposes typed helpers when the block size is known
at compile time:

```rust
use cryptography::Sm4;

let key = [0u8; 16]; // SM4 = 16-byte key
let cipher = Sm4::new(&key);
let block = [0u8; 16];

let ct = cipher.encrypt_block(&block);
let pt = cipher.decrypt_block(&ct);
assert_eq!(pt, block);
```

### Constant-time example

If you need the software constant-time path, use the dedicated `Ct` type:

```rust
use cryptography::Aes128Ct;

let key = [0u8; 16];
let cipher = Aes128Ct::new(&key);
let block = [0u8; 16];

let ct = cipher.encrypt_block(&block);
let pt = cipher.decrypt_block(&ct);
assert_eq!(pt, block);
```

### Modes of operation example

The generic mode wrappers accept any `BlockCipher` in the crate:

```rust
use cryptography::{Aes128, Cbc, Cmac, Ctr, Gcm, Xts};

let key = [0u8; 16];
let cipher = Aes128::new(&key);

let mut cbc_buf = [0u8; 32];
let iv = [0u8; 16]; // one AES block
Cbc::new(cipher).encrypt_nopad(&iv, &mut cbc_buf);

let mut ctr_buf = [0u8; 37];
let counter = [0u8; 16]; // one AES block
Ctr::new(Aes128::new(&key)).apply_keystream(&counter, &mut ctr_buf);

let tag = Cmac::new(Aes128::new(&key)).compute(b"header and body");
assert_eq!(tag.len(), 16);

let mut gcm_buf = [0u8; 23];
let nonce = [0u8; 12]; // standard 96-bit GCM nonce
let aad = b"header";
let tag = Gcm::new(Aes128::new(&key)).encrypt(&nonce, aad, &mut gcm_buf);
assert!(Gcm::new(Aes128::new(&key)).decrypt(&nonce, aad, &mut gcm_buf, &tag));

let aead = cryptography::ChaCha20Poly1305::new(&[0u8; 32]);
let (ct, tag) = aead.encrypt(&nonce, aad, b"hello");
assert_eq!(aead.decrypt(&nonce, aad, &ct, &tag), Some(b"hello".to_vec()));

let mut sector = [0u8; 32];
let tweak = [0u8; 16]; // one 16-byte tweak block
let data_key = [0u8; 16];
let tweak_key = [1u8; 16];
Xts::new(Aes128::new(&data_key), Aes128::new(&tweak_key)).encrypt_sector(&tweak, &mut sector);
```

The mode layer implements:

- SP 800-38A: ECB, CBC, CFB (full-block), CFB8, OFB, CTR
- SP 800-38B: CMAC
- SP 800-38C: CCM
- SP 800-38D: GCM, GMAC (`Gcm`/`Gmac` constant-time, `GcmVt`/`GmacVt` variable-time)
- SP 800-38E: XTS (for 128-bit block ciphers)
- SP 800-38F / RFC 3394: AES Key Wrap (`AesKeyWrap`, no padding)
- RFC 5297: SIV
- RFC 7253: OCB3
- RFC 8452: AES-GCM-SIV (`Aes128GcmSiv`, `Aes256GcmSiv`)
- RFC 8439: Poly1305, ChaCha20-Poly1305
- Bellare-Rogaway-Wagner EAX

`Gcm` enforces the SP 800-38D per-call payload bound of
`68_719_476_704` bytes (`2^32 - 2` counter blocks) to prevent counter wrap.

### Stream-cipher example

SNOW 3G and ZUC produce keystream words and can fill a caller-supplied
buffer, while Salsa20, ChaCha20, and XChaCha20 apply their keystream directly
to plaintext or ciphertext:

```rust
use cryptography::{ChaCha20, Salsa20, Snow3g, XChaCha20, Zuc128};

let mut msg = *b"example message...";
let mut salsa = Salsa20::new(&[0u8; 32], &[0u8; 8]); // 32-byte key, 8-byte nonce
let mut chacha = ChaCha20::with_counter(&[1u8; 32], &[0u8; 12], 7); // 32-byte key, 12-byte nonce, u32 counter
let mut xchacha = XChaCha20::with_counter(&[2u8; 32], &[0u8; 24], 7); // 32-byte key, 24-byte nonce, u32 counter
let mut buf = [0u8; 64];
let mut snow = Snow3g::new(&[3u8; 16], &[0u8; 16]); // 16-byte key, 16-byte IV
let mut zuc = Zuc128::new(&[0u8; 16], &[0u8; 16]); // 16-byte key, 16-byte IV

salsa.apply_keystream(&mut msg);
chacha.apply_keystream(&mut msg);
xchacha.apply_keystream(&mut msg);
snow.fill(&mut buf);
zuc.fill(&mut buf);
```

The crate root exports:

- `StreamCipher` for byte-oriented keystream APIs
- `Aead` for detached-tag authenticated encryption wrappers, implemented for
  `Gcm`, `GcmVt`, `Ccm`, `Eax`, `Ocb`, `Siv`, `Aes128GcmSiv`, `Aes256GcmSiv`,
  and `ChaCha20Poly1305`

### Hash / XOF / HMAC example

SHA-1 / SHA-2 / SHA-3 expose fixed-output hashes, and SHAKE exposes
extendable-output functions:

For keyed integrity, do not treat raw SHA-1 / SHA-2 digests as MACs. Those
Merkle-Damgard hashes have the usual length-extension caveat; use `Hmac<H>`
instead, or prefer SHA-3 / SHAKE when sponge-based hashing is a better fit.

```rust
use cryptography::{Digest, Hmac, Sha256, Sha3_256, Shake128};

let digest = Sha256::digest(b"abc");
let mut out = [0u8; 32];
Shake128::digest(b"abc", &mut out);
let tag = Hmac::<Sha3_256>::compute(b"key", b"message");

assert_eq!(digest.len(), 32);
assert_eq!(out.len(), 32);
assert_eq!(tag.len(), Sha3_256::OUTPUT_LEN);
```

### CSPRNG example

The shared `Csprng` trait lets callers fill caller-owned buffers regardless of
which generator is underneath:

```rust
use cryptography::{Csprng, CtrDrbgAes256};

let seed_material = [0u8; 48]; // 32-byte AES key + 16-byte V
let mut drbg = CtrDrbgAes256::new(&seed_material);
let mut out = [0u8; 32];
drbg.fill_bytes(&mut out);
```

### Fast vs `Ct` variants

For AES, CAST-128, DES, Twofish, Magma, Grasshopper, SM4, SNOW 3G, and ZUC,
the default type is the fast software implementation and the `Ct` type is the
separate constant-time software path.

Use the fast path when:

- you want the fastest portable software implementation in this crate
- your threat model does not require side-channel-resistant software behavior

Use the `Ct` path when:

- you need a software-only constant-time implementation
- you are willing to pay the throughput penalty documented in `ANALYSIS.md`

The `Ct` types are distinct on purpose; the API makes the tradeoff explicit.

### Wiping caller-owned keys

Cipher types that retain expanded round keys also expose `new_wiping(...)`
constructors. These build the cipher, then erase the caller-provided key
buffer:

```rust
use cryptography::Aes256Ct;

let mut key = [0x42u8; 32];
let _cipher = Aes256Ct::new_wiping(&mut key);

assert_eq!(key, [0u8; 32]);
```

## How To Verify Correctness

Run the full suite:

```text
cargo test
```

Run one family:

```text
cargo test aes::tests
cargo test cast128::tests
cargo test camellia::tests
cargo test des::tests
cargo test grasshopper::tests
cargo test magma::tests
cargo test present::tests
cargo test serpent::tests
cargo test seed::tests
cargo test chacha20::tests
cargo test simon::tests
cargo test sm4::tests
cargo test speck::tests
cargo test twofish::tests
cargo test salsa20::tests
cargo test snow3g::tests
cargo test zuc::tests
cargo test public_key::
```

Coverage is in-module, not in separate test scripts. Each cipher family ships
its own known-answer vectors and fast-vs-`Ct` equivalence tests where both
paths exist.

The public-key tests cover raw arithmetic vectors, wrapper round-trips, RSA
OAEP/PSS behavior, DSA signing and verification, key serialization, and
OpenSSL interoperability checks where real standards exist.

The generic mode layer is covered in-module too:

```text
cargo test modes::tests
```

## How To Benchmark

All publication-facing benchmarks use [pilot-bench](https://github.com/darrelllong/pilot-bench).

Build the Pilot workload binaries:

```text
cargo build --release --bin pilot_cipher --bin pilot_pk
```

Run symmetric throughput:

```text
bash scripts/bench_all.sh
```

Run public-key latency:

```text
bash scripts/bench_all_pk_full.sh
```

Optional tuning knobs:

```text
PILOT_PRESET=quick|normal|strict
PILOT_CIPHER_BYTES=262144   # bytes per pilot_cipher invocation
PILOT_PK_ITERS_PERCENT=25   # scales per-invocation loop counts in pilot_pk
```

Pilot controls repetition and stop criteria from observed variance, so slow
operations (for example `sm4` / `sm4ct`) no longer rely on hand-picked loop
counts.

## Public-Key How To

The variable-time public-key module is intentionally explicit under
`cryptography::vt` and exposes three layers:

- core arithmetic primitives: `Rsa`, `Dsa`, `Cocks`, `ElGamal`, `Rabin`, `Paillier`, `SchmidtSamoa`
- shared arithmetic support: `BigUint`, `BigInt`, `MontgomeryCtx`
- usable wrappers:
  - `RsaOaep<H>` and `RsaPss<H>` for standards-based RSA encryption/signatures
  - standard RSA key externalization via PKCS #1 / PKCS #8 / SPKI in DER or PEM
  - crate-defined DER/PEM/XML key externalization for the non-RSA schemes, including `Dsa`
  - byte-to-byte encrypt/decrypt helpers for all implemented encryption-capable schemes
  - byte-to-byte sign/verify helpers for signature-capable schemes (`Dsa`, `RsaPss<H>`)
  - built-in key generation for all implemented public-key schemes
  - Paillier helper operations: ciphertext addition and rerandomization

Generate an RSA key pair from a CSPRNG:

```rust
use cryptography::vt::Rsa;
use cryptography::CtrDrbgAes256;

let seed = [0x55u8; 48];
let mut drbg = CtrDrbgAes256::new(&seed);
let (public, private) = Rsa::generate(&mut drbg, 512).expect("RSA key");
```

Persist the RSA key pair in modern standard containers:

```rust
let private_pem = private.to_pkcs8_pem();
let public_pem = public.to_spki_pem();

let private_again =
    cryptography::vt::RsaPrivateKey::from_pkcs8_pem(&private_pem).expect("PKCS #8");
let public_again =
    cryptography::vt::RsaPublicKey::from_spki_pem(&public_pem).expect("SPKI");

assert_eq!(private_again, private);
assert_eq!(public_again, public);
```

If you want a simple human-readable export for debugging, RSA also has the same
flat XML convenience format as the non-RSA schemes:

```rust
let private_xml = private.to_xml();
let public_xml = public.to_xml();

let private_again = cryptography::vt::RsaPrivateKey::from_xml(&private_xml).expect("xml");
let public_again = cryptography::vt::RsaPublicKey::from_xml(&public_xml).expect("xml");

assert_eq!(private_again, private);
assert_eq!(public_again, public);
```

Persist a non-RSA key pair in the crate-defined portable format:

```rust
use cryptography::vt::Paillier;
use cryptography::CtrDrbgAes256;

let mut drbg = CtrDrbgAes256::new(&[0x23; 48]);
let (public, private) = Paillier::generate(&mut drbg, 512).expect("Paillier key");

let public_pem = public.to_pem();
let private_pem = private.to_pem();

let public_again = cryptography::vt::PaillierPublicKey::from_pem(&public_pem).expect("public");
let private_again = cryptography::vt::PaillierPrivateKey::from_pem(&private_pem).expect("private");

assert_eq!(public_again, public);
assert_eq!(private_again, private);
```

The same non-RSA keys can also be exported as flat XML:

```rust
let public_xml = public.to_xml();
let private_xml = private.to_xml();

let public_again = cryptography::vt::PaillierPublicKey::from_xml(&public_xml).expect("public");
let private_again = cryptography::vt::PaillierPrivateKey::from_xml(&private_xml).expect("private");

assert_eq!(public_again, public);
assert_eq!(private_again, private);
```

Encrypt and decrypt with `RSAES-OAEP`:

```rust
use cryptography::vt::RsaOaep;
use cryptography::{CtrDrbgAes256, Sha256};

let mut drbg = CtrDrbgAes256::new(&[0x11; 48]);
// The OAEP label is an optional context string. The empty label is the
// standard default when you do not need domain separation.
let ciphertext =
    RsaOaep::<Sha256>::encrypt_rng(&public, b"", b"hello", &mut drbg).expect("OAEP");
let plaintext = RsaOaep::<Sha256>::decrypt(&private, b"", &ciphertext).expect("OAEP");

assert_eq!(plaintext, b"hello");
```

Sign and verify with `RSASSA-PSS`:

```rust
use cryptography::vt::RsaPss;
use cryptography::{CtrDrbgAes256, Sha256};

let mut drbg = CtrDrbgAes256::new(&[0x22; 48]);
let signature = RsaPss::<Sha256>::sign_rng(&private, b"message", &mut drbg).expect("PSS");
assert!(RsaPss::<Sha256>::verify(&public, b"message", &signature));
```

Generate and use a `DSA` key pair:

```rust
use cryptography::vt::Dsa;
use cryptography::{CtrDrbgAes256, Sha256};

let mut drbg = CtrDrbgAes256::new(&[0x24; 48]);
let (public, private) = Dsa::generate(&mut drbg, 256).expect("DSA key");
let signature = private
    .sign_message_bytes::<Sha256>(b"message")
    .expect("DSA sign");
assert!(public.verify_message_bytes::<Sha256>(b"message", &signature));
```

Generate and use an `ElGamal` key pair:

```rust
use cryptography::vt::ElGamal;
use cryptography::CtrDrbgAes256;

let mut drbg = CtrDrbgAes256::new(&[0x33u8; 48]);
let (public, private) = ElGamal::generate(&mut drbg, 256).expect("ElGamal key");
let ciphertext = public.encrypt_bytes(b"hi", &mut drbg).expect("message fits in F_p");
let plaintext = private.decrypt_bytes(&ciphertext).expect("valid ciphertext");

assert_eq!(plaintext, b"hi");
```

The other schemes follow the same pattern: the arithmetic primitive stays
available, and the usable layer exposes byte-to-byte helpers. `Paillier` also
keeps its homomorphic operations visible:

```rust
use cryptography::vt::{BigUint, Paillier};
use cryptography::CtrDrbgAes256;

let p = BigUint::from_u64(257);
let q = BigUint::from_u64(263);
let (public, private) = Paillier::from_primes(&p, &q).expect("Paillier key");
let mut drbg = CtrDrbgAes256::new(&[0x52u8; 48]);

let left = public.encrypt(b"\x12", &mut drbg).expect("message fits");
let right = public.encrypt(b"\x34", &mut drbg).expect("message fits");
let combined = public
    .add_ciphertexts(&left, &right)
    .expect("ciphertexts are in range");

assert_eq!(private.decrypt(&combined), b"\x46");
```

If you want the ciphertext as bytes instead of a scheme-native integer or
pair, use the dedicated byte-to-byte helpers:

```rust
let ciphertext = public
    .encrypt_bytes(b"\x2A", &mut drbg)
    .expect("message fits");
let plaintext = private.decrypt_bytes(&ciphertext).expect("valid ciphertext");
assert_eq!(plaintext, b"\x2A");
```

The same byte-oriented APIs work directly on file contents: read the file into
a byte buffer, call `encrypt_bytes` / `decrypt_bytes`, and write the returned
buffer back out. `RSA` is the only encryption scheme here with RFC/NIST
message formatting; the other public-key encryption schemes use explicit
crate-defined wrappers and serialization, which is documented in
[ASYMMETRIC.md](ASYMMETRIC.md). `DSA` and `ECDSA` already follow their
published signature standards directly rather than adding a second padding
layer on top.

To run one public-key operation directly under Pilot:

```text
~/pilot-bench/build/cli/bench run_program --preset quick \
  --pi "rsa_sign_2048,ms/op,0,1,1" \
  -- ./target/release/pilot_pk rsa_sign_2048
```

Production note:
- The standards-backed RSA wrappers (`OAEP`, `PSS`, and standard key
  formats) are the intended path for modern use in this crate.
- The historical schemes and the exposed raw primitives are included as
  specialized primitives. Treat them as specialized tools, not as the
  default choice for new deployments.

## Design Notes

- The core ciphers, hashes, modes, CSPRNG, and public-key arithmetic are
  written in safe, portable Rust without architecture intrinsics.
- Two narrow, deliberate exceptions to the "no `unsafe`" rule:
  - `crate::ct::zeroize_slice` uses `ptr::write_volatile` so the compiler
    cannot elide key-clearing writes.
  - `src/hash/sha3.rs` includes an aarch64 FEAT_SHA3 fast path
    (`keccak_f1600_sha3`) gated on runtime feature detection, with the
    portable scalar Keccak-f[1600] kept as the always-correct fallback. This
    is the only architecture-specific path in the in-tree library; AES does
    not use AES-NI / AESE intrinsics in `src/`.
- Optional alternative kernels (Apple Silicon and x86 "go-fast") live under
  `fast/` outside the main library tree.
- No heap allocation inside block encrypt/decrypt paths.
- Benchmark and test coverage are tracked in [ANALYSIS.md](ANALYSIS.md).
- Reference PDFs used during implementation live in `pubs/`.

## Local PDFs

The `pubs/` directory carries one or more local PDFs for every cipher
family and supporting primitive covered in this repository:

- AES: `fips197.pdf`, `boyar-peralta-2011-a-depth-16-circuit-for-the-aes-s-box.pdf`
- CAST-128 / CAST5: `rfc2144-cast128.pdf`
- Camellia: `camellia-specification.pdf`
- DES / 3DES: `fips46-3.pdf`, `nist-sp-800-67r2.pdf`
- PRESENT: `present-ches2007.pdf`
- Serpent: `serpent.pdf`
- Twofish: `twofish-paper.pdf`
- SEED: `rfc4009-seed-algorithm.pdf`, `rfc4196-seed-ipsec.pdf`
- SHA-1 / SHA-2: `fips180-4.pdf`
- SHA-3 / SHAKE: `fips202.pdf`
- HMAC: `fips198-1.pdf`
- DRBGs: `sp800-90a-r1.pdf`
- Entropy engineering and failure analysis: `hughes-2022-badrandom-the-effect-and-mitigations-for-low-entropy-random-numbers-in-tls.pdf`
- Bigint arithmetic kernels: `comba-1990-exponentiation-cryptosystems-on-the-ibm-pc.pdf`, `karatsuba-ofman-1963-multiplication-of-multidigit-numbers-on-automata.pdf`
- Public-key primitives and RSA standards: `cocks-1973-note-on-non-secret-encryption.pdf`, `rsa-1978.pdf`, `elgamal-1985.pdf`, `rabin-1979-digitalized-signatures-and-public-key-functions.pdf`, `paillier-1999.pdf`, `schmidt-samoa.pdf`, `rfc8017-pkcs1-v2_2.pdf`, `sp800-56b-r2.pdf`, `fips186-5.pdf`
- Post-quantum standards: `fips203-ml-kem.pdf`, `fips204-ml-dsa.pdf`
- Hash standards/papers: `rfc1321-md5.pdf`, `ripemd-160-a-strengthened-version-of-ripemd.pdf`, `fips180-4.pdf`, `fips202.pdf`
- Modes of operation: `sp800-38a.pdf`, `sp800-38b.pdf`, `sp800-38c.pdf`, `sp800-38d.pdf`, `sp800-38e.pdf`, `sp800-38f.pdf`, `rfc3394-aes-key-wrap.pdf`, `rfc5297-siv.pdf`, `rfc7253-ocb.pdf`, `rfc8452-aes-gcm-siv.pdf`
- SIMON / SPECK: `simon_speck_2013.pdf`
- Grasshopper: `rfc7801-kuznyechik.pdf`
- Magma: `rfc8891-magma.pdf`
- SM4: `sm4-linear-cryptanalysis-2024.pdf` (the official GM/T host is not reachable from this sandbox, so the checked-in local PDF is a public SM4-family paper)
- ChaCha20 / XChaCha20: `chacha-20080128.pdf`, `rfc8439-chacha20-poly1305.pdf`, `draft-irtf-cfrg-xchacha-03.pdf`
- Salsa20: `salsafamily-20071225.pdf`
- Rabbit: `rfc4503-rabbit.pdf`
- SNOW 3G: `ts-135216-snow3g.pdf`
- ZUC-128: `ts-135222-zuc.pdf`

## References

Local copies of implementation-specific papers live in `pubs/`. The
Boyar-Peralta AES S-box circuit paper is stored at
`pubs/boyar-peralta-2011-a-depth-16-circuit-for-the-aes-s-box.pdf`.

```bibtex
@misc{simon-speck-2013,
  author       = {Ray Beaulieu and Douglas Shors and Jason Smith and
                  Stefan Treatman-Clark and Bryan Weeks and Louis Wingers},
  title        = {The {SIMON} and {SPECK} Families of Lightweight Block Ciphers},
  howpublished = {{IACR} Cryptology ePrint Archive, Report 2013/404},
  year         = {2013},
  url          = {https://eprint.iacr.org/2013/404},
}

@techreport{fips197,
  author      = {{National Institute of Standards and Technology}},
  title       = {Advanced Encryption Standard ({AES})},
  institution = {National Institute of Standards and Technology},
  type        = {{Federal Information Processing Standard}},
  number      = {FIPS PUB 197},
  year        = {2001},
  month       = nov,
  url         = {https://csrc.nist.gov/publications/detail/fips/197/final},
}

@techreport{fips202,
  author      = {{National Institute of Standards and Technology}},
  title       = {{SHA}-3 Standard: Permutation-Based Hash and Extendable-Output Functions},
  institution = {National Institute of Standards and Technology},
  type        = {{Federal Information Processing Standard}},
  number      = {FIPS PUB 202},
  year        = {2015},
  month       = aug,
  url         = {https://csrc.nist.gov/pubs/fips/202/final},
}

@techreport{fips180-4,
  author      = {{National Institute of Standards and Technology}},
  title       = {Secure Hash Standard ({SHS})},
  institution = {National Institute of Standards and Technology},
  type        = {{Federal Information Processing Standard}},
  number      = {FIPS PUB 180-4},
  year        = {2015},
  month       = aug,
  url         = {https://csrc.nist.gov/pubs/fips/180-4/upd1/final},
}

@techreport{rfc1321,
  author      = {R. Rivest},
  title       = {The {MD5} Message-Digest Algorithm},
  type        = {{RFC}},
  number      = {1321},
  institution = {IETF},
  year        = {1992},
  month       = apr,
  doi         = {10.17487/RFC1321},
  url         = {https://www.rfc-editor.org/rfc/rfc1321},
  note        = {Local copy: pubs/rfc1321-md5.pdf},
}

@inproceedings{dobbertin-bosselaers-preneel-1996-ripemd160,
  author    = {Hans Dobbertin and Antoon Bosselaers and Bart Preneel},
  title     = {{RIPEMD}-160: A Strengthened Version of {RIPEMD}},
  booktitle = {Fast Software Encryption},
  series    = {Lecture Notes in Computer Science},
  volume    = {1039},
  pages     = {71--82},
  year      = {1996},
  publisher = {Springer},
  doi       = {10.1007/3-540-60865-6_46},
  url       = {https://link.springer.com/chapter/10.1007/3-540-60865-6_46},
  note      = {Local copy: pubs/ripemd-160-a-strengthened-version-of-ripemd.pdf},
}

@techreport{fips198-1,
  author      = {{National Institute of Standards and Technology}},
  title       = {The Keyed-Hash Message Authentication Code ({HMAC})},
  institution = {National Institute of Standards and Technology},
  type        = {{Federal Information Processing Standard}},
  number      = {FIPS PUB 198-1},
  year        = {2008},
  month       = jul,
  url         = {https://csrc.nist.gov/pubs/fips/198-1/final},
}

@techreport{fips186-5,
  author      = {{National Institute of Standards and Technology}},
  title       = {Digital Signature Standard ({DSS})},
  institution = {National Institute of Standards and Technology},
  type        = {{Federal Information Processing Standard}},
  number      = {FIPS PUB 186-5},
  year        = {2023},
  month       = feb,
  url         = {https://csrc.nist.gov/pubs/fips/186-5/final},
}

@misc{sp800-90a-r1,
  author       = {{National Institute of Standards and Technology}},
  title        = {Recommendation for Random Number Generation Using Deterministic Random Bit Generators},
  howpublished = {Special Publication 800-90A Revision 1},
  year         = {2015},
  month        = jun,
  url          = {https://csrc.nist.gov/pubs/sp/800/90/a/r1/final},
}

@phdthesis{hughes-2022-badrandom,
  author = {James P. Hughes},
  title  = {{BADRANDOM: The Effect and Mitigations for Low Entropy Random Numbers in TLS}},
  school = {University of California, Santa Cruz},
  year   = {2022},
  month  = feb,
  note   = {Local copy: pubs/hughes-2022-badrandom-the-effect-and-mitigations-for-low-entropy-random-numbers-in-tls.pdf},
}

@misc{sp800-56b-r2,
  author       = {{National Institute of Standards and Technology}},
  title        = {Recommendation for Pair-Wise Key-Establishment Using Integer Factorization Cryptography},
  howpublished = {Special Publication 800-56B Revision 2},
  year         = {2019},
  month        = mar,
  url          = {https://csrc.nist.gov/pubs/sp/800/56/b/r2/final},
}

@article{cocks-1973,
  author  = {Clifford Cocks},
  title   = {A Note on Non-Secret Encryption},
  journal = {{CESG} Research Memorandum},
  year    = {1973},
}

@article{rsa-1978,
  author  = {Ronald L. Rivest and Adi Shamir and Leonard Adleman},
  title   = {A Method for Obtaining Digital Signatures and Public-Key Cryptosystems},
  journal = {Communications of the ACM},
  volume  = {21},
  number  = {2},
  pages   = {120--126},
  year    = {1978},
  doi     = {10.1145/359340.359342},
}

@misc{rfc8017,
  author       = {K. Moriarty and B. Kaliski and J. Jonsson and A. Rusch},
  title        = {{PKCS} \#1: RSA Cryptography Specifications Version 2.2},
  howpublished = {RFC 8017},
  year         = {2016},
  month        = nov,
  doi          = {10.17487/RFC8017},
  url          = {https://www.rfc-editor.org/rfc/rfc8017},
}

@article{elgamal-1985,
  author  = {Taher ElGamal},
  title   = {A Public Key Cryptosystem and a Signature Scheme Based on Discrete Logarithms},
  journal = {{IEEE} Transactions on Information Theory},
  volume  = {31},
  number  = {4},
  pages   = {469--472},
  year    = {1985},
  doi     = {10.1109/TIT.1985.1057074},
}

@article{rabin-1979,
  author  = {Michael O. Rabin},
  title   = {Digitalized Signatures and Public-Key Functions as Intractable as Factorization},
  journal = {MIT Laboratory for Computer Science Technical Report},
  number  = {MIT/LCS/TR-212},
  year    = {1979},
}

@inproceedings{paillier-1999,
  author    = {Pascal Paillier},
  title     = {Public-Key Cryptosystems Based on Composite Degree Residuosity Classes},
  booktitle = {Advances in Cryptology --- EUROCRYPT '99},
  series    = {Lecture Notes in Computer Science},
  volume    = {1592},
  pages     = {223--238},
  year      = {1999},
  publisher = {Springer},
  doi       = {10.1007/3-540-48910-X_16},
}

@inproceedings{schmidt-samoa-2005,
  author    = {Katja Schmidt-Samoa},
  title     = {A New Rabin-Type Trapdoor Permutation Equivalent to Factoring},
  booktitle = {Electronic Notes in Theoretical Computer Science},
  volume    = {157},
  pages     = {79--94},
  year      = {2006},
  publisher = {Elsevier},
  doi       = {10.1016/j.entcs.2005.11.052},
}

@article{comba-1990,
  author  = {Paul G. Comba},
  title   = {Exponentiation Cryptosystems on the {IBM} {PC}},
  journal = {{IBM} Systems Journal},
  volume  = {29},
  number  = {4},
  pages   = {526--538},
  year    = {1990},
}

@article{karatsuba-ofman-1963,
  author  = {Anatolii A. Karatsuba and Yuri Ofman},
  title   = {Multiplication of Multidigit Numbers on Automata},
  journal = {Soviet Physics Doklady},
  volume  = {7},
  pages   = {595--596},
  year    = {1963},
  note    = {English translation of Doklady Akademii Nauk SSSR 145(2):293--294 (1962)},
}

@misc{sp800-38a,
  author       = {{National Institute of Standards and Technology}},
  title        = {Recommendation for Block Cipher Modes of Operation: Methods and Techniques},
  howpublished = {Special Publication 800-38A},
  year         = {2001},
  month        = dec,
  url          = {https://csrc.nist.gov/pubs/sp/800/38/a/final},
}

@misc{sp800-38b,
  author       = {{National Institute of Standards and Technology}},
  title        = {Recommendation for Block Cipher Modes of Operation: The {CMAC} Mode for Authentication},
  howpublished = {Special Publication 800-38B},
  year         = {2005},
  month        = may,
  url          = {https://csrc.nist.gov/pubs/sp/800/38/b/final},
}

@misc{sp800-38c,
  author       = {{National Institute of Standards and Technology}},
  title        = {Recommendation for Block Cipher Modes of Operation: The {CCM} Mode for Authentication and Confidentiality},
  howpublished = {Special Publication 800-38C},
  year         = {2004},
  month        = may,
  url          = {https://csrc.nist.gov/pubs/sp/800/38/c/final},
  note         = {Local copy: pubs/sp800-38c.pdf},
}

@misc{sp800-38d,
  author       = {{National Institute of Standards and Technology}},
  title        = {Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode ({GCM}) and {GMAC}},
  howpublished = {Special Publication 800-38D},
  year         = {2007},
  month        = nov,
  url          = {https://csrc.nist.gov/pubs/sp/800/38/d/final},
}

@misc{sp800-38e,
  author       = {{National Institute of Standards and Technology}},
  title        = {Recommendation for Block Cipher Modes of Operation: The {XTS}-{AES} Mode for Confidentiality on Storage Devices},
  howpublished = {Special Publication 800-38E},
  year         = {2010},
  month        = jan,
  url          = {https://csrc.nist.gov/pubs/sp/800/38/e/final},
}

@misc{sp800-38f,
  author       = {{National Institute of Standards and Technology}},
  title        = {Recommendation for Block Cipher Modes of Operation: Methods for Key Wrapping},
  howpublished = {Special Publication 800-38F},
  year         = {2012},
  month        = dec,
  url          = {https://csrc.nist.gov/pubs/sp/800/38/f/final},
}

@techreport{rfc3394,
  author      = {J. Schaad and R. Housley},
  title       = {Advanced Encryption Standard ({AES}) Key Wrap Algorithm},
  type        = {{RFC}},
  number      = {3394},
  institution = {IETF},
  year        = {2002},
  month       = sep,
  doi         = {10.17487/RFC3394},
  url         = {https://www.rfc-editor.org/rfc/rfc3394},
  note        = {Local copy: pubs/rfc3394-aes-key-wrap.pdf},
}

@techreport{rfc5297,
  author      = {P. Rogaway and T. Shrimpton},
  title       = {Synthetic Initialization Vector ({SIV}) Authenticated Encryption Using the Advanced Encryption Standard ({AES})},
  type        = {{RFC}},
  number      = {5297},
  institution = {IETF},
  year        = {2008},
  month       = oct,
  doi         = {10.17487/RFC5297},
  url         = {https://www.rfc-editor.org/rfc/rfc5297},
  note        = {Local copy: pubs/rfc5297-siv.pdf},
}

@techreport{rfc7253,
  author      = {T. Krovetz and P. Rogaway},
  title       = {The {OCB} Authenticated-Encryption Algorithm},
  type        = {{RFC}},
  number      = {7253},
  institution = {IETF},
  year        = {2014},
  month       = may,
  doi         = {10.17487/RFC7253},
  url         = {https://www.rfc-editor.org/rfc/rfc7253},
  note        = {Local copy: pubs/rfc7253-ocb.pdf},
}

@techreport{rfc8452,
  author      = {S. Gueron and A. Langley and Y. Lindell},
  title       = {{AES}-{GCM}-{SIV}: Nonce Misuse-Resistant Authenticated Encryption},
  type        = {{RFC}},
  number      = {8452},
  institution = {IETF},
  year        = {2019},
  month       = apr,
  url         = {https://www.rfc-editor.org/rfc/rfc8452},
}

@misc{boyar-peralta-2011,
  author       = {Joan Boyar and Ren{\'e} Peralta},
  title        = {A depth-16 circuit for the {AES} {S}-box},
  howpublished = {{IACR} Cryptology ePrint Archive, Report 2011/332},
  year         = {2011},
  url          = {https://eprint.iacr.org/2011/332},
}

@techreport{fips46-3,
  author      = {{National Institute of Standards and Technology}},
  title       = {Data Encryption Standard ({DES})},
  institution = {National Institute of Standards and Technology},
  type        = {{Federal Information Processing Standard}},
  number      = {FIPS PUB 46-3},
  year        = {1999},
  month       = oct,
  url         = {https://csrc.nist.gov/publications/detail/fips/46/3/archive/1999-10-25},
}

@techreport{rfc2144,
  author      = {C. Adams},
  title       = {The CAST-128 Encryption Algorithm},
  type        = {{RFC}},
  number      = {2144},
  institution = {IETF},
  year        = {1997},
  month       = may,
  url         = {https://www.rfc-editor.org/rfc/rfc2144},
}

@inproceedings{anderson-biham-knudsen-1998-serpent,
  author    = {Ross Anderson and Eli Biham and Lars Knudsen},
  title     = {Serpent: A Proposal for the Advanced Encryption Standard},
  booktitle = {Fast Software Encryption --- FSE 1998},
  editor    = {Alfred J. Menezes},
  series    = {Lecture Notes in Computer Science},
  volume    = {1372},
  pages     = {222--238},
  publisher = {Springer},
  year      = {1998},
  doi       = {10.1007/3-540-69710-1_15},
  url       = {https://www.cl.cam.ac.uk/archive/rja14/Papers/serpent.pdf},
}

@misc{twofish-1998,
  author       = {Bruce Schneier and John Kelsey and Doug Whiting and
                  David Wagner and Chris Hall and Niels Ferguson},
  title        = {Twofish: A 128-Bit Block Cipher},
  howpublished = {AES submission / design paper},
  year         = {1998},
  url          = {https://www.schneier.com/wp-content/uploads/2016/02/paper-twofish-paper.pdf},
}

@misc{camellia-spec,
  author       = {Kazumaro Aoki and Takeshi Ichikawa and Masayuki Kanda and
                  Mitsuru Matsui and Shiho Moriai and Junko Nakajima and
                  Toshio Tokita},
  title        = {Specification of Camellia, a 128-bit Block Cipher},
  howpublished = {CRYPTREC submission / algorithm specification},
  year         = {2001},
  url          = {https://www.cryptrec.go.jp/en/cryptrec_03_spec_cypherlist_files/PDF/06_01espec.pdf},
}

@techreport{rfc3713,
  author      = {Mitsuru Matsui and Junko Nakajima and Shiho Moriai},
  title       = {A Description of the Camellia Encryption Algorithm},
  type        = {{RFC}},
  number      = {3713},
  institution = {IETF},
  year        = {2004},
  month       = apr,
  url         = {https://www.rfc-editor.org/rfc/rfc3713},
}

@techreport{rfc4312,
  author      = {K. Seo and S. Kent},
  title       = {Camellia Encryption Algorithm Use with IPsec},
  type        = {{RFC}},
  number      = {4312},
  institution = {IETF},
  year        = {2005},
  month       = dec,
  url         = {https://www.rfc-editor.org/rfc/rfc4312},
}

@techreport{rfc4009,
  author      = {Jongwook Park and Sungjae Lee and Jeeyeon Kim and Jaeil Lee},
  title       = {The {SEED} Encryption Algorithm},
  type        = {{RFC}},
  number      = {4009},
  institution = {IETF},
  year        = {2005},
  month       = feb,
  url         = {https://www.rfc-editor.org/rfc/rfc4009},
}

@techreport{rfc4196,
  author      = {Hyangjin Lee and Jaeho Yoon and Seoklae Lee and Jaeil Lee},
  title       = {The {SEED} Cipher Algorithm and Its Use with {IPsec}},
  type        = {{RFC}},
  number      = {4196},
  institution = {IETF},
  year        = {2005},
  month       = oct,
  url         = {https://www.rfc-editor.org/rfc/rfc4196},
}

@techreport{sp800-67r2,
  author      = {{National Institute of Standards and Technology}},
  title       = {Recommendation for the Triple Data Encryption Algorithm
                 ({TDEA}) Block Cipher},
  institution = {National Institute of Standards and Technology},
  type        = {{NIST Special Publication}},
  number      = {800-67 Revision 2},
  year        = {2017},
  month       = nov,
  url         = {https://csrc.nist.gov/publications/detail/sp/800-67/rev-2/final},
}

@book{daemen-rijmen-2002,
  author    = {Joan Daemen and Vincent Rijmen},
  title     = {The Design of {Rijndael}: {AES} --- The Advanced Encryption Standard},
  publisher = {Springer},
  year      = {2002},
  isbn      = {978-3-540-42580-9},
}

@techreport{rfc7801,
  author      = {V. Dolmatov},
  title       = {GOST R 34.12-2015: Block Cipher ``Grasshopper''},
  type        = {{RFC}},
  number      = {7801},
  institution = {IETF},
  year        = {2016},
  month       = mar,
  url         = {https://www.rfc-editor.org/rfc/rfc7801},
}

@techreport{rfc8891,
  author      = {V. Dolmatov and A. Degtyarev},
  title       = {GOST R 34.12-2015: Block Cipher ``Magma''},
  type        = {{RFC}},
  number      = {8891},
  institution = {IETF},
  year        = {2020},
  month       = sep,
  url         = {https://www.rfc-editor.org/rfc/rfc8891},
}

@inproceedings{bogdanov-2007-present,
  author    = {Andrey Bogdanov and Lars R. Knudsen and Gregor Leander and
               Christof Paar and Axel Poschmann and Matthew J. B. Robshaw and
               Yannick Seurin and Charlotte Vikkelsoe},
  title     = {{PRESENT}: An Ultra-Lightweight Block Cipher},
  booktitle = {Cryptographic Hardware and Embedded Systems --- {CHES} 2007},
  year      = {2007},
  pages     = {450--466},
  publisher = {Springer},
  url       = {https://crypto.orange-labs.fr/papers/ches2007-450.pdf},
}

@techreport{gm-t-0002-2012,
  author      = {{State Cryptography Administration of the People's Republic of China}},
  title       = {{SM4} Block Cipher Algorithm},
  institution = {{State Cryptography Administration of the People's Republic of China}},
  type        = {{GM/T}},
  number      = {0002-2012},
  year        = {2012},
  month       = mar,
  url         = {https://www.gmbz.org.cn/upload/2025-01-23/1737625646289030731.pdf},
  note        = {English translation of the Chinese standard},
}

@article{liu-2024-sm4-linear,
  author  = {Qi Liu and others},
  title   = {Linear Cryptanalysis of {SM4} based on Correlation of Binary Masks},
  journal = {Highlights in Science, Engineering and Technology},
  volume  = {83},
  pages   = {17--22},
  year    = {2024},
  url     = {https://zenodo.org/records/10867006/files/_3_219_17-22_Liu.pdf?download=1},
}

@techreport{etsi-sage-zuc-v16,
  author      = {{ETSI SAGE}},
  title       = {Specification of the 3GPP Confidentiality and Integrity Algorithms
                 128-{EEA3} \& 128-{EIA3}; Document 2: {ZUC} Specification},
  institution = {{European Telecommunications Standards Institute}},
  type        = {Specification},
  version     = {1.6},
  year        = {2011},
  note        = {Referenced by 3GPP TS 35.222 / ETSI TS 135 222},
  url         = {https://www.etsi.org/deliver/etsi_ts/135200_135299/135222/16.00.00_60/ts_135222v160000p.pdf},
}

@incollection{salsafamily-2007,
  author    = {Daniel J. Bernstein},
  title     = {The {Salsa20} family of stream ciphers},
  booktitle = {New Stream Cipher Designs},
  series    = {Lecture Notes in Computer Science},
  volume    = {4986},
  pages     = {84--97},
  publisher = {Springer},
  year      = {2008},
  note      = {Author's specification PDF dated 2007-12-25},
  url       = {https://cr.yp.to/snuffle/salsafamily-20071225.pdf},
}

@techreport{rfc4503,
  author      = {M. Boesgaard and M. Vesterager and T. Pedersen and J. Christiansen},
  title       = {The {Rabbit} Cipher Algorithm},
  type        = {{RFC}},
  number      = {4503},
  institution = {IETF},
  year        = {2006},
  month       = may,
  url         = {https://www.rfc-editor.org/rfc/rfc4503},
}

@misc{chacha-2008,
  author       = {Daniel J. Bernstein},
  title        = {ChaCha, a variant of Salsa20},
  howpublished = {Author's specification paper},
  year         = {2008},
  month        = jan,
  url          = {https://cr.yp.to/chacha/chacha-20080128.pdf},
}

@techreport{rfc8439,
  author      = {Y. Nir and A. Langley},
  title       = {ChaCha20 and Poly1305 for {IETF} Protocols},
  type        = {{RFC}},
  number      = {8439},
  institution = {IETF},
  year        = {2018},
  month       = jun,
  url         = {https://www.rfc-editor.org/rfc/rfc8439},
}

@misc{draft-irtf-cfrg-xchacha-03,
  author       = {A. Langley and Y. Nir},
  title        = {{XChaCha}: eXtended-nonce ChaCha and {AEAD}\_XChaCha20\_Poly1305},
  howpublished = {Internet-Draft, draft-irtf-cfrg-xchacha-03},
  year         = {2020},
  month        = jan,
  url          = {https://www.ietf.org/archive/id/draft-irtf-cfrg-xchacha-03.txt},
  note         = {Local PDF copy in `pubs/` generated from the IETF draft text},
}

@inproceedings{ajtai-1996,
  author    = {Mikl{\'o}s Ajtai},
  title     = {Generating Hard Instances of Lattice Problems (Extended Abstract)},
  booktitle = {Proceedings of the Twenty-Eighth Annual ACM Symposium on Theory of Computing},
  series    = {STOC '96},
  pages     = {99--108},
  year      = {1996},
  publisher = {Association for Computing Machinery},
  doi       = {10.1145/237814.237838},
}

@inproceedings{ajtai-dwork-1997,
  author    = {Mikl{\'o}s Ajtai and Cynthia Dwork},
  title     = {A Public-Key Cryptosystem with Worst-Case/Average-Case Equivalence},
  booktitle = {Proceedings of the Twenty-Ninth Annual ACM Symposium on Theory of Computing},
  series    = {STOC '97},
  pages     = {284--293},
  year      = {1997},
  publisher = {Association for Computing Machinery},
  doi       = {10.1145/258533.258604},
}

@techreport{fips203,
  author      = {{National Institute of Standards and Technology}},
  title       = {Module-Lattice-Based Key-Encapsulation Mechanism Standard},
  institution = {National Institute of Standards and Technology},
  type        = {{Federal Information Processing Standard}},
  number      = {FIPS PUB 203},
  year        = {2024},
  month       = aug,
  doi         = {10.6028/NIST.FIPS.203},
  url         = {https://csrc.nist.gov/pubs/fips/203/final},
}

@techreport{fips204,
  author      = {{National Institute of Standards and Technology}},
  title       = {Module-Lattice-Based Digital Signature Standard},
  institution = {National Institute of Standards and Technology},
  type        = {{Federal Information Processing Standard}},
  number      = {FIPS PUB 204},
  year        = {2024},
  month       = aug,
  doi         = {10.6028/NIST.FIPS.204},
  url         = {https://csrc.nist.gov/pubs/fips/204/final},
}
```

<p align="center">
  <img src="assets/ship_of_fools.png" width="50%" alt="Ship of Fools">
</p>
