# sntrup-sys
[](https://crates.io/crates/sntrup-sys)
[](https://docs.rs/sntrup-sys)
[](Cargo.toml)
[](LICENSE.md)
A standalone, single-algorithm Rust bindings to **Streamlined NTRU Prime**,
a post-quantum key encapsulation mechanism (KEM). The C reference implementation
is vendored from [SUPERCOP](https://bench.cr.yp.to/supercop.html) and
compiled with the [`cc`](https://crates.io/crates/cc) crate — no system package,
no submodule, no network access at build time. Portable ISO C11, no CPU-specific
intrinsics (yet), so it builds anywhere a C compiler does.
## Usage
```rust
let (pk, sk) = sntrup_sys::sntrup761::keypair();
let (ct, ss1) = sntrup_sys::sntrup761::encapsulate(&pk);
let ss2 = sntrup_sys::sntrup761::decapsulate(&ct, &sk);
assert_eq!(ss1, ss2);
```
Every parameter set exposes the same three functions plus
`PUBLIC_KEY_BYTES`/`SECRET_KEY_BYTES`/`CIPHERTEXT_BYTES`/`SHARED_SECRET_BYTES`
constants (see `src/lib.rs`).
## Parameter sets
All six are gated behind their own Cargo feature (all on by default), so
you can trim the build to just what you need with
`default-features = false, features = ["sntrup761"]`. Sizes in bytes:
| `sntrup653` | 1 | 994 | 1518 | 897 | 32 |
| `sntrup761` | 2 | 1158 | 1763 | 1039 | 32 |
| `sntrup857` | 3 | 1322 | 1999 | 1184 | 32 |
| `sntrup953` | 4 | 1505 | 2254 | 1349 | 32 |
| `sntrup1013` | 4 | 1623 | 2417 | 1455 | 32 |
| `sntrup1277` | 5 | 2067 | 3059 | 1847 | 32 |
`sntrup761` is the one used in OpenSSH's `sntrup761x25519-sha512` hybrid
key exchange. Sizes are taken directly from each parameter set's `api.h`
and were confirmed by this crate's own build validation. NIST categories:
`sntrup761` = Category 2 is confirmed directly by
[liboqs](https://github.com/open-quantum-safe/liboqs/blob/main/docs/algorithms/kem/ntruprime.md);
the rest follow the same monotonic mapping commonly cited across the
NTRU Prime ecosystem — if the exact category matters for a compliance
requirement, verify against the
[official submission](https://ntruprime.cr.yp.to/).
Only the `ref` (portable ISO C11) implementation is included; SUPERCOP's
only alternative is x86-64-only hand-written assembly with avx2 feature,
which is on the to-do list for this crate.
## Benchmarking
```bash
cargo bench
```
Uses [`criterion`](https://crates.io/crates/criterion) to benchmark
keypair/encapsulate/decapsulate for every enabled parameter set, with
proper warm-up, iteration-count tuning, outlier rejection, and a confidence
interval, unlike a bare timer loop. Numbers are still environment-sensitive
(CPU, and the platform's random-number-source call overhead), so run it on
hardware you actually care about rather than trusting a number quoted here.
For a third-party reference point, SUPERCOP publishes its own cycle counts
for the `ref` implementation across many CPUs: <https://bench.cr.yp.to/results-kem.html>.
## Randomness
The vendored C code calls one external C function, `randombytes(unsigned
char *, unsigned long long)`, for all key-generation and encapsulation
randomness. `src/lib.rs` implements it via the `getrandom` crate (the OS
CSPRNG) — the one piece of "dependency" the vendored C itself doesn't supply,
by SUPERCOP's own convention.
## Platform notes
`build.rs` targets both compiler families that matter on Windows, not just
one:
- **GCC/Clang** (`*-gnu`, and any Unix target): uses `-include` to
force-include each directory's `namespace.h` ahead of everything else,
and `-D` for the `CRYPTO_NAMESPACE`-style defines.
- **MSVC's `cl.exe`** (`*-pc-windows-msvc` — the
[Rust team's recommended Windows target](https://forge.rust-lang.org/infra/other-installation-methods.html#the-toolchains-available),
not the `-gnu`/MinGW one): `cl.exe` doesn't understand `-include` at
all — its equivalent is `/FI`, and it needs `/D` instead of `-D`.
`build.rs` detects this from `TARGET` and switches spelling.
Getting the flags right wasn't quite the whole story, though: `cl.exe`
(real MSVC, not `clang-cl`) also doesn't understand the GCC/Clang
`__attribute__((...))` extension used in the vendored `cryptoint` headers
under `vendor/common/`. Since those files are untouched autogen output
(see [`vendor/NOTICE.md`](vendor/NOTICE.md)) and not something to hand-edit,
`vendor/common/namespace.h` neutralizes `__attribute__` to a no-op macro
specifically when `_MSC_VER` is defined and neither `__GNUC__` nor
`__clang__` is — i.e. only for real `cl.exe`, not `clang-cl`, which already
understands the extension natively. The same headers also contain inline
GCC-style `__asm__` blocks, but every one is already guarded behind
`#if defined(__GNUC__)` with a portable C fallback, and `cl.exe` never
defines `__GNUC__`, so those need no shim at all.
All of that said: this has only been **compiled and tested on `clang` on
macOS (arm64)** so far. The MSVC path above is a from-first-principles fix
for a real, checked incompatibility (verified by reading `cl.exe`'s actual
documented flag set and grepping every vendored file for GCC/Clang-only
constructs), not something run through an actual Windows/MSVC toolchain —
there isn't one available in this environment. Treat it as "should work,
please verify" rather than "verified," and file an issue with the actual
compiler error if it doesn't.
## Internals
`vendor/` is a deduplicated extraction from SUPERCOP: the generic helper
layer (SHA-512, sort networks, `crypto_declassify`, the `cryptoint`
headers) compiles once and is shared by every parameter set, while the
Streamlined NTRU Prime algorithm itself is stored once but compiled once
per parameter set (the object code genuinely differs — parameter sizes are
baked in at compile time). See [`vendor/NOTICE.md`](vendor/NOTICE.md) for
exactly what was changed from the original SUPERCOP sources, why the split
is drawn where it is, and how the extraction was validated — worth reading
before modifying anything under `vendor/`.
## License
This crate's own code (`build.rs`, `src/lib.rs`, `benches/`) is dual-licensed
under MIT ([`LICENSE-MIT`](LICENSE-MIT)) or Apache-2.0
([`LICENSE-APACHE`](LICENSE-APACHE)), at your option. The vendored
Streamlined NTRU Prime sources under `vendor/algo/` are **not** covered by
that — they're Daniel J. Bernstein and coauthors' code, and the only usage
grant on record from them is purpose-scoped to NIST's public review
process, not a general open-source release. See [`LICENSE.md`](LICENSE.md)
for the full split and [`vendor/NOTICE.md`](vendor/NOTICE.md) for the
source-by-source breakdown — read both before relying on this past
experimentation.