A safe pure-rust implementation of the Saber post-quantum scheme.
sha3
as SHA-3 implementation and aes
as AES block cipher (used as RNG) implementationAnyone, how wants to utilize Saber to negotiate a symmetric key between two parties.
Add this to your Cargo.toml
:
toml
[dependencies]
rusty-saber = "1.0"
To use a specific Saber variant, you need to import it with the corresponding feature flag:
toml
[dependencies]
rusty-saber = { version = "1.0", features = ["lightsaber"] }
Feature flags for the three variants are called lightsaber
, saber
, and firesaber
respectively.
The simple
example illustrates the API:
```rust
use rustysaber::api::{
CRYPTOBYTES, CRYPTOCIPHERTEXTBYTES, CRYPTOPUBLICKEYBYTES, CRYPTOSECRETKEYBYTES,
};
use rustysaber::kem::{cryptokemdec, cryptokemenc, cryptokemkeypair};
use rusty_saber::rng::AesState;
use std::error::Error;
fn main() -> Result<(), Box
// Party a: generate public key pk
and secret key sk
cryptokemkeypair(&mut pk, &mut sk, &mut rng)?;
// Party b: generate a shared secret ss_a
and ciphertext ct
from the public key pk
cryptokemenc(&mut ct, &mut ssa, &mut pk, &mut rng)?;
// Party a: derive the same shared secret ss_b
from the ciphertext ct
and the secret key sk
cryptokemdec(&mut ssb, &mut ct, &mut sk)?;
asserteq!(ssa, ss_b); Ok(()) } ```
This library comes with two examples:
bash
$ cargo run --example simple
The pqcgenkat_kem
example implements the classic request/response file structure which is part of the NIST PQC framework.
bash
$ cargo run --example pqcgenkat_kem
$ ls *.r??
PQCkemKAT_2304.req PQCkemKAT_2304.rsp
$ tail -n 2 PQCkemKAT_2304.rsp
ss = E5256B4F25816367FBE235E47C25ABB78195CEF7DE3F9C77926839F209CDF652
The different variants can be enabled through feature flags:
bash
$ cargo run --example pqcgenkat_kem --features lightsaber
$ ls *.r??
PQCkemKAT_1568.req PQCkemKAT_1568.rsp
saber
is the default variant. Unfortunately, you cannot enable two variants simultaneously.
Yes. You can run unittests with the following commands:
bash
$ cargo test --features cref,lightsaber
$ cargo test --features cref
$ cargo test --features cref,firesaber
It compares the output of function calls with its C equivalent.
Besides unittests, you can generate the pqcgenkat_kem
req/rsp files and compare them to the ones generated by the C reference implementation.
We verified that they are equivalent.
Yes, but it takes roughly 16.2% more runtime than the C implementation. Here, data is always mentioned with clock cycles as unit. The rust implementation has the following clock-cycle count characteristics (the smaller the better):
complete KEM | keypair | enc | dec | |
lightsaber | 329,964 | 86,665 | 116,139 | 121,433 |
saber | 586,544 | 182,183 | 216,528 | 232,882 |
firesaber | 923,330 | 282,467 | 318,043 | 335,297 |
The C reference implementation has the following clock-cycle count characteristics (the smaller the better):
complete KEM | keypair | enc | dec | |
lightsaber | 284,558 | 72,785 | 95,936 | 115,837 |
saber | 509,361 | 140,370 | 174,995 | 193,996 |
firesaber | 785,548 | 222,955 | 268,561 | 294,032 |
The tests were done on a Lenovo Thinkpad x260 (Intel Core i5-6200U CPU @ 2.30GHz). In the case of rust, criterion 0.3.5 has been used as given in benches/
and in case of C, the rudimentary code utilizing the TSC register provided with the reference implementation is used. I disabled CPU frequency scaling before running experiments. You can run the benchmark suite yourself with the bench
subcommand, the cref
feature and optionally some variant feature flag:
bash
$ cargo bench --features cref,lightsaber
$ cargo bench --features cref
$ cargo bench --features cref,firesaber
On github.
On github.