Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/sntrup-kem.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jobs:
- run: cargo test --no-default-features
- run: cargo test
- run: cargo test --all-features
- run: cargo test --features kem
- run: cargo test --features serde,force-scalar

cross:
Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions sntrup-kem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ categories = ["algorithms", "cryptography"]
readme = "README.md"
edition = "2024"

[package.metadata.docs.rs]
features = ["kem", "serde"]

[features]
default = ["kgen", "ecap", "dcap"]
kgen = []
Expand All @@ -19,6 +22,7 @@ dcap = []
alloc = []
force-scalar = []
std = []
kem = ["dep:hybrid-array", "dep:kem", "dep:rand_core", "kgen", "ecap", "dcap"]
serde = ["dep:serdect", "dep:serde"]
js = ["getrandom/wasm_js"]

Expand All @@ -28,6 +32,9 @@ rand = "0.10.0"
rand_chacha = "0.10.0"
subtle = "2"
getrandom = { version = "0.4", optional = true }
hybrid-array = { version = "0.4.14", features = ["extra-sizes"], optional = true }
kem = { version = "0.3", optional = true }
rand_core = { version = "0.10", optional = true }
serde = { version = "1", optional = true, default-features = false }
serdect = { version = "0.4", optional = true }
# sha2 0.11 dropped the `asm` feature; hardware SHA acceleration is now selected
Expand All @@ -40,6 +47,10 @@ zeroize = { version = "1", features = ["derive"] }
criterion = "0.7"
serde_json = "1"

[[example]]
name = "kem_traits"
required-features = ["kem"]

[[bench]]
name = "mod"
harness = false
Expand Down
24 changes: 24 additions & 0 deletions sntrup-kem/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ The KEM API is split into three default features so downstream crates can pull i
| `kgen` | **yes** | Key generation: `SntrupKem::generate_key`, `SntrupKem::generate_key_deterministic` |
| `ecap` | **yes** | Encapsulation: `EncapsulationKey::encapsulate` |
| `dcap` | **yes** | Decapsulation: `DecapsulationKey::decapsulate` |
| `kem` | no | Implements the [`kem`](https://docs.rs/kem) crate traits for every parameter set |
| `force-scalar` | no | Disable SIMD (AVX2/NEON) and use pure-Rust scalar code |
| `serde` | no | Enables `Serialize`/`Deserialize` for all key and ciphertext types (via `serdect` for constant-time hex encoding) |
| `js` | no | Enables WebAssembly support for `wasm32-unknown-unknown` by configuring `getrandom` to use JavaScript's `crypto.getRandomValues()` |
Expand Down Expand Up @@ -175,6 +176,29 @@ let ek2 = EncapsulationKey::<Sntrup761Params>::try_from(ek_bytes).unwrap();
assert_eq!(ek, ek2);
```

### `kem` crate integration

Enable the `kem` feature to use any parameter set through the generic
[`kem`](https://docs.rs/kem) traits:

```rust
# #[cfg(feature = "kem")] {
use rand::SeedableRng;
use rand::rngs::{StdRng, SysRng};
use sntrup_kem::kem::{Decapsulate, Encapsulate, Kem, Sntrup761Params};

let Ok(mut rng) = StdRng::try_from_rng(&mut SysRng) else {
return;
};
let (dk, ek) = Sntrup761Params::generate_keypair_from_rng(&mut rng);
let (ct, sent) = ek.encapsulate_with_rng(&mut rng);
assert_eq!(dk.decapsulate(&ct), sent);
# }
```

The module re-exports the traits and parameter-set marker types. See
`examples/kem_traits.rs` for generic use and key import/export.

## WebAssembly

To compile for `wasm32-unknown-unknown`, enable the `js` feature so that `getrandom` uses JavaScript's `crypto.getRandomValues()` for randomness:
Expand Down
43 changes: 43 additions & 0 deletions sntrup-kem/examples/kem_traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//! Streamlined NTRU Prime through the [`kem`](https://docs.rs/kem) crate traits.

use rand::SeedableRng;
use rand::rngs::{StdRng, SysRng};
use rand_core::CryptoRng;
use sntrup_kem::kem::{
Decapsulate, DecapsulationKey, Decapsulator, Encapsulate, EncapsulationKey, Generate, Kem,
KemSizes, KeyExport, Sntrup653Params, Sntrup761Params, Sntrup1277Params, TryKeyInit,
};

fn round_trip<K>(mut rng: impl CryptoRng) -> (usize, usize)
where
K: KemSizes
+ Kem<EncapsulationKey = EncapsulationKey<K>, DecapsulationKey = DecapsulationKey<K>>,
{
let (dk, ek) = K::generate_keypair_from_rng(&mut rng);
let (ct, sent) = ek.encapsulate_with_rng(&mut rng);
let received = dk.decapsulate(&ct);
assert_eq!(sent, received);
(ct.len(), received.len())
}

fn main() {
let Ok(mut rng) = StdRng::try_from_rng(&mut SysRng) else {
return;
};

for (ct, ss) in [
round_trip::<Sntrup653Params>(&mut rng),
round_trip::<Sntrup761Params>(&mut rng),
round_trip::<Sntrup1277Params>(&mut rng),
] {
assert!(ct > 0);
assert_eq!(ss, 32);
}

let dk = DecapsulationKey::<Sntrup761Params>::generate_from_rng(&mut rng);
let exported = dk.encapsulation_key().to_bytes();
let Ok(imported) = EncapsulationKey::<Sntrup761Params>::new(&exported) else {
return;
};
assert_eq!(&imported, dk.encapsulation_key());
}
Loading