# MANUAL
This manual documents the externally usable API surface of the crate as it is
today. It is organized by task and primitive family rather than by source file.
## Imports and Safety Model
The crate has two distinct surfaces:
- root-level exports for symmetric primitives, hashes, XOFs, MACs, modes, and
the practical DRBG
- `cryptography::vt` for public-key primitives
Public-key code lives under `cryptography::vt` intentionally. Those APIs use
variable-time bigint and elliptic-curve arithmetic and are not appropriate for
side-channel-exposed production signing or decryption services.
Typical imports look like:
```rust
use cryptography::{
Aes256, BlockCipher, CtrDrbgAes256, Gcm, Hmac, Sha256, Sha512, Xof,
ChaCha20,
};
use cryptography::public_key::ec_edwards::ed25519;
use cryptography::vt::{
p256, Dh, Dsa, Ecdh, Ecdsa, Ecies, Ed25519, EdDsa, EdwardsDh,
ElGamal, MlKem, MlKemParameterSet, Paillier, Rsa, RsaOaep, RsaPss,
X25519, X448,
};
```
## Entropy Requirements
This crate does **not** provide an operating-system entropy source.
That is deliberate. If you use `CtrDrbgAes256`, key-generation APIs, randomized
padding, or any other randomness-dependent operation, you must supply the seed
material yourself from a high-entropy external source.
Use OS-provided entropy APIs for this (`getentropy`, `SecRandomCopyBytes`,
`getrandom`, or equivalent on your target). Do not invent your own entropy
source in application code.
What this means in practice:
- `CtrDrbgAes256` is deterministic once seeded. A bad 48-byte seed gives bad
output forever until you reseed it correctly.
- every `generate(rng, ...)` public-key API inherits the quality of the `rng`
you pass in
- randomized schemes such as RSA OAEP, RSA PSS, ElGamal, Paillier
rerandomization, ECIES, ECDH key generation, ECDSA/DSA randomized signing,
and Edwards/EC key generation all depend on caller-supplied entropy
- low-entropy seeds, repeated seeds, predictable seeds, or seeds derived from
clocks, PIDs, usernames, or other guessable values are cryptographic
failures, not merely quality issues
The examples in this manual use fixed seed literals because the examples are
also exercised by tests and need deterministic behavior. Those literals are
for documentation only. Production callers must replace them with real external
entropy before using any randomness-dependent API.
For concrete failure modes caused by low-entropy randomness in deployed TLS
implementations, see James P. Hughes, *BADRANDOM: The Effect and Mitigations
for Low Entropy Random Numbers in TLS* (PhD thesis, 2022). Local copy:
`pubs/hughes-2022-badrandom-the-effect-and-mitigations-for-low-entropy-random-numbers-in-tls.pdf`.
## API Conventions
The public surface follows these naming rules:
- `to_wire_bytes` / `from_wire_bytes` are compact standard encodings that do
not carry full algorithm parameters
- `to_key_blob` / `from_key_blob` are the crate-defined self-describing binary
encodings
- `to_raw_bytes` / `from_raw_bytes` are used where the standard representation
is already a fixed-width raw byte string, notably `Ed25519`
- explicit caller-supplied randomness uses `*_with_nonce`
- Diffie-Hellman style APIs name the returned form explicitly:
`agree_element`, `agree_x_coordinate`, `agree_compressed_point`
## CSPRNG
### Root-level practical DRBG
The practical generator is `CtrDrbgAes256`, exported at the crate root. It is a
DRBG, not an entropy source.
Key methods:
- `CtrDrbgAes256::new(&[u8; 48])`
- `CtrDrbgAes256::new_wiping(&mut [u8; 48])`
- `reseed(&[u8; 48])`
- `reseed_wiping(&mut [u8; 48])`
- `generate(&mut [u8], Option<&[u8; 48]>)`
- `fill_bytes(&mut [u8])` via the `Csprng` trait
- `next_u64()` via the `Csprng` trait
Example:
```rust
use cryptography::{Csprng, CtrDrbgAes256};
// Fixed seed for a reproducible example only.
// Production code must replace this with high-entropy external seed material.
let mut seed = [0x42u8; 48];
let mut rng = CtrDrbgAes256::new_wiping(&mut seed);
let mut key = [0u8; 32];
rng.fill_bytes(&mut key);
let counter = rng.next_u64();
assert_ne!(counter, 0);
```
### Entropy checklist
Before using `CtrDrbgAes256` or any public-key `generate(...)` API, make sure:
- the seed came from a real external entropy source
- the seed is not reused across machines, users, or runs
- test/example literals never survive into deployment code
- any reseed path is held to the same entropy standard as the initial seed
## Hash, XOF, and MAC
### Fixed-output hashes
The crate exports:
- `Md5`
- `Ripemd160`
- `Sha1`
- `Sha224`, `Sha256`, `Sha384`, `Sha512`, `Sha512_224`, `Sha512_256`
- `Sha3_224`, `Sha3_256`, `Sha3_384`, `Sha3_512`
All fixed-output hashes support:
- `new()`
- `update(&[u8])`
- `finalize()`
- `digest(&[u8])`
One-shot example:
```rust
use cryptography::Sha256;
let digest = Sha256::digest(b"hello");
assert_eq!(digest.len(), 32);
```
Incremental example:
```rust
use cryptography::Sha512;
let mut h = Sha512::new();
h.update(b"hello ");
h.update(b"world");
let digest = h.finalize();
assert_eq!(digest.len(), 64);
```
### XOFs
The XOF exports are:
- `Shake128`
- `Shake256`
They implement the `Xof` trait:
- `update(&[u8])`
- `squeeze(&mut [u8])`
Example:
```rust
use cryptography::{Shake256, Xof};
let mut xof = Shake256::new();
xof.update(b"context");
xof.update(b"message");
let mut out = [0u8; 64];
xof.squeeze(&mut out);
### HMAC
`Hmac<H>` is exported at the crate root and works with any in-tree `Digest`.
Key methods:
- `Hmac::<H>::new(key)`
- `update(data)`
- `finalize()`
- `compute(key, data)`
- `verify(key, data, tag)`
Example:
```rust
use cryptography::{Hmac, Sha256};
let tag = Hmac::<Sha256>::compute(b"secret", b"message");
assert!(Hmac::<Sha256>::verify(b"secret", b"message", &tag));
```
### HKDF
`Hkdf<H>` implements RFC 5869 extract+expand over any in-tree `Digest`.
Key methods:
- `Hkdf::<H>::extract(salt, ikm)`
- `Hkdf::<H>::from_prk(prk)`
- `expand(info, out)`
- `derive(salt, ikm, info, len)`
Example:
```rust
use cryptography::{Hkdf, Sha256};
let hkdf = Hkdf::<Sha256>::extract(Some(b"salt"), b"input keying material");
let mut okm = [0u8; 32];
assert!(hkdf.expand(b"context", &mut okm));
```
### Block-cipher MACs
The mode layer also exports:
- `Cmac<C>`
- `Gmac<C>`
- `GmacVt<C>`
Example:
```rust
use cryptography::{Aes256, Gmac};
let gmac = Gmac::new(Aes256::new(&[0u8; 32]));
let tag = gmac.compute(&[0u8; 12], b"aad");
assert!(gmac.verify(&[0u8; 12], b"aad", &tag));
```
## Symmetric
### Block ciphers
All block ciphers implement:
```rust
pub trait BlockCipher {
const BLOCK_LEN: usize;
fn encrypt(&self, block: &mut [u8]);
fn decrypt(&self, block: &mut [u8]);
}
```
Most concrete block ciphers also expose:
- `new(&[u8; N])`
- `encrypt_block(&[u8; BLOCK]) -> [u8; BLOCK]`
- `decrypt_block(&[u8; BLOCK]) -> [u8; BLOCK]`
Families exported at the crate root:
- AES: `Aes128`, `Aes192`, `Aes256`, `Aes128Ct`, `Aes192Ct`, `Aes256Ct`
- Camellia: `Camellia128`, `Camellia192`, `Camellia256`, plus `Ct` variants
- CAST: `Cast128`, `Cast128Ct`, `Cast5`, `Cast5Ct`
- DES: `Des`, `DesCt`, `TripleDes`
- Grasshopper: `Grasshopper`, `GrasshopperCt`
- Magma: `Magma`, `MagmaCt`
- PRESENT: `Present80`, `Present128`, and `Ct` variants
- SEED: `Seed`, `SeedCt`
- Serpent: `Serpent128`, `Serpent192`, `Serpent256`, plus `Ct` variants
- SIMON and SPECK parameter sets
- SM4: `Sm4`, `Sm4Ct`
- Twofish: `Twofish128`, `Twofish192`, `Twofish256`, plus `Ct` variants
Simple block example:
```rust
use cryptography::Aes256;
let cipher = Aes256::new(&[0u8; 32]);
let block = cipher.encrypt_block(&[0u8; 16]);
let roundtrip = cipher.decrypt_block(&block);
assert_eq!(roundtrip, [0u8; 16]);
```
### Modes
The mode layer exports:
- `Ecb<C>`
- `Cbc<C>`
- `Cfb<C>`
- `Cfb8<C>`
- `Ofb<C>`
- `Ctr<C>`
- `Xts<C>`
- `Cmac<C>`
- `Ccm<C>`
- `Gcm<C>`
- `GcmVt<C>`
- `Gmac<C>`
- `GmacVt<C>`
- `AesKeyWrap<C>`
- `Eax<C>`
- `Ocb<C>`
- `Siv<C>`
- `Aes128GcmSiv`
- `Aes256GcmSiv`
- `Poly1305`
- `ChaCha20Poly1305`
Constructor pattern:
- `Mode::new(cipher)`
Representative methods:
- `encrypt_nopad` / `decrypt_nopad` for `Ecb`, `Cbc`, `Cfb`
- `encrypt` / `decrypt` for `Cfb8`
- `apply_keystream` for `Ofb`, `Ctr`
- `encrypt_sector` / `decrypt_sector` for `Xts`
- `encrypt` / `decrypt` / `compute_tag` for `Ccm`
- `encrypt`, `decrypt`, `compute_tag` for `Gcm` and `GcmVt`
- `wrap_key` / `unwrap_key` for `AesKeyWrap` (RFC 3394, no padding)
- `encrypt` / `decrypt` for `Eax`, `Ocb`, and `Siv`
- `encrypt` / `decrypt` for `Aes128GcmSiv` and `Aes256GcmSiv`
- `compute` / `verify` for `Poly1305`
- `encrypt`, `decrypt`, `encrypt_in_place`, `decrypt_in_place` for
`ChaCha20Poly1305`
`Gcm` and `Gmac` are the safe-default constant-time GHASH-backed variants.
`GcmVt` and `GmacVt` are the explicit variable-time reference/performance
variants.
`Aead` is the shared detached-tag trait implemented by `Gcm`, `GcmVt`, `Ccm`,
`Eax`, `Ocb`, `Siv`, `Aes128GcmSiv`, `Aes256GcmSiv`, and `ChaCha20Poly1305`.
`Gcm` and `GcmVt` enforce the SP 800-38D per-call payload bound of
$(2^{32}-2)$ counter blocks (`68_719_476_704` bytes); oversized inputs panic
to prevent counter wrap.
Example: AES-256-GCM
```rust
use cryptography::{Aes256, Gcm};
let gcm = Gcm::new(Aes256::new(&[0u8; 32]));
let nonce = [0u8; 12];
let aad = b"header";
let mut data = b"secret message".to_vec();
let tag = gcm.encrypt(&nonce, aad, &mut data);
assert!(gcm.decrypt(&nonce, aad, &mut data, &tag));
assert_eq!(data, b"secret message");
```
Example: CTR mode over AES
```rust
use cryptography::{Aes128, Ctr};
let ctr = Ctr::new(Aes128::new(&[0u8; 16]));
let counter = [0u8; 16];
let mut buf = b"plaintext".to_vec();
ctr.apply_keystream(&counter, &mut buf);
ctr.apply_keystream(&counter, &mut buf);
assert_eq!(buf, b"plaintext");
```
Example: ChaCha20-Poly1305 AEAD
```rust
use cryptography::ChaCha20Poly1305;
let aead = ChaCha20Poly1305::new(&[0u8; 32]);
let nonce = [0u8; 12];
let aad = b"header";
let (ct, tag) = aead.encrypt(&nonce, aad, b"secret message");
assert_eq!(
aead.decrypt(&nonce, aad, &ct, &tag),
Some(b"secret message".to_vec())
);
```
### Worked example: `encrypt_file` / `decrypt_file` with counter mode
This is a minimal complete file-encryption example built directly from the
surface API.
Important caveat: `CTR` mode gives confidentiality only. It does **not**
authenticate the ciphertext. In real deployments, pair this with a MAC or use
`Gcm<Aes256>` instead unless a separate integrity layer already exists.
```rust
use std::fs;
use std::path::Path;
use cryptography::{Aes256, Ctr};
fn encrypt_file(input: &Path, output: &Path, key: &[u8; 32], counter: &[u8; 16]) {
let ctr = Ctr::new(Aes256::new(key));
let mut data = fs::read(input).expect("read plaintext");
ctr.apply_keystream(counter, &mut data);
fs::write(output, data).expect("write ciphertext");
}
fn decrypt_file(input: &Path, output: &Path, key: &[u8; 32], counter: &[u8; 16]) {
let ctr = Ctr::new(Aes256::new(key));
let mut data = fs::read(input).expect("read ciphertext");
ctr.apply_keystream(counter, &mut data);
fs::write(output, data).expect("write plaintext");
}
```
Round-trip usage:
```rust
use std::path::Path;
let key = [0x11u8; 32];
let counter = [0x22u8; 16];
encrypt_file(
Path::new("plain.txt"),
Path::new("secret.bin"),
&key,
&counter,
);
decrypt_file(
Path::new("secret.bin"),
Path::new("roundtrip.txt"),
&key,
&counter,
);
```
### Stream ciphers
The stream ciphers are byte-oriented inherent APIs rather than `BlockCipher`
implementations.
Shared trait:
- `StreamCipher` with `fill(&mut [u8])` and `apply_keystream(&mut [u8])`
Root-level exports:
- `ChaCha20`
- `XChaCha20`
- `Salsa20`
- `Rabbit`
- `Snow3g`, `Snow3gCt`
- `Zuc128`, `Zuc128Ct`
Common method pattern:
- `new(key, nonce_or_iv)`
- `apply_keystream(&mut [u8])`
- `fill(&mut [u8])`
Some stream ciphers also expose:
- `with_counter(...)` and `set_counter(...)` for ChaCha20/XChaCha20
- `without_iv(...)` for Rabbit
- `keystream_block()` for ChaCha20, XChaCha20, Rabbit
Example: ChaCha20
```rust
use cryptography::ChaCha20;
let mut cipher = ChaCha20::new(&[0u8; 32], &[0u8; 12]);
let mut buf = b"stream data".to_vec();
let original = buf.clone();
cipher.apply_keystream(&mut buf);
let mut cipher = ChaCha20::new(&[0u8; 32], &[0u8; 12]);
cipher.apply_keystream(&mut buf);
assert_eq!(buf, original);
```
Example: SNOW 3G
```rust
use cryptography::Snow3g;
let mut snow = Snow3g::new(&[0u8; 16], &[0u8; 16]);
let mut stream = [0u8; 64];
snow.fill(&mut stream);
## Public-Key
All public-key APIs live under `cryptography::vt`.
```rust
use cryptography::public_key::ec_edwards::ed25519;
use cryptography::vt::{p256, Ecdsa, Ed25519, Rsa};
```
The public-key surface naturally splits into:
- finite-field / integer schemes
- short-Weierstrass EC schemes
- Edwards-curve schemes
### Serialization rules
Public-key serialization is not uniform across all families:
- RSA uses standard PKCS/SPKI methods such as `to_pkcs8_der()` and
`to_spki_pem()`
- most non-RSA key types use `to_key_blob()` / `from_key_blob()` for the
crate-defined binary format
- EC and Edwards public keys that have compact standard point encodings expose
`to_wire_bytes()` / `from_wire_bytes(...)`
- `Ed25519` uses `to_raw_bytes()` / `from_raw_bytes()` for its standard 32-byte
forms
PEM and XML wrappers are available on most key types:
- `to_pem()` / `from_pem(...)`
- `to_xml()` / `from_xml(...)`
### Finite-field and integer schemes
Primary root types:
- `Rsa`
- `RsaOaep<H>`
- `RsaPss<H>`
- `Dh`
- `Dsa`
- `ElGamal`
- `Paillier`
- `Rabin`
- `SchmidtSamoa`
- `Cocks`
#### RSA
Key-generation methods:
- `Rsa::generate(rng, bits)`
- `Rsa::generate_with_exponent(rng, bits, e)`
- `Rsa::from_primes(...)`
- `Rsa::from_primes_with_exponent(...)`
Raw operations:
- `RsaPublicKey::encrypt_raw(&BigUint) -> BigUint`
- `RsaPrivateKey::decrypt_raw(&BigUint) -> BigUint`
Standards-based wrappers:
- `RsaOaep::<H>::encrypt(public, label, message)`
- `RsaOaep::<H>::encrypt_rng(public, label, message, rng)`
- `RsaOaep::<H>::decrypt(private, label, ciphertext)`
- `RsaPss::<H>::sign(private, message, salt)`
- `RsaPss::<H>::sign_rng(private, message, rng)`
- `RsaPss::<H>::verify(public, message, signature)`
RSA serialization:
- public: `to_pkcs1_der`, `to_spki_der`, `to_pkcs1_pem`, `to_spki_pem`
- private: `to_pkcs1_der`, `to_pkcs8_der`, `to_pkcs1_pem`, `to_pkcs8_pem`
Example: RSA OAEP and PSS
```rust
use cryptography::{CtrDrbgAes256, Sha256, Sha512};
use cryptography::vt::{Rsa, RsaOaep, RsaPss};
// Fixed seed for a deterministic example only.
let mut rng = CtrDrbgAes256::new(&[7u8; 48]);
let (public, private) = Rsa::generate(&mut rng, 1024).expect("rsa");
let ciphertext = RsaOaep::<Sha256>::encrypt_rng(&public, b"label", b"hello", &mut rng)
.expect("oaep encrypt");
let plaintext = RsaOaep::<Sha256>::decrypt(&private, b"label", &ciphertext)
.expect("oaep decrypt");
assert_eq!(plaintext, b"hello");
let signature = RsaPss::<Sha512>::sign_rng(&private, b"hello", &mut rng)
.expect("pss sign");
assert!(RsaPss::<Sha512>::verify(&public, b"hello", &signature));
```
#### Diffie-Hellman over finite fields
Key types:
- `DhParams`
- `DhPublicKey`
- `DhPrivateKey`
Generation:
- `Dh::generate_params(rng, bits)`
- `Dh::generate(¶ms, rng)`
Agreement:
- `DhPrivateKey::agree_element(&peer) -> Option<BigUint>`
Example:
```rust
use cryptography::CtrDrbgAes256;
use cryptography::vt::Dh;
// Fixed seed for a deterministic example only.
let mut rng = CtrDrbgAes256::new(&[9u8; 48]);
let params = Dh::generate_params(&mut rng, 256).expect("params");
let (pub_a, priv_a) = Dh::generate(¶ms, &mut rng);
let (pub_b, priv_b) = Dh::generate(¶ms, &mut rng);
let shared_a = priv_a.agree_element(&pub_b).expect("agree a");
let shared_b = priv_b.agree_element(&pub_a).expect("agree b");
assert_eq!(shared_a, shared_b);
```
#### DSA
Generation:
- `Dsa::generate(rng, bits)`
- `Dsa::from_secret_exponent(...)`
Signing and verification:
- `sign_message::<H>(message)`
- `sign_message_with_rng::<H, R>(message, rng)`
- `sign_digest::<H>(digest)`
- `sign_digest_with_rng(digest, rng)`
- `sign_digest_with_nonce(digest, nonce)`
- `verify_message::<H>(message, signature)`
- `verify_message_bytes::<H>(message, signature_bytes)`
- `verify(digest, signature)`
- `verify_digest_scalar(&BigUint, signature)`
Example:
```rust
use cryptography::{CtrDrbgAes256, Sha256};
use cryptography::vt::Dsa;
// Fixed seed for a deterministic example only.
let mut rng = CtrDrbgAes256::new(&[3u8; 48]);
let (public, private) = Dsa::generate(&mut rng, 1024).expect("dsa");
let sig = private.sign_message::<Sha256>(b"message").expect("sign");
assert!(public.verify_message::<Sha256>(b"message", &sig));
```
#### ElGamal, Paillier, and the educational schemes
Normal APIs:
- `ElGamalPublicKey::encrypt(...)`
- `ElGamalPublicKey::encrypt_with_nonce(...)`
- `ElGamalPrivateKey::decrypt(...)`
- `PaillierPublicKey::encrypt(...)`
- `PaillierPublicKey::encrypt_with_nonce(...)`
- `PaillierPrivateKey::decrypt(...)`
- `PaillierPublicKey::add_ciphertexts(...)`
- `Rabin`, `SchmidtSamoa`, `Cocks` expose `encrypt_raw` plus byte wrappers
Example: Paillier homomorphic addition
```rust
use cryptography::CtrDrbgAes256;
use cryptography::vt::{BigUint, Paillier};
// Fixed seed for a deterministic example only.
let mut rng = CtrDrbgAes256::new(&[5u8; 48]);
let (public, private) = Paillier::generate(&mut rng, 256).expect("paillier");
let c1 = public.encrypt_with_nonce(&BigUint::from_u64(10), &BigUint::from_u64(3))
.expect("enc1");
let c2 = public.encrypt_with_nonce(&BigUint::from_u64(20), &BigUint::from_u64(5))
.expect("enc2");
let sum_ct = public.add_ciphertexts(&c1, &c2).expect("add");
let sum = private.decrypt_raw(&sum_ct);
assert_eq!(sum, BigUint::from_u64(30));
```
### Short-Weierstrass EC
Curve constructors exported from `cryptography::vt`:
- prime-field curves: `p192`, `p224`, `p256`, `p384`, `p521`, `secp256k1`
- binary curves: `b163`, `k163`, `b233`, `k233`, `b283`, `k283`, `b409`,
`k409`, `b571`, `k571`
Typed schemes:
- `Ecdh`
- `Ecdsa`
- `Ecies`
- `EcElGamal`
Low-level arithmetic is available through:
- `CurveParams`
- `AffinePoint`
#### ECDH
Generation and agreement:
- `Ecdh::generate(curve, rng)`
- `EcdhPrivateKey::agree_x_coordinate(&peer) -> Option<Vec<u8>>`
Public-key encoding:
- `EcdhPublicKey::to_wire_bytes()`
- `EcdhPublicKey::from_wire_bytes(curve, bytes)`
Example:
```rust
use cryptography::CtrDrbgAes256;
use cryptography::vt::{p256, Ecdh};
// Fixed seed for a deterministic example only.
let mut rng = CtrDrbgAes256::new(&[1u8; 48]);
let (pub_a, priv_a) = Ecdh::generate(p256(), &mut rng);
let (pub_b, priv_b) = Ecdh::generate(p256(), &mut rng);
let shared_a = priv_a.agree_x_coordinate(&pub_b).expect("a");
let shared_b = priv_b.agree_x_coordinate(&pub_a).expect("b");
assert_eq!(shared_a, shared_b);
```
#### ECDSA
Generation:
- `Ecdsa::generate(curve, rng)`
- `Ecdsa::from_secret_scalar(curve, d)`
Signing and verification:
- `sign_message::<H>(message)`
- `sign_message_with_rng::<H, R>(message, rng)`
- `sign_digest::<H>(digest)`
- `sign_digest_with_rng(digest, rng)`
- `sign_digest_with_nonce(digest, nonce)`
- `verify_message::<H>(message, signature)`
- `verify(digest, signature)`
- `verify_digest_scalar(&BigUint, signature)`
Wire encoding for public keys:
- `EcdsaPublicKey::to_wire_bytes()`
- `EcdsaPublicKey::from_wire_bytes(curve, bytes)`
Example:
```rust
use cryptography::{CtrDrbgAes256, Sha256};
use cryptography::vt::{p256, Ecdsa};
// Fixed seed for a deterministic example only.
let mut rng = CtrDrbgAes256::new(&[2u8; 48]);
let (public, private) = Ecdsa::generate(p256(), &mut rng);
let sig = private.sign_message::<Sha256>(b"ecdsa message").expect("sign");
assert!(public.verify_message::<Sha256>(b"ecdsa message", &sig));
```
#### ECIES
Generation:
- `Ecies::generate(curve, rng)`
Hybrid encryption:
- `EciesPublicKey::encrypt(message, rng) -> Vec<u8>`
- `EciesPrivateKey::decrypt(ciphertext) -> Option<Vec<u8>>`
Public-key compact form:
- `EciesPublicKey::to_wire_bytes()`
- `EciesPublicKey::from_wire_bytes(curve, bytes)`
Example:
```rust
use cryptography::CtrDrbgAes256;
use cryptography::vt::{p256, Ecies};
// Fixed seed for a deterministic example only.
let mut rng = CtrDrbgAes256::new(&[4u8; 48]);
let (public, private) = Ecies::generate(p256(), &mut rng);
let ciphertext = public.encrypt(b"ecies payload", &mut rng);
let plaintext = private.decrypt(&ciphertext).expect("decrypt");
assert_eq!(plaintext, b"ecies payload");
```
#### EC-ElGamal
Generation:
- `EcElGamal::generate(curve, rng)`
Operations:
- `encrypt_point(...)`
- `encrypt_point_with_nonce(...)`
- `encrypt(...)`
- `encrypt_int(...)`
- `decrypt_point(...)`
- `decrypt(...)`
- `decrypt_int(...)`
- `add_ciphertexts(...)`
Public-key compact form:
- `EcElGamalPublicKey::to_wire_bytes()`
- `EcElGamalPublicKey::from_wire_bytes(curve, bytes)`
This is the additive-homomorphic EC ElGamal layer, not ECIES.
### Edwards curves
Built-in curve constructor:
- `cryptography::public_key::ec_edwards::ed25519() -> TwistedEdwardsCurve`
Typed schemes:
- `Ed25519`
- `EdDsa`
- `EdwardsDh`
- `EdwardsElGamal`
Low-level arithmetic:
- `TwistedEdwardsCurve`
- `EdwardsPoint`
#### Ed25519
Generation and import:
- `Ed25519::generate(rng)`
- `Ed25519::from_seed([u8; 32])`
Encodings:
- `Ed25519PublicKey::to_raw_bytes()`
- `Ed25519PublicKey::from_raw_bytes(bytes)`
- `Ed25519PrivateKey::to_raw_bytes()`
- `Ed25519PrivateKey::from_raw_bytes(bytes)`
- `Ed25519Signature::to_key_blob()`
- `Ed25519Signature::from_key_blob(bytes)`
Signing and verification:
- `Ed25519PrivateKey::sign_message(message) -> Ed25519Signature`
- `Ed25519PrivateKey::sign_message_bytes(message) -> Vec<u8>`
- `Ed25519PublicKey::verify_message(message, signature)`
- `Ed25519PublicKey::verify_message_bytes(message, signature_bytes)`
Example:
```rust
use cryptography::CtrDrbgAes256;
use cryptography::vt::Ed25519;
// Fixed seed for a deterministic example only.
let mut rng = CtrDrbgAes256::new(&[6u8; 48]);
let (public, private) = Ed25519::generate(&mut rng);
let sig = private.sign_message(b"ed25519");
assert!(public.verify_message(b"ed25519", &sig));
```
#### Generic EdDSA over Edwards curves
Generation:
- `EdDsa::generate(curve, rng)`
- `EdDsa::from_secret_scalar(curve, d)`
Signing and verification:
- `sign_message::<H, R>(message, rng)`
- `sign_message_with_nonce::<H>(message, nonce)`
- `sign_message_bytes::<H, R>(message, rng)`
- `verify_message::<H>(message, signature)`
- `verify_message_bytes::<H>(message, signature_bytes)`
Public-key compact form:
- `EdDsaPublicKey::to_wire_bytes()`
- `EdDsaPublicKey::from_wire_bytes(curve, bytes)`
Example:
```rust
use cryptography::{CtrDrbgAes256, Sha512};
use cryptography::public_key::ec_edwards::ed25519;
use cryptography::vt::EdDsa;
// Fixed seed for a deterministic example only.
let mut rng = CtrDrbgAes256::new(&[8u8; 48]);
let (public, private) = EdDsa::generate(ed25519(), &mut rng);
let sig = private.sign_message::<Sha512, _>(b"eddsa", &mut rng).expect("sign");
assert!(public.verify_message::<Sha512>(b"eddsa", &sig));
```
#### Curve25519 / Curve448 Diffie-Hellman (RFC 7748)
`X25519` and `X448` are the Montgomery-ladder ECDH primitives from RFC 7748.
Unlike the rest of `cryptography::vt`, both are constant-time in the secret
scalar: the field arithmetic uses fixed-radix limbs (5×51 for X25519, 8×56 for
X448), conditional swaps are mask-driven, and there is no data-dependent
branching or table indexing.
Functional API:
- `X25519::scalar_mult(&[u8; 32], &[u8; 32]) -> [u8; 32]`
- `X25519::scalar_mult_base(&[u8; 32]) -> [u8; 32]`
- `X25519::generate(rng) -> (X25519PublicKey, X25519PrivateKey)`
- `X448::scalar_mult(&[u8; 56], &[u8; 56]) -> [u8; 56]`
- `X448::scalar_mult_base(&[u8; 56]) -> [u8; 56]`
- `X448::generate(rng) -> (X448PublicKey, X448PrivateKey)`
Key types:
- `X25519PrivateKey` / `X25519PublicKey` (32-byte raw)
- `X448PrivateKey` / `X448PublicKey` (56-byte raw)
Both private-key types zeroise on drop and expose `from_raw_bytes` /
`to_raw_bytes` / `from_raw_bytes_wiping` / `to_public_key` / `agree`. `agree`
returns `Option<[u8; N]>` and rejects the all-zero output (low-order point)
per the conservative recommendation in RFC 7748 §6.
Example (X25519):
```rust
use cryptography::CtrDrbgAes256;
use cryptography::vt::X25519;
let mut rng = CtrDrbgAes256::new(&[0x11u8; 48]);
let (pub_a, priv_a) = X25519::generate(&mut rng);
let (pub_b, priv_b) = X25519::generate(&mut rng);
let shared_a = priv_a.agree(&pub_b).expect("non-low-order");
let shared_b = priv_b.agree(&pub_a).expect("non-low-order");
assert_eq!(shared_a, shared_b);
```
Validation: RFC 7748 §5.2 KAT vectors are wired in `cargo test`, including
the iterated vectors at 1, 1000, and 1 000 000 iterations. The 1 M-iteration
tests are gated `#[ignore]`; run them with
`cargo test --release -- --ignored rfc7748_section5_2_iter_1m`.
#### Edwards Diffie-Hellman
Generation and agreement:
- `EdwardsDh::generate(curve, rng)`
- `EdwardsDhPrivateKey::agree_compressed_point(&peer) -> Option<Vec<u8>>`
Public-key compact form:
- `EdwardsDhPublicKey::to_wire_bytes()`
- `EdwardsDhPublicKey::from_wire_bytes(curve, bytes)`
Example:
```rust
use cryptography::CtrDrbgAes256;
use cryptography::public_key::ec_edwards::ed25519;
use cryptography::vt::EdwardsDh;
// Fixed seed for a deterministic example only.
let mut rng = CtrDrbgAes256::new(&[10u8; 48]);
let (pub_a, priv_a) = EdwardsDh::generate(ed25519(), &mut rng);
let (pub_b, priv_b) = EdwardsDh::generate(ed25519(), &mut rng);
let shared_a = priv_a.agree_compressed_point(&pub_b).expect("a");
let shared_b = priv_b.agree_compressed_point(&pub_a).expect("b");
assert_eq!(shared_a, shared_b);
```
#### Edwards ElGamal
Generation:
- `EdwardsElGamal::generate(curve, rng)`
Operations:
- `encrypt_point(...)`
- `encrypt_point_with_nonce(...)`
- `encrypt_int(...)`
- `decrypt_point(...)`
- `decrypt_int(...)`
- `add_ciphertexts(...)`
Public-key compact form:
- `EdwardsElGamalPublicKey::to_wire_bytes()`
- `EdwardsElGamalPublicKey::from_wire_bytes(curve, bytes)`
## Choosing an Algorithm Family
Use this decision rule:
- choose `CtrDrbgAes256` for practical random bytes inside this crate
- choose SHA-2 or SHA-3 for hashing; choose `Hmac<H>` for keyed integrity
- choose `Gcm<Aes256>` when you want authenticated symmetric encryption from
the symmetric layer
- choose `RsaOaep` and `RsaPss` when you need standard RSA encryption or
signatures with interoperable key formats
- choose `Dsa` or `Ecdsa` when you specifically need those signature families
- choose `Ecies` for short-Weierstrass hybrid public-key encryption
- choose `Ed25519` when you want the standard fixed Edwards signature system
- choose `Ecdh` or `EdwardsDh` for key agreement, then run the returned shared
material through your own KDF
- choose `EcElGamal`, `EdwardsElGamal`, or `Paillier` when you explicitly need
homomorphic behavior
## Low-Level Arithmetic Surfaces
The crate also exposes arithmetic building blocks through `cryptography::vt`:
- `BigUint`, `BigInt`, `MontgomeryCtx`
- `CurveParams`, `AffinePoint`
- `TwistedEdwardsCurve`, `EdwardsPoint`
Those are the right tools when you are testing formulas, reconstructing known
vectors, or experimenting with the math directly. They are not the normal
application-level entry points.
## Surface API Reference
This section is the API inventory. It focuses on externally callable surface
methods rather than implementation internals.
### CSPRNG Surface
#### `CtrDrbgAes256`
- constructors:
- `new(&[u8; 48])`
- `new_wiping(&mut [u8; 48])`
- reseeding:
- `reseed(&[u8; 48])`
- `reseed_wiping(&mut [u8; 48])`
- output:
- `generate(&mut [u8], Option<&[u8; 48]>)`
- `fill_bytes(&mut [u8])` via `Csprng`
- `next_u64()` via `Csprng`
- state inspection:
- `reseed_counter()`
### Hash and XOF Surface
#### Fixed-output hashes
Applies to:
- `Md5`
- `Ripemd160`
- `Sha1`
- `Sha224`, `Sha256`, `Sha384`, `Sha512`, `Sha512_224`, `Sha512_256`
- `Sha3_224`, `Sha3_256`, `Sha3_384`, `Sha3_512`
Methods:
- `new()`
- `update(&[u8])`
- `finalize()`
- `digest(&[u8])`
#### XOFs
Applies to:
- `Shake128`
- `Shake256`
Methods:
- `new()`
- `update(&[u8])`
- `digest(&[u8], &mut [u8])` as a one-shot helper on the concrete type
- `squeeze(&mut [u8])` via the `Xof` trait
#### `Hmac<H>`
- `new(key)`
- `update(data)`
- `finalize()`
- `compute(key, data)`
- `verify(key, data, tag)`
### Symmetric Surface
#### Block-cipher types
Fast and `Ct` block-cipher types share the same shape. The concrete exports are:
- AES: `Aes128`, `Aes192`, `Aes256`, `Aes128Ct`, `Aes192Ct`, `Aes256Ct`
- Camellia: `Camellia128`, `Camellia192`, `Camellia256`, `Camellia128Ct`,
`Camellia192Ct`, `Camellia256Ct`
- CAST: `Cast128`, `Cast128Ct`, `Cast5`, `Cast5Ct`
- DES family: `Des`, `DesCt`, `TripleDes`
- Grasshopper: `Grasshopper`, `GrasshopperCt`
- Magma: `Magma`, `MagmaCt`
- PRESENT: `Present80`, `Present128`, `Present80Ct`, `Present128Ct`
- SEED: `Seed`, `SeedCt`
- Serpent: `Serpent128`, `Serpent192`, `Serpent256`, `Serpent128Ct`,
`Serpent192Ct`, `Serpent256Ct`
- SIMON parameter sets
- SPECK parameter sets
- SM4: `Sm4`, `Sm4Ct`
- Twofish: `Twofish128`, `Twofish192`, `Twofish256`, `Twofish128Ct`,
`Twofish192Ct`, `Twofish256Ct`
Common methods:
- `new(&[u8; N])`
- `new_wiping(&mut [u8; N])` where implemented
- `encrypt_block(&[u8; BLOCK]) -> [u8; BLOCK]`
- `decrypt_block(&[u8; BLOCK]) -> [u8; BLOCK]`
- `encrypt(&mut [u8])` / `decrypt(&mut [u8])` through the `BlockCipher` trait
Special DES-family constructors:
- `key_schedule(u64)`
- `TripleDes::new_3key(&[u8; 24])`
- `TripleDes::new_2key(&[u8; 16])`
- `TripleDes::new_single_key(&[u8; 8])`
- wiping variants of the `TripleDes` constructors
#### Stream-cipher types
##### `ChaCha20`
- `new(&[u8; 32], &[u8; 12])`
- `with_counter(&[u8; 32], &[u8; 12], u32)`
- `new_wiping(&mut [u8; 32], &mut [u8; 12])`
- `apply_keystream(&mut [u8])`
- `fill(&mut [u8])`
- `keystream_block()`
- `set_counter(u32)`
##### `XChaCha20`
- `new(&[u8; 32], &[u8; 24])`
- `with_counter(&[u8; 32], &[u8; 24], u32)`
- `new_wiping(&mut [u8; 32], &mut [u8; 24])`
- `apply_keystream(&mut [u8])`
- `fill(&mut [u8])`
- `keystream_block()`
- `set_counter(u32)`
##### `Salsa20`
- `new(&[u8; 32], &[u8; 8])`
- `with_key_bytes(&[u8], &[u8; 8])`
- `with_counter(&[u8], &[u8; 8], u64)`
- wiping variants of those constructors
- `apply_keystream(&mut [u8])`
- `fill(&mut [u8])`
- `keystream_block()`
- `set_counter(u64)`
##### `Rabbit`
- `new(&[u8; 16], &[u8; 8])`
- `without_iv(&[u8; 16])`
- wiping variants
- `apply_keystream(&mut [u8])`
- `fill(&mut [u8])`
- `keystream_block()`
##### `Snow3g`, `Snow3gCt`, `Zuc128`, `Zuc128Ct`
- `new(&[u8; 16], &[u8; 16])`
- `new_wiping(...)` where implemented
- `next_word()`
- `fill(&mut [u8])`
#### Mode and MAC types
##### `Ecb<C>`
- `new(cipher)`
- `cipher()`
- `encrypt_nopad(&mut [u8])`
- `decrypt_nopad(&mut [u8])`
##### `Cbc<C>` and `Cfb<C>`
- `new(cipher)`
- `cipher()`
- `encrypt_nopad(iv, &mut [u8])`
- `decrypt_nopad(iv, &mut [u8])`
##### `Ofb<C>` and `Ctr<C>`
- `new(cipher)`
- `cipher()`
- `apply_keystream(iv_or_counter, &mut [u8])`
##### `Xts<C>`
- `new(data_cipher, tweak_cipher)`
- `data_cipher()`
- `tweak_cipher()`
- `encrypt_sector(&[u8; 16], &mut [u8])`
- `decrypt_sector(&[u8; 16], &mut [u8])`
##### `Gcm<C>` and `GcmVt<C>`
- `new(cipher)`
- `cipher()`
- `compute_tag(nonce, aad, ciphertext)`
- `encrypt(nonce, aad, &mut [u8])`
- `decrypt(nonce, aad, &mut [u8], tag)`
##### `Gmac<C>` and `GmacVt<C>`
- `new(cipher)`
- `cipher()`
- `compute(nonce, aad)`
- `verify(nonce, aad, tag)`
##### `Cmac<C>`
- `new(cipher)`
- `cipher()`
- `compute(data)`
- `verify(data, tag)`
### Public-Key Surface
#### Integer and finite-field types
##### `RsaPublicKey`
- arithmetic:
- `exponent()`
- `modulus()`
- `encrypt_raw(&BigUint)`
- standard serialization:
- `to_pkcs1_der()`, `from_pkcs1_der(...)`
- `to_spki_der()`, `from_spki_der(...)`
- `to_pkcs1_pem()`, `from_pkcs1_pem(...)`
- `to_spki_pem()`, `from_spki_pem(...)`
- convenience serialization:
- `to_xml()`, `from_xml(...)`
##### `RsaPrivateKey`
- arithmetic:
- `exponent()`
- `modulus()`
- `decrypt_raw(&BigUint)`
- standard serialization:
- `to_pkcs1_der()`, `from_pkcs1_der(...)`
- `to_pkcs8_der()`, `from_pkcs8_der(...)`
- `to_pkcs1_pem()`, `from_pkcs1_pem(...)`
- `to_pkcs8_pem()`, `from_pkcs8_pem(...)`
- convenience serialization:
- `to_xml()`, `from_xml(...)`
##### `Rsa`
- `from_primes_with_exponent(...)`
- `from_primes(...)`
- `generate_with_exponent(rng, bits, e)`
- `generate(rng, bits)`
##### `RsaOaep<H>`
- `encrypt(public, label, message)`
- `encrypt_rng(public, label, message, rng)`
- `decrypt(private, label, ciphertext)`
##### `RsaPss<H>`
- `sign(private, message, salt)`
- `sign_rng(private, message, rng)`
- `verify(public, message, signature)`
##### `DhParams`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `DhPublicKey`
- `modulus()`
- `subgroup_order()`
- `generator()`
- `public_component()`
- `params()`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `DhPrivateKey`
- `modulus()`
- `subgroup_order()`
- `generator()`
- `exponent()`
- `to_public_key()`
- `params()`
- `agree_element(&DhPublicKey)`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `Dh`
- `generate_params(rng, bits)`
- `generate(&DhParams, rng)`
##### `DsaPublicKey`
- domain access:
- `modulus()`
- `subgroup_order()`
- `generator()`
- `public_component()`
- verification:
- `verify_message::<H>(...)`
- `verify_message_bytes::<H>(...)`
- `verify_digest_scalar(...)`
- `verify(digest, signature)`
- `verify_bytes(digest, signature_bytes)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `DsaPrivateKey`
- domain/key access:
- `modulus()`
- `subgroup_order()`
- `generator()`
- `exponent()`
- `to_public_key()`
- signing:
- `sign_digest_with_nonce(...)`
- `sign_digest::<H>(...)`
- `sign_digest_with_rng(...)`
- `sign_message::<H>(...)`
- `sign_message_with_rng::<H, R>(...)`
- `sign_digest_bytes::<H>(...)`
- `sign_digest_bytes_with_rng::<H, R>(...)`
- `sign_message_bytes::<H>(...)`
- `sign_message_bytes_with_rng::<H, R>(...)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `DsaSignature`
- `r()`
- `s()`
- `to_key_blob()`, `from_key_blob(...)`
##### `Dsa`
- `from_secret_exponent(...)`
- `generate(rng, bits)`
##### `ElGamalPublicKey`
- parameter access:
- `modulus()`
- `generator()`
- `ephemeral_exclusive_bound()`
- `public_component()`
- encryption:
- `encrypt_with_nonce(...)`
- `encrypt(message, rng)`
- `encrypt_bytes(message, rng)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `ElGamalPrivateKey`
- key access:
- `modulus()`
- `exponent()`
- `exponent_modulus()`
- decryption:
- `decrypt_raw(...)`
- `decrypt(...)`
- `decrypt_bytes(...)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `ElGamalCiphertext`
- `gamma()`
- `delta()`
- `to_key_blob()`, `from_key_blob(...)`
##### `ElGamal`
- `from_secret_exponent(...)`
- `generate(rng, bits)`
##### `PaillierPublicKey`
- parameter access:
- `modulus()`
- `generator()`
- `max_plaintext_exclusive()`
- encryption and homomorphism:
- `encrypt_with_nonce(...)`
- `encrypt(message, rng)`
- `encrypt_bytes(message, rng)`
- `rerandomize(ciphertext, rng)`
- `add_ciphertexts(lhs, rhs)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `PaillierPrivateKey`
- parameter access:
- `modulus()`
- `lambda()`
- `decryption_factor()`
- decryption:
- `decrypt_raw(...)`
- `decrypt(...)`
- `decrypt_bytes(...)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `Paillier`
- `from_primes_with_base(...)`
- `from_primes(...)`
- `generate(rng, bits)`
##### `Rabin`, `SchmidtSamoa`, `Cocks`
These educational integer-scheme families all expose the same broad pattern:
- public side:
- numeric accessors such as `modulus()` or `max_plaintext_exclusive()`
- `encrypt_raw(...)`
- `encrypt(...)`
- `encrypt_bytes(...)`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
- private side:
- scheme-specific key accessors
- `decrypt_raw(...)`
- `decrypt(...)`
- `decrypt_bytes(...)`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
- namespace:
- `from_primes(...)`
- `generate(rng, bits)`
#### Short-Weierstrass EC types
##### `CurveParams`
- constructors:
- `new(...)`
- `new_binary(...)`
- curve arithmetic:
- `gf2m_degree()`
- `base_point()`
- `is_on_curve(...)`
- `negate(...)`
- `add(...)`
- `double(...)`
- `scalar_mul(...)`
- `diffie_hellman(...)`
- `random_scalar(rng)`
- `generate_keypair(rng)`
- `scalar_invert(...)`
- point encoding:
- `encode_point(...)`
- `encode_point_compressed(...)`
- `decode_point(...)`
##### `AffinePoint`
- `infinity()`
- `new(x, y)`
- `is_infinity()`
##### `EcdhPublicKey`
- `curve()`
- `public_point()`
- `to_wire_bytes()`, `from_wire_bytes(curve, ...)`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EcdhPrivateKey`
- `curve()`
- `private_scalar()`
- `to_public_key()`
- `agree_x_coordinate(&EcdhPublicKey)`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `Ecdh`
- `generate(curve, rng)`
##### `EcdsaPublicKey`
- `curve()`
- `public_point()`
- `to_wire_bytes()`, `from_wire_bytes(curve, ...)`
- verification:
- `verify_message::<H>(...)`
- `verify_message_bytes::<H>(...)`
- `verify(digest, signature)`
- `verify_digest_scalar(...)`
- `verify_bytes(digest, signature_bytes)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EcdsaPrivateKey`
- `curve()`
- `private_scalar()`
- `to_public_key()`
- signing:
- `sign_digest_with_nonce(...)`
- `sign_digest::<H>(...)`
- `sign_digest_with_rng(...)`
- `sign_message::<H>(...)`
- `sign_message_with_rng::<H, R>(...)`
- `sign_digest_bytes::<H>(...)`
- `sign_digest_bytes_with_rng::<H, R>(...)`
- `sign_message_bytes::<H>(...)`
- `sign_message_bytes_with_rng::<H, R>(...)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EcdsaSignature`
- `r()`
- `s()`
- `to_key_blob()`, `from_key_blob(...)`
##### `Ecdsa`
- `generate(curve, rng)`
- `from_secret_scalar(curve, secret)`
##### `EciesPublicKey`
- `curve()`
- `public_point()`
- `to_wire_bytes()`, `from_wire_bytes(curve, ...)`
- `encrypt(message, rng)`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EciesPrivateKey`
- `curve()`
- `private_scalar()`
- `to_public_key()`
- `decrypt(ciphertext_bytes)`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `Ecies`
- `generate(curve, rng)`
##### `EcElGamalPublicKey`
- `curve()`
- `public_point()`
- `to_wire_bytes()`, `from_wire_bytes(curve, ...)`
- encryption:
- `encrypt_point(...)`
- `encrypt_point_with_nonce(...)`
- `encrypt(...)`
- `encrypt_int(...)`
- `add_ciphertexts(...)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EcElGamalPrivateKey`
- `curve()`
- `private_scalar()`
- `to_public_key()`
- decryption:
- `decrypt_point(...)`
- `decrypt(...)`
- `decrypt_int(...)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EcElGamalCiphertext`
- `c1()`
- `c2()`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EcElGamal`
- `generate(curve, rng)`
#### Edwards-curve types
##### `TwistedEdwardsCurve`
- constructors and curve identity:
- `new(...)`
- `same_curve(...)`
- curve arithmetic:
- `base_point()`
- `is_on_curve(...)`
- `negate(...)`
- `add(...)`
- `double(...)`
- `scalar_mul(...)`
- `scalar_mul_base(...)`
- `diffie_hellman(...)`
- `random_scalar(rng)`
- `generate_keypair(rng)`
- `scalar_invert(...)`
- point encoding:
- `encode_point(...)`
- `decode_point(...)`
##### `EdwardsPoint`
- `neutral()`
- `new(x, y)`
- `is_neutral()`
##### `Ed25519PublicKey`
- `public_point()`
- `to_key_blob()`, `from_key_blob(...)`
- `to_raw_bytes()`, `from_raw_bytes(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
- verification:
- `verify_message(...)`
- `verify_message_bytes(...)`
##### `Ed25519PrivateKey`
- `seed()`
- `scalar()`
- `to_public_key()`
- `to_key_blob()`, `from_key_blob(...)`
- `to_raw_bytes()`, `from_raw_bytes(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
- signing:
- `sign_message(...)`
- `sign_message_bytes(...)`
##### `Ed25519Signature`
- `nonce_point()`
- `response()`
- `to_key_blob()`, `from_key_blob(...)`
##### `Ed25519`
- `generate(rng)`
- `from_seed([u8; 32])`
##### `EdDsaPublicKey`
- `curve()`
- `public_point()`
- `to_wire_bytes()`, `from_wire_bytes(curve, ...)`
- verification:
- `verify_message::<H>(...)`
- `verify_message_bytes::<H>(...)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EdDsaPrivateKey`
- `curve()`
- `private_scalar()`
- `public_point()`
- `to_public_key()`
- signing:
- `sign_message_with_nonce::<H>(...)`
- `sign_message::<H, R>(...)`
- `sign_message_bytes::<H, R>(...)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EdDsaSignature`
- `nonce_point()`
- `response()`
- `to_key_blob()`
- `from_key_blob(blob, curve)`
##### `EdDsa`
- `generate(curve, rng)`
- `from_secret_scalar(curve, secret)`
##### `EdwardsDhPublicKey`
- `curve()`
- `public_point()`
- `to_wire_bytes()`, `from_wire_bytes(curve, ...)`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EdwardsDhPrivateKey`
- `curve()`
- `private_scalar()`
- `to_public_key()`
- `agree_compressed_point(&EdwardsDhPublicKey)`
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EdwardsDh`
- `generate(curve, rng)`
##### `EdwardsElGamalPublicKey`
- `curve()`
- `public_point()`
- `to_wire_bytes()`, `from_wire_bytes(curve, ...)`
- encryption:
- `encrypt_point(...)`
- `encrypt_point_with_nonce(...)`
- `encrypt_int(...)`
- `add_ciphertexts(...)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EdwardsElGamalPrivateKey`
- `curve()`
- `private_scalar()`
- `to_public_key()`
- decryption:
- `decrypt_point(...)`
- `decrypt_int(...)`
- serialization:
- `to_key_blob()`, `from_key_blob(...)`
- `to_pem()`, `from_pem(...)`
- `to_xml()`, `from_xml(...)`
##### `EdwardsElGamalCiphertext`
- `c1()`
- `c2()`
- `to_key_blob()`
- `from_key_blob(curve, blob)`
- `to_pem()`
- `from_pem(curve, pem)`
- `to_xml()`
- `from_xml(curve, xml)`
##### `EdwardsElGamal`
- `generate(curve, rng)`
#### Post-quantum lattice types
##### `MlKemParameterSet`
- `MlKem512`, `MlKem768`, `MlKem1024`
- `k()`
- `public_key_len()`
- `private_key_len()`
- `ciphertext_len()`
- `shared_secret_len()`
##### `MlKemPublicKey`
- metadata:
- `parameter_set()`
- encoding:
- `to_wire_bytes()`, `from_wire_bytes(params, ...)`
- `to_key_blob()`, `from_key_blob(...)`
##### `MlKemPrivateKey`
- metadata:
- `parameter_set()`
- encoding:
- `to_wire_bytes()`, `from_wire_bytes(params, ...)`
- `to_key_blob()`, `from_key_blob(...)`
##### `MlKemCiphertext`
- metadata:
- `parameter_set()`
- encoding:
- `to_wire_bytes()`, `from_wire_bytes(params, ...)`
##### `MlKemSharedSecret`
- `to_wire_bytes()`
- `from_wire_bytes(...)`
##### `MlKem`
- `keygen(params, rng)`
- `keygen_from_seed(params, d, z)`
- `encaps(public_key, rng)`
- `encaps_with_randomness(public_key, m)`
- `decaps(private_key, ciphertext)`
##### `MlDsaParameterSet`
- `MlDsa44`, `MlDsa65`, `MlDsa87`
- `public_key_len()`
- `private_key_len()`
- `signature_len()`
##### `MlDsaPublicKey`
- metadata:
- `parameter_set()`
- encoding:
- `to_wire_bytes()`, `from_wire_bytes(params, ...)`
- `to_key_blob()`, `from_key_blob(...)`
##### `MlDsaPrivateKey`
- metadata:
- `parameter_set()`
- encoding:
- `to_wire_bytes()`, `from_wire_bytes(params, ...)`
- `to_key_blob()`, `from_key_blob(...)`
##### `MlDsaSignature`
- metadata:
- `parameter_set()`
- encoding:
- `to_wire_bytes()`, `from_wire_bytes(params, ...)`
##### `MlDsa`
- `keygen(params, rng)`
- `keygen_from_seed(params, seed)`
- `sign(private_key, message, rng)`
- `sign_with_randomness(private_key, message, rnd)`
- `sign_with_randomness_and_context(private_key, message, rnd, ctx)`
- `verify(public_key, message, signature)`
- `verify_with_context(public_key, message, signature, ctx)`
#### RFC 7748 constant-time ECDH types
##### `X25519`
- `scalar_mult(&[u8; 32], &[u8; 32]) -> [u8; 32]`
- `scalar_mult_base(&[u8; 32]) -> [u8; 32]`
- `generate(rng) -> (X25519PublicKey, X25519PrivateKey)`
##### `X25519PrivateKey`
- `from_raw_bytes(&[u8; 32])`
- `from_raw_bytes_wiping(&mut [u8; 32])`
- `to_raw_bytes()`
- `to_public_key()`
- `agree(&X25519PublicKey) -> Option<[u8; 32]>`
##### `X25519PublicKey`
- `from_raw_bytes(&[u8; 32])`
- `to_raw_bytes()`
##### `X448`
- `scalar_mult(&[u8; 56], &[u8; 56]) -> [u8; 56]`
- `scalar_mult_base(&[u8; 56]) -> [u8; 56]`
- `generate(rng) -> (X448PublicKey, X448PrivateKey)`
##### `X448PrivateKey`
- `from_raw_bytes(&[u8; 56])`
- `from_raw_bytes_wiping(&mut [u8; 56])`
- `to_raw_bytes()`
- `to_public_key()`
- `agree(&X448PublicKey) -> Option<[u8; 56]>`
##### `X448PublicKey`
- `from_raw_bytes(&[u8; 56])`
- `to_raw_bytes()`