Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/itzmeanjan/saber

Saber: Post-Quantum Key Encapsulation Mechanism
https://github.com/itzmeanjan/saber

kem key-encapsulation-mechanism learing-with-rounding mlwr pke post-quantum-cryptography public-key-encryption saber

Last synced: 12 days ago
JSON representation

Saber: Post-Quantum Key Encapsulation Mechanism

Awesome Lists containing this project

README

        

# saber
Saber: Post-Quantum Key Encapsulation Mechanism

> **Warning**
This header-only library implementation of Saber KEM is made to behave constant-time though it's not yet audited. If you consider using it in production environment, be careful !

## Overview

Saber is a family of cryptographic primitives that rely on the hardness of the Module Learning With Rounding (Mod-LWR) problem. Saber offers an IND-CPA secure public key encryption algorithm, which is transformed to an IND-CCA secure key encapsulation mechanism, using a version of Fujisaki-Okamoto transform.

It's a header-only C++ library implementation of Saber KEM scheme(s), as described in specification https://www.esat.kuleuven.be/cosic/pqcrypto/saber/files/saberspecround3.pdf and instantiating all parameter sets, suggested

- (a) In section 8.1, on table 8 [**Samples from Centered Binomial Distribution**]
- (b) In section A.2, on table 9 [**Samples from Centered Uniform Distribution**]

of the Saber specification.

Sampling of secret vector ? | KEM Implemented
--- | ---
From Centered Binomial Distribution | LightSaber, Saber and FireSaber
From Centered Uniform Distribution | uLightSaber, uSaber and uFireSaber

> **Warning**
This library **doesn't** implement `-90s` variants of KEM, only SHAKE-based variants are implemented.

KEM schemes offer three main algorithms.

Algorithm | Input | Output | How is it used ?
--- | :-: | :-: | --:
keygen | 32 -bytes random seed `seedA`, 32 -bytes random noise `seedS` and 32 -bytes random key `z` | Public and private keypair | Imagine two parties `peer0` & `peer1`, want to securely ( using symmetric key encryption i.e. some AEAD scheme ) communicate over insecure channel. One of them, say `peer0`, generates an ephemeral KEM keypair and publish its public key to other peer i.e. `peer1`.
encaps | 32 -bytes random seed `m` and receiver's public key | Cipher text and 32 -bytes session key | `Peer1` encapsulates 32 -bytes message inside cipher text, using `peer0`'s public key. And then it shares the cipher text with `peer0`, over insecure channel. Finally `peer1` also derives a 32 -bytes session key, which it can now use with symmetric key constructions.
decaps | Cipher text and receiver's private key | 32 -bytes session key | `Peer0` uses its private key for decapsulating the cipher text it received from `peer1`, deriving the same 32 -bytes session key. Now both of the parties have same 32 -bytes session key, they can use it for enciphering their communication.

For learning more about Saber, follow their website @ https://www.esat.kuleuven.be/cosic/pqcrypto/saber. Also note that Saber was a round 3 finalist of NIST PQC standardization effort, more @ https://csrc.nist.gov/Projects/post-quantum-cryptography/post-quantum-cryptography-standardization/round-3-submissions.

## Prerequisites

- A C++ compiler with C++20 standard library.

```bash
$ g++ --version
g++ (Ubuntu 13.2.0-4ubuntu3) 13.2.0

$ clang++ --version
Ubuntu clang version 17.0.2 (1~exp1ubuntu2.1)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
```

- Build tools.

```bash
$ make --version
GNU Make 4.3
Built for x86_64-pc-linux-gnu

$ cmake --version
cmake version 3.27.4
```

- For testing functional correctness of Saber KEM and its components, you need to globally install `google-test` headers and library. Follow [this](https://github.com/google/googletest/tree/main/googletest#standalone-cmake-project) guide.
- For benchmarking Saber KEM algorithms, you need to globally install `google-benchmark` headers and library. Follow [this](https://github.com/google/benchmark#installation) guide.

> **Note**
If you are on a machine running GNU/Linux kernel and you want to obtain CPU cycle count for KEM algorithms, you should consider building `google-benchmark` library with libPFM support, following [this](https://gist.github.com/itzmeanjan/05dc3e946f635d00c5e0b21aae6203a7) step-by-step guide. Find more about libPFM @ https://perfmon2.sourceforge.net.

- Saber KEM has two dependencies ( i.e. `sha3` and `subtle` ), managed by git submodule. After cloning this repository, you must run following command inside root of this repository, so that you can test/ benchmark/ use it.

```bash
git clone https://github.com/itzmeanjan/saber.git
pushd saber
git submodule update --init # <-- Import dependencies
popd

# Or just clone it like
git clone https://github.com/itzmeanjan/saber.git --recurse-submodules
```

## Testing

For testing functional correctness and ensuring that this implementation is conforming to the Saber KEM specification, issue following command.

> **Warning**
Conformance to the specification is ensured by using known answer test files, generated by following instructions @ https://gist.github.com/itzmeanjan/e499eba2b8c42f150a795d9e1c3c5dea. Generated known answer test files live under [kats](./kats/) directory.

```bash
make -j
```

```bash
[==========] Running 20 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 20 tests from SaberKEM
[ RUN ] SaberKEM.LightSaberKeyEncapsulationMechanism
[ OK ] SaberKEM.LightSaberKeyEncapsulationMechanism (0 ms)
[ RUN ] SaberKEM.SaberKeyEncapsulationMechanism
[ OK ] SaberKEM.SaberKeyEncapsulationMechanism (0 ms)
[ RUN ] SaberKEM.FireSaberKeyEncapsulationMechanism
[ OK ] SaberKEM.FireSaberKeyEncapsulationMechanism (0 ms)
[ RUN ] SaberKEM.uLightSaberKeyEncapsulationMechanism
[ OK ] SaberKEM.uLightSaberKeyEncapsulationMechanism (0 ms)
[ RUN ] SaberKEM.uSaberKeyEncapsulationMechanism
[ OK ] SaberKEM.uSaberKeyEncapsulationMechanism (0 ms)
[ RUN ] SaberKEM.uFireSaberKeyEncapsulationMechanism
[ OK ] SaberKEM.uFireSaberKeyEncapsulationMechanism (0 ms)
[ RUN ] SaberKEM.LightSaberKnownAnswerTests
[ OK ] SaberKEM.LightSaberKnownAnswerTests (19 ms)
[ RUN ] SaberKEM.SaberKnownAnswerTests
[ OK ] SaberKEM.SaberKnownAnswerTests (37 ms)
[ RUN ] SaberKEM.FireSaberKnownAnswerTests
[ OK ] SaberKEM.FireSaberKnownAnswerTests (61 ms)
[ RUN ] SaberKEM.uLightSaberKnownAnswerTests
[ OK ] SaberKEM.uLightSaberKnownAnswerTests (19 ms)
[ RUN ] SaberKEM.uSaberKnownAnswerTests
[ OK ] SaberKEM.uSaberKnownAnswerTests (38 ms)
[ RUN ] SaberKEM.uFireSaberKnownAnswerTests
[ OK ] SaberKEM.uFireSaberKnownAnswerTests (63 ms)
[ RUN ] SaberKEM.LightSaberPublicKeyEncryption
[ OK ] SaberKEM.LightSaberPublicKeyEncryption (0 ms)
[ RUN ] SaberKEM.SaberPublicKeyEncryption
[ OK ] SaberKEM.SaberPublicKeyEncryption (0 ms)
[ RUN ] SaberKEM.FireSaberPublicKeyEncryption
[ OK ] SaberKEM.FireSaberPublicKeyEncryption (0 ms)
[ RUN ] SaberKEM.uLightSaberPublicKeyEncryption
[ OK ] SaberKEM.uLightSaberPublicKeyEncryption (0 ms)
[ RUN ] SaberKEM.uSaberPublicKeyEncryption
[ OK ] SaberKEM.uSaberPublicKeyEncryption (0 ms)
[ RUN ] SaberKEM.uFireSaberPublicKeyEncryption
[ OK ] SaberKEM.uFireSaberPublicKeyEncryption (0 ms)
[ RUN ] SaberKEM.PolynomialMatrixConversion
[ OK ] SaberKEM.PolynomialMatrixConversion (0 ms)
[ RUN ] SaberKEM.PolynomialConversion
[ OK ] SaberKEM.PolynomialConversion (0 ms)
[----------] 20 tests from SaberKEM (244 ms total)

[----------] Global test environment tear-down
[==========] 20 tests from 1 test suite ran. (244 ms total)
[ PASSED ] 20 tests.
```

## Benchmarking

For benchmarking Saber KEM algorithms ( i.e. keygen, encaps and decaps ), instantiated with various suggested parameters, targeting CPU systems, issue following command.

> **Warning**
When benchmarking, ensure that you've disabled CPU frequency scaling, by following [this](https://github.com/google/benchmark/blob/main/docs/reducing_variance.md) guide.

> **Note**
`make perf` - was issued when collecting following benchmarks. Notice, *CYCLES* column, denoting latency of Saber KEM routines. Follow [this](https://github.com/google/benchmark/blob/main/docs/perf_counters.md) for more details.

```bash
make benchmark # If you haven't built google-benchmark library with libPFM support.
make perf # Must do if you have built google-benchmark library with libPFM support.
```

### On 12th Gen Intel(R) Core(TM) i7-1260P ( compiled with Clang-16.0.0 )

```bash
2023-10-20T22:49:28+04:00
Running ./build/perf.out
Run on (16 X 3698.59 MHz CPU s)
CPU Caches:
L1 Data 48 KiB (x8)
L1 Instruction 32 KiB (x8)
L2 Unified 1280 KiB (x8)
L3 Unified 18432 KiB (x1)
Load Average: 0.45, 0.42, 0.45
------------------------------------------------------------------------------------------------
Benchmark Time CPU Iterations CYCLES items_per_second
------------------------------------------------------------------------------------------------
firesaber/decaps_mean 84.4 us 84.4 us 8 382.872k 11.851k/s
firesaber/decaps_median 84.6 us 84.6 us 8 382.598k 11.8185k/s
firesaber/decaps_stddev 1.05 us 1.06 us 8 835.441 150.718/s
firesaber/decaps_cv 1.25 % 1.25 % 8 0.22% 1.27%
firesaber/decaps_min 82.1 us 82.1 us 8 382.111k 11.6945k/s
firesaber/decaps_max 85.5 us 85.5 us 8 384.602k 12.1856k/s
saber/keygen_mean 34.0 us 34.0 us 8 154.762k 29.3921k/s
saber/keygen_median 33.9 us 33.9 us 8 154.676k 29.4594k/s
saber/keygen_stddev 0.553 us 0.553 us 8 294.139 477.5/s
saber/keygen_cv 1.62 % 1.62 % 8 0.19% 1.62%
saber/keygen_min 33.2 us 33.2 us 8 154.461k 28.7492k/s
saber/keygen_max 34.8 us 34.8 us 8 155.396k 30.1616k/s
lightsaber/decaps_mean 29.0 us 29.0 us 8 131.401k 34.4513k/s
lightsaber/decaps_median 29.0 us 29.0 us 8 131.343k 34.4486k/s
lightsaber/decaps_stddev 0.495 us 0.496 us 8 254.65 591.838/s
lightsaber/decaps_cv 1.71 % 1.71 % 8 0.19% 1.72%
lightsaber/decaps_min 28.2 us 28.2 us 8 131.093k 33.7379k/s
lightsaber/decaps_max 29.6 us 29.6 us 8 131.927k 35.4728k/s
firesaber/encaps_mean 74.4 us 74.4 us 8 336.196k 13.4449k/s
firesaber/encaps_median 74.4 us 74.4 us 8 336.23k 13.436k/s
firesaber/encaps_stddev 0.844 us 0.844 us 8 242.034 152.866/s
firesaber/encaps_cv 1.13 % 1.13 % 8 0.07% 1.14%
firesaber/encaps_min 73.2 us 73.2 us 8 335.804k 13.2467k/s
firesaber/encaps_max 75.5 us 75.5 us 8 336.599k 13.6657k/s
ulightsaber/keygen_mean 15.9 us 15.9 us 8 73.0721k 62.829k/s
ulightsaber/keygen_median 15.9 us 15.9 us 8 73.0414k 62.8434k/s
ulightsaber/keygen_stddev 0.185 us 0.185 us 8 134.7 723.397/s
ulightsaber/keygen_cv 1.16 % 1.16 % 8 0.18% 1.15%
ulightsaber/keygen_min 15.7 us 15.7 us 8 72.9107k 61.3224k/s
ulightsaber/keygen_max 16.3 us 16.3 us 8 73.3453k 63.8755k/s
saber/decaps_mean 54.8 us 54.8 us 8 249.765k 18.2472k/s
saber/decaps_median 55.0 us 55.0 us 8 249.684k 18.1819k/s
saber/decaps_stddev 0.723 us 0.720 us 8 275.253 240.849/s
saber/decaps_cv 1.32 % 1.31 % 8 0.11% 1.32%
saber/decaps_min 53.7 us 53.7 us 8 249.425k 17.9502k/s
saber/decaps_max 55.7 us 55.7 us 8 250.185k 18.6314k/s
ufiresaber/decaps_mean 83.2 us 83.2 us 8 376.946k 12.015k/s
ufiresaber/decaps_median 83.1 us 83.1 us 8 376.767k 12.0328k/s
ufiresaber/decaps_stddev 0.941 us 0.936 us 8 459.823 132.987/s
ufiresaber/decaps_cv 1.13 % 1.12 % 8 0.12% 1.11%
ufiresaber/decaps_min 82.3 us 82.3 us 8 376.597k 11.7139k/s
ufiresaber/decaps_max 85.4 us 85.4 us 8 377.83k 12.1555k/s
ulightsaber/decaps_mean 28.4 us 28.4 us 8 128.592k 35.163k/s
ulightsaber/decaps_median 28.5 us 28.5 us 8 128.581k 35.0827k/s
ulightsaber/decaps_stddev 0.289 us 0.289 us 8 92.3866 357.559/s
ulightsaber/decaps_cv 1.02 % 1.02 % 8 0.07% 1.02%
ulightsaber/decaps_min 28.0 us 28.0 us 8 128.499k 34.6127k/s
ulightsaber/decaps_max 28.9 us 28.9 us 8 128.799k 35.6822k/s
firesaber/keygen_mean 61.1 us 61.1 us 8 280.316k 16.363k/s
firesaber/keygen_median 61.0 us 60.9 us 8 280.301k 16.407k/s
firesaber/keygen_stddev 0.722 us 0.722 us 8 246.267 190.759/s
firesaber/keygen_cv 1.18 % 1.18 % 8 0.09% 1.17%
firesaber/keygen_min 60.4 us 60.4 us 8 280.066k 15.9561k/s
firesaber/keygen_max 62.7 us 62.7 us 8 280.831k 16.5517k/s
usaber/encaps_mean 45.6 us 45.6 us 8 206.792k 21.9454k/s
usaber/encaps_median 45.5 us 45.5 us 8 206.737k 21.984k/s
usaber/encaps_stddev 0.779 us 0.778 us 8 307.03 374.398/s
usaber/encaps_cv 1.71 % 1.71 % 8 0.15% 1.71%
usaber/encaps_min 44.3 us 44.3 us 8 206.427k 21.3903k/s
usaber/encaps_max 46.8 us 46.8 us 8 207.455k 22.5701k/s
usaber/decaps_mean 54.8 us 54.8 us 8 249.357k 18.2674k/s
usaber/decaps_median 54.7 us 54.7 us 8 249.186k 18.274k/s
usaber/decaps_stddev 0.823 us 0.821 us 8 463.525 274.743/s
usaber/decaps_cv 1.50 % 1.50 % 8 0.19% 1.50%
usaber/decaps_min 53.5 us 53.5 us 8 248.922k 17.9813k/s
usaber/decaps_max 55.6 us 55.6 us 8 250.404k 18.6809k/s
ufiresaber/keygen_mean 59.7 us 59.7 us 8 273.819k 16.7587k/s
ufiresaber/keygen_median 59.9 us 59.9 us 8 273.828k 16.6901k/s
ufiresaber/keygen_stddev 0.865 us 0.858 us 8 196.044 242.142/s
ufiresaber/keygen_cv 1.45 % 1.44 % 8 0.07% 1.44%
ufiresaber/keygen_min 58.4 us 58.4 us 8 273.527k 16.4175k/s
ufiresaber/keygen_max 60.9 us 60.9 us 8 274.147k 17.1309k/s
saber/encaps_mean 46.0 us 46.0 us 8 208.958k 21.7341k/s
saber/encaps_median 46.0 us 46.0 us 8 208.882k 21.7243k/s
saber/encaps_stddev 0.679 us 0.679 us 8 370.735 322.816/s
saber/encaps_cv 1.48 % 1.47 % 8 0.18% 1.49%
saber/encaps_min 44.8 us 44.8 us 8 208.502k 21.276k/s
saber/encaps_max 47.0 us 47.0 us 8 209.704k 22.3444k/s
usaber/keygen_mean 33.7 us 33.7 us 8 151.209k 29.7017k/s
usaber/keygen_median 33.5 us 33.5 us 8 151.157k 29.825k/s
usaber/keygen_stddev 0.482 us 0.483 us 8 179.085 423.323/s
usaber/keygen_cv 1.43 % 1.43 % 8 0.12% 1.43%
usaber/keygen_min 33.1 us 33.1 us 8 151.049k 29.0304k/s
usaber/keygen_max 34.4 us 34.4 us 8 151.544k 30.1965k/s
lightsaber/keygen_mean 17.7 us 17.7 us 8 79.7241k 56.5706k/s
lightsaber/keygen_median 17.8 us 17.8 us 8 79.6325k 56.2462k/s
lightsaber/keygen_stddev 0.288 us 0.286 us 8 248.664 929.261/s
lightsaber/keygen_cv 1.63 % 1.62 % 8 0.31% 1.64%
lightsaber/keygen_min 17.1 us 17.1 us 8 79.4854k 55.6024k/s
lightsaber/keygen_max 18.0 us 18.0 us 8 80.2012k 58.3852k/s
ufiresaber/encaps_mean 73.5 us 73.5 us 8 330.533k 13.6167k/s
ufiresaber/encaps_median 73.5 us 73.5 us 8 330.58k 13.6155k/s
ufiresaber/encaps_stddev 1.38 us 1.38 us 8 321.261 258.24/s
ufiresaber/encaps_cv 1.88 % 1.89 % 8 0.10% 1.90%
ufiresaber/encaps_min 71.1 us 71.1 us 8 329.901k 13.2973k/s
ufiresaber/encaps_max 75.2 us 75.2 us 8 331.03k 14.0679k/s
ulightsaber/encaps_mean 23.7 us 23.7 us 8 106.835k 42.2998k/s
ulightsaber/encaps_median 23.8 us 23.7 us 8 106.787k 42.1096k/s
ulightsaber/encaps_stddev 0.528 us 0.528 us 8 205.977 953.679/s
ulightsaber/encaps_cv 2.23 % 2.23 % 8 0.19% 2.25%
ulightsaber/encaps_min 22.9 us 22.9 us 8 106.609k 41.1247k/s
ulightsaber/encaps_max 24.3 us 24.3 us 8 107.14k 43.7573k/s
lightsaber/encaps_mean 24.3 us 24.3 us 8 109.841k 41.2444k/s
lightsaber/encaps_median 24.3 us 24.3 us 8 109.778k 41.0825k/s
lightsaber/encaps_stddev 0.579 us 0.575 us 8 168.173 983.847/s
lightsaber/encaps_cv 2.39 % 2.37 % 8 0.15% 2.39%
lightsaber/encaps_min 23.5 us 23.5 us 8 109.663k 40.2215k/s
lightsaber/encaps_max 24.9 us 24.9 us 8 110.168k 42.6162k/s
```

### On 12th Gen Intel(R) Core(TM) i7-1260P ( compiled with GCC-13.1.0 )

```bash
2023-10-20T22:47:01+04:00
Running ./build/perf.out
Run on (16 X 4651.3 MHz CPU s)
CPU Caches:
L1 Data 48 KiB (x8)
L1 Instruction 32 KiB (x8)
L2 Unified 1280 KiB (x8)
L3 Unified 18432 KiB (x1)
Load Average: 0.37, 0.38, 0.44
------------------------------------------------------------------------------------------------
Benchmark Time CPU Iterations CYCLES items_per_second
------------------------------------------------------------------------------------------------
firesaber/keygen_mean 158 us 158 us 8 737.234k 6.34113k/s
firesaber/keygen_median 158 us 158 us 8 737.256k 6.34506k/s
firesaber/keygen_stddev 0.215 us 0.217 us 8 440.175 8.72/s
firesaber/keygen_cv 0.14 % 0.14 % 8 0.06% 0.14%
firesaber/keygen_min 158 us 158 us 8 736.606k 6.32183k/s
firesaber/keygen_max 158 us 158 us 8 738.03k 6.34719k/s
usaber/encaps_mean 121 us 121 us 8 563.495k 8.29283k/s
usaber/encaps_median 120 us 120 us 8 563.463k 8.29954k/s
usaber/encaps_stddev 0.246 us 0.247 us 8 189.434 16.9884/s
usaber/encaps_cv 0.20 % 0.21 % 8 0.03% 0.20%
usaber/encaps_min 120 us 120 us 8 563.285k 8.26525k/s
usaber/encaps_max 121 us 121 us 8 563.788k 8.30771k/s
ufiresaber/decaps_mean 235 us 235 us 8 1.09752M 4.25653k/s
ufiresaber/decaps_median 235 us 235 us 8 1.09747M 4.25813k/s
ufiresaber/decaps_stddev 0.354 us 0.356 us 8 382.907 6.43838/s
ufiresaber/decaps_cv 0.15 % 0.15 % 8 0.03% 0.15%
ufiresaber/decaps_min 235 us 235 us 8 1.09706M 4.24625k/s
ufiresaber/decaps_max 236 us 236 us 8 1.09824M 4.26329k/s
lightsaber/keygen_mean 42.0 us 42.0 us 8 196.399k 23.8367k/s
lightsaber/keygen_median 41.9 us 41.9 us 8 196.397k 23.8428k/s
lightsaber/keygen_stddev 0.062 us 0.063 us 8 171.763 35.6318/s
lightsaber/keygen_cv 0.15 % 0.15 % 8 0.09% 0.15%
lightsaber/keygen_min 41.9 us 41.9 us 8 196.14k 23.7586k/s
lightsaber/keygen_max 42.1 us 42.1 us 8 196.694k 23.8782k/s
saber/encaps_mean 118 us 118 us 8 552.242k 8.44651k/s
saber/encaps_median 118 us 118 us 8 553.194k 8.46011k/s
saber/encaps_stddev 0.515 us 0.512 us 8 2.95137k 36.2085/s
saber/encaps_cv 0.44 % 0.43 % 8 0.53% 0.43%
saber/encaps_min 118 us 118 us 8 544.953k 8.35746k/s
saber/encaps_max 120 us 120 us 8 553.701k 8.46366k/s
saber/keygen_mean 89.5 us 89.5 us 8 418.371k 11.1757k/s
saber/keygen_median 89.5 us 89.5 us 8 418.393k 11.1724k/s
saber/keygen_stddev 0.117 us 0.121 us 8 337.487 15.1486/s
saber/keygen_cv 0.13 % 0.14 % 8 0.08% 0.14%
saber/keygen_min 89.3 us 89.3 us 8 417.956k 11.1508k/s
saber/keygen_max 89.7 us 89.7 us 8 418.742k 11.1996k/s
ulightsaber/encaps_mean 61.4 us 61.4 us 8 287.266k 16.2776k/s
ulightsaber/encaps_median 61.3 us 61.3 us 8 286.919k 16.3108k/s
ulightsaber/encaps_stddev 0.372 us 0.373 us 8 1.06354k 97.637/s
ulightsaber/encaps_cv 0.61 % 0.61 % 8 0.37% 0.60%
ulightsaber/encaps_min 61.2 us 61.2 us 8 286.516k 16.0377k/s
ulightsaber/encaps_max 62.4 us 62.4 us 8 289.859k 16.3319k/s
firesaber/encaps_mean 196 us 196 us 8 914.876k 5.11k/s
firesaber/encaps_median 196 us 196 us 8 914.912k 5.11091k/s
firesaber/encaps_stddev 0.321 us 0.320 us 8 536.681 8.34906/s
firesaber/encaps_cv 0.16 % 0.16 % 8 0.06% 0.16%
firesaber/encaps_min 195 us 195 us 8 914.135k 5.09122k/s
firesaber/encaps_max 196 us 196 us 8 915.669k 5.11782k/s
ulightsaber/decaps_mean 79.3 us 79.3 us 8 370.856k 12.6077k/s
ulightsaber/decaps_median 79.3 us 79.3 us 8 370.846k 12.6147k/s
ulightsaber/decaps_stddev 0.119 us 0.120 us 8 171.552 19.0279/s
ulightsaber/decaps_cv 0.15 % 0.15 % 8 0.05% 0.15%
ulightsaber/decaps_min 79.2 us 79.2 us 8 370.676k 12.572k/s
ulightsaber/decaps_max 79.5 us 79.5 us 8 371.212k 12.6255k/s
ufiresaber/encaps_mean 199 us 199 us 8 929.823k 5.02799k/s
ufiresaber/encaps_median 199 us 199 us 8 929.522k 5.02952k/s
ufiresaber/encaps_stddev 0.246 us 0.244 us 8 905.644 6.17132/s
ufiresaber/encaps_cv 0.12 % 0.12 % 8 0.10% 0.12%
ufiresaber/encaps_min 199 us 199 us 8 929.199k 5.01484k/s
ufiresaber/encaps_max 199 us 199 us 8 931.993k 5.03363k/s
usaber/decaps_mean 147 us 147 us 8 687.526k 6.80119k/s
usaber/decaps_median 147 us 147 us 8 687.515k 6.79988k/s
usaber/decaps_stddev 0.115 us 0.086 us 8 182.306 4.00027/s
usaber/decaps_cv 0.08 % 0.06 % 8 0.03% 0.06%
usaber/decaps_min 147 us 147 us 8 687.278k 6.7959k/s
usaber/decaps_max 147 us 147 us 8 687.789k 6.80719k/s
ulightsaber/keygen_mean 41.6 us 41.6 us 8 194.699k 24.0248k/s
ulightsaber/keygen_median 41.6 us 41.6 us 8 194.721k 24.0364k/s
ulightsaber/keygen_stddev 0.088 us 0.082 us 8 213.95 47.3521/s
ulightsaber/keygen_cv 0.21 % 0.20 % 8 0.11% 0.20%
ulightsaber/keygen_min 41.5 us 41.5 us 8 194.378k 23.9326k/s
ulightsaber/keygen_max 41.8 us 41.8 us 8 195.058k 24.0686k/s
ufiresaber/keygen_mean 160 us 160 us 8 749.899k 6.23375k/s
ufiresaber/keygen_median 160 us 160 us 8 749.656k 6.23642k/s
ufiresaber/keygen_stddev 0.265 us 0.268 us 8 709.261 10.374/s
ufiresaber/keygen_cv 0.17 % 0.17 % 8 0.09% 0.17%
ufiresaber/keygen_min 160 us 160 us 8 749.418k 6.2094k/s
ufiresaber/keygen_max 161 us 161 us 8 751.596k 6.24275k/s
firesaber/decaps_mean 230 us 230 us 8 1.07534M 4.34691k/s
firesaber/decaps_median 230 us 230 us 8 1.07525M 4.34991k/s
firesaber/decaps_stddev 0.490 us 0.493 us 8 501.356 9.29772/s
firesaber/decaps_cv 0.21 % 0.21 % 8 0.05% 0.21%
firesaber/decaps_min 230 us 230 us 8 1.07488M 4.32803k/s
firesaber/decaps_max 231 us 231 us 8 1.07652M 4.35439k/s
saber/decaps_mean 143 us 143 us 8 671.358k 6.97545k/s
saber/decaps_median 143 us 143 us 8 671.327k 6.9754k/s
saber/decaps_stddev 0.076 us 0.073 us 8 183.137 3.55688/s
saber/decaps_cv 0.05 % 0.05 % 8 0.03% 0.05%
saber/decaps_min 143 us 143 us 8 671.11k 6.97164k/s
saber/decaps_max 143 us 143 us 8 671.69k 6.98306k/s
usaber/keygen_mean 91.3 us 91.3 us 8 426.7k 10.9555k/s
usaber/keygen_median 91.2 us 91.2 us 8 426.712k 10.9596k/s
usaber/keygen_stddev 0.131 us 0.128 us 8 180.262 15.3317/s
usaber/keygen_cv 0.14 % 0.14 % 8 0.04% 0.14%
usaber/keygen_min 91.2 us 91.2 us 8 426.499k 10.9194k/s
usaber/keygen_max 91.6 us 91.6 us 8 426.947k 10.9659k/s
lightsaber/decaps_mean 78.7 us 78.7 us 8 367.573k 12.7129k/s
lightsaber/decaps_median 78.7 us 78.7 us 8 367.525k 12.7134k/s
lightsaber/decaps_stddev 0.086 us 0.053 us 8 218.962 8.59515/s
lightsaber/decaps_cv 0.11 % 0.07 % 8 0.06% 0.07%
lightsaber/decaps_min 78.6 us 78.6 us 8 367.296k 12.7001k/s
lightsaber/decaps_max 78.8 us 78.7 us 8 368.016k 12.7257k/s
lightsaber/encaps_mean 61.5 us 61.5 us 8 287.72k 16.2575k/s
lightsaber/encaps_median 61.5 us 61.5 us 8 287.665k 16.2688k/s
lightsaber/encaps_stddev 0.125 us 0.131 us 8 264.066 34.695/s
lightsaber/encaps_cv 0.20 % 0.21 % 8 0.09% 0.21%
lightsaber/encaps_min 61.4 us 61.4 us 8 287.371k 16.1999k/s
lightsaber/encaps_max 61.7 us 61.7 us 8 288.147k 16.294k/s
```

## Usage

Saber is a header-only C++ library, implementing key encapsulation mechanism i.e.

- Key Generation
- Encapsulation
- Decapsulation

Getting started with using Saber in your project is fairly easy.

- Clone Saber repository under `$HOME`.

```bash
cd
git clone https://github.com/itzmeanjan/saber.git --recurse-submodules
```

- Include proper header file in your program and use functions, constants etc. living inside respective namespace.

Scheme of Interest | Header | Namespace
--- | :-: | --:
LightSaber KEM | include/lightsaber_kem.hpp | `lightsaber_kem::`
Saber KEM | include/saber_kem.hpp | `saber_kem::`
FireSaber KEM | include/firesaber_kem.hpp | `firesaber_kem::`
uLightSaber KEM | include/ulightsaber_kem.hpp | `ulightsaber_kem::`
uSaber KEM | include/usaber_kem.hpp | `usaber_kem::`
uFireSaber KEM | include/ufiresaber_kem.hpp | `ufiresaber_kem::`

```cpp
// main.cpp
#include "saber_kem.hpp"
#include "prng.hpp"
#include

int main() {
std::vector seedA(saber_kem::seedBytes);
std::vector seedS(saber_kem::noiseBytes);
std::vector z(saber_kem::keyBytes);
std::vector m(saber_kem::keyBytes);
std::vector pkey(saber_kem::PK_LEN);
std::vector skey(saber_kem::SK_LEN);
std::vector ctxt(saber_kem::CT_LEN);
std::vector sskey_peer0(sha3_256::DIGEST_LEN);
std::vector sskey_peer1(sha3_256::DIGEST_LEN);

// Create non-owning interfaces over heap allocated vectors
// More @ https://en.cppreference.com/w/cpp/container/span
auto _seedA = std::span(seedA);
auto _seedS = std::span(seedS);
auto _z = std::span(z);
auto _m = std::span(m);
auto _pkey = std::span(pkey);
auto _skey = std::span(skey);
auto _ctxt = std::span(ctxt);
auto _sskey_peer0 = std::span(sskey_peer0);
auto _sskey_peer1 = std::span(sskey_peer1);

// Random sample seeds using PRNG backed by SHAKE128 Xof
//
// !!! I strongly advice you to go through comments in include/prng.hpp
// header file before you start using it in production for sampling randomness. !!!
prng::prng_t prng;

prng.read(_seedA);
prng.read(_seedS);
prng.read(_z);
prng.read(_m);

// Peer-1 generates a Saber KEM keypair.
saber_kem::keygen(_seedA, _seedS, _z, _pkey, _skey);
// Peer-0 uses Peer-1's public key for encapsulating a key, also producing session key.
saber_kem::encaps(_m, _pkey, _ctxt, _sskey_peer0);
// Peer-1 uses its private key to decapsulate cipher text, producing same session key.
saber_kem::decaps(_ctxt, _skey, _sskey_peer1);

// Both peers must arrive at same session key.
assert(std::ranges::equal(_sskey_peer0, _sskey_peer1));
return 0;
}
```

- When it's time to compile your program, let your compiler know where it can find Saber KEM headers ( `./include` directory ) along with Sha3 and Subtle headers, respectively living in `./sha3/include` and `./subtle/include`.

```bash
SABER_HEADERS=~/saber/include
SHA3_HEADERS=~/saber/sha3/include
SUBTLE_HEADERS=~/saber/subtle/include

g++ -std=c++20 -Wall -O3 -march=native -I $SABER_HEADERS -I $SHA3_HEADERS -I $SUBTLE_HEADERS main.cpp
```

I maintain an example [program](./examples/saber.cpp), demonstrating usage of Saber KEM API. Just like that one can use LightSaber or FireSaber or any of the uniform sampling based KEM variant's API, while just updating header file and namespace.

```bash
$ g++ -std=c++20 -Wall -Wextra -pedantic -O3 -march=native -I include -I sha3/include -I subtle/include examples/saber.cpp && ./a.out
Saber KEM :

Public Key : 3bdf4809d5dd79700910e80ebcc98f1d68f20ef0efaadf594bb5c15ccce18418116bc77ae1bbafef275f9f224c4c2481ca6d8d7053a8933c5fd8ffebfc1415a94faee5d5b15010f81c1df7accb45df45cb7b8351988c9f381ee5073998097488763c61684d909ae255fe920cd2ee1a15267c6f758a0429af964edd24ee2d0154369f5cd7526bbae9649b3c1c6e64fe229ddaadb26ec6b6808ef072dc6a281c9a7ae64e6590f194198bd9b60f3404c7d9340fc910fc1ee4a93a1a21f09ebb3d099d8c0850330809a12a4cea5a89c6d93e3cf73beab33e27c1ff1908508a92c7e055593a737d416752eba99f066f3c7bc1d436ec94438f1db8f180e0b595effcbd2df50639f5a7f9fde1d0cd923e1dc524f696d3682c3ce540175b275882f27fc30ca306080899517115183cd423ba93a9c8734e5e3e38366163d91a120fc0499902b0917b3131cdd83e8b14415c93f11879583c337b54b515d494bb1dc1236856ed7a0a99611acedcfd8e528d0310d3fac98eba8cfa0d679f9d38df31ffc11b3349c4d89a8696f8b560ad92b38bb201dda0be8b15d5b8aa303c727654ecf3d9d0c7b547bccfef963c00dbf0af825e3e1430d8853befbfbae8aadbdea192ac92cac98e02241a5edc4c3df9a8df5fd13e2e5fc4d9312d6b1509629f9a3c0c5674f886c547a5cc8061e1e175460791bc1b4aa5b98164fcfa40a12d14b774b7e9f815d043c47cc839cfe973a1d118c933d7ec008a4c5811114c4eca24706b8228c794b0a53519368b670b0076ad4c6430225664376d149f8101b3ceb07cb93fbf70cdd97ec55592bfc4ae8d7e153456a7ba1ebfcf1bb75b1a5ee0e448d12816ade6c512f93546e7ccd29fc677ea4599e1fe5a3ef7fb2dc7ace1fb4780a9b28ba18536775413e7eeaf947ed3c8c5373a6204f788164ea08b21e2502b84dd5240c38c48781fa1f1ddf965bed87ace3e20da27e1a9d827c72b59b6238efe392df88dcf0e635c83b26073830583d35acafd63ef52667d2cab4452104418d3ff3d5aaab55b7e6a1c1e5d885c45a2b79fcc81a1268b45c2207d642cb3a5bab85e80e1e0a5c8b68f8a448ec51926c0e4433053b14f17a3e0b55e3127fbc4a98209da6bd6b9e29cbf17491ce20ac3e20a82b7ae417fb95b0005ae5417a04341c481e81a2b9fb9ef930faef3b22995c23da685341c46d1c216e9ae36da20f14dc0e503bb44e9e8745c2972e57786519a77e472dde716c4245fc44ca388b6320eeb4fe154ecdfd7fd2c94a7a280bb65f96aae4a2c76653bc8e5bf84a012aecb1f80d3d63866c5475eb3ef333413964f64cfe2567d8504be374021dc1dca686a1d8b6cf1532d7b1eb7c701d4d46bf48fd12dea72c4a92eee3dc335e294248fcd1cae1df3c9e33c29
Secret Key : bbdb28be86156fe2bd1126ddc742bdc47865927fe477b50d0d902c360c1a2470055bdf2ef37e5ad8fffd65de17d90d6a0d35df792e912f47b1dea9c299503b0e3bdf4809d5dd79700910e80ebcc98f1d68f20ef0efaadf594bb5c15ccce18418116bc77ae1bbafef275f9f224c4c2481ca6d8d7053a8933c5fd8ffebfc1415a94faee5d5b15010f81c1df7accb45df45cb7b8351988c9f381ee5073998097488763c61684d909ae255fe920cd2ee1a15267c6f758a0429af964edd24ee2d0154369f5cd7526bbae9649b3c1c6e64fe229ddaadb26ec6b6808ef072dc6a281c9a7ae64e6590f194198bd9b60f3404c7d9340fc910fc1ee4a93a1a21f09ebb3d099d8c0850330809a12a4cea5a89c6d93e3cf73beab33e27c1ff1908508a92c7e055593a737d416752eba99f066f3c7bc1d436ec94438f1db8f180e0b595effcbd2df50639f5a7f9fde1d0cd923e1dc524f696d3682c3ce540175b275882f27fc30ca306080899517115183cd423ba93a9c8734e5e3e38366163d91a120fc0499902b0917b3131cdd83e8b14415c93f11879583c337b54b515d494bb1dc1236856ed7a0a99611acedcfd8e528d0310d3fac98eba8cfa0d679f9d38df31ffc11b3349c4d89a8696f8b560ad92b38bb201dda0be8b15d5b8aa303c727654ecf3d9d0c7b547bccfef963c00dbf0af825e3e1430d8853befbfbae8aadbdea192ac92cac98e02241a5edc4c3df9a8df5fd13e2e5fc4d9312d6b1509629f9a3c0c5674f886c547a5cc8061e1e175460791bc1b4aa5b98164fcfa40a12d14b774b7e9f815d043c47cc839cfe973a1d118c933d7ec008a4c5811114c4eca24706b8228c794b0a53519368b670b0076ad4c6430225664376d149f8101b3ceb07cb93fbf70cdd97ec55592bfc4ae8d7e153456a7ba1ebfcf1bb75b1a5ee0e448d12816ade6c512f93546e7ccd29fc677ea4599e1fe5a3ef7fb2dc7ace1fb4780a9b28ba18536775413e7eeaf947ed3c8c5373a6204f788164ea08b21e2502b84dd5240c38c48781fa1f1ddf965bed87ace3e20da27e1a9d827c72b59b6238efe392df88dcf0e635c83b26073830583d35acafd63ef52667d2cab4452104418d3ff3d5aaab55b7e6a1c1e5d885c45a2b79fcc81a1268b45c2207d642cb3a5bab85e80e1e0a5c8b68f8a448ec51926c0e4433053b14f17a3e0b55e3127fbc4a98209da6bd6b9e29cbf17491ce20ac3e20a82b7ae417fb95b0005ae5417a04341c481e81a2b9fb9ef930faef3b22995c23da685341c46d1c216e9ae36da20f14dc0e503bb44e9e8745c2972e57786519a77e472dde716c4245fc44ca388b6320eeb4fe154ecdfd7fd2c94a7a280bb65f96aae4a2c76653bc8e5bf84a012aecb1f80d3d63866c5475eb3ef333413964f64cfe2567d8504be374021dc1dca686a1d8b6cf1532d7b1eb7c701d4d46bf48fd12dea72c4a92eee3dc335e294248fcd1cae1df3c9e33c2902c0ffff7f00f0ff038000f8fffe3f000080ff1f00fe3f00f8ffff3f000000ff0f0000c0ff1f00002000000000f0ff0180ff0f00012000fcff00e0fffdff00100001a0fffb7fffffff0380fff7ff000000040001f0ff030000000000c0ff078000000000000010000340000080ffdfff01000000000320000480ff4f00fc7f00000001e0ff0f0001f0ff05c0fff7ff000000fcff00000002c0ff0700fe1f000480fe0f00084000000000400000800000000040000800fdffff0300000000024000f8ffffffff0380ff1f0002c0ff0f00002000040001f0fffdbffff7fffe1f00f4ffffeffffdbfff070001e0ff07800010000240000800ffffff0700000000febf000000000000f87f001000064000f8ff00c0ff0780ffefff01c0fff7ff0200000480ff1f00fe7f000000012000fcff0110000000000000fc1f00040000e0ff038000f0ff0300000400001000fc7f000800fe1f00008000f0ff0380ff170000e0ff03000120000080ff0700ff1f00000001e0ff0180ff1700012000fc7f010000fc3f00e8ffff3f00f87f0000000200001800004000000001f0ff014000f0ff0220000480ffffffff3f00f8ff0100000c00001000024000080003e0ff038000f0ff0340000000fedffffb7f00e0ff050000e8ff00e0ffff7f01f0fffdffff170001e0ffffff00e0fff9ffff17000100000000002000febfff1f00fe5f00f87f00f0ffff3f0008000100000400001000feffff0700010000000001e0ffffffff0f00010000000000f0ff07c0fff7ff0100000880002000feffff0f00ff1f000480ffffffff3f000000ff3f000480ffffff03c0ffffff00e0ff0b000000000440000800fe3f0000000020000440000000fd3f00f8ffffefff054000f8ff002000fcff001000008000f0ffff1f00fc7f00000000c0ff0f00ff5f000000ff1f00040000080000c0ff0300ffefff0140001000fe1f000c0000f0ff01c000e8ff02000000800100000280ff1700fe3f00008000f0ffffbf001000020000000001f0fffdffff070000e0ff0b80002000febf00f8ff0200000880ff0f00004000f8ff0120000400ffffff014000f8fffedfff0f8000f0ff01c0ffefffff1f00040001000002c0fffffffe3f00fcffff0f00fe7f00f8ff020000f8ff001000fe3f00100001c0ff078000f0ff0300000000ffdffffbff000000fe3f00000001c0fffb7f00d0fffb7f0008000020000080ff0f00024000080001e0ff0b0000f0ffffbfff0700feffff078000e0ffff3f00000002c0fffb7f002000febf00000000000004000020000280ff0f0000e0fffb7f002000048000100000c0ff070001e0ff01c0ffffff0300000480ff0f00040000f8ff0140000480000000004000f0ff010000f87fffffffff7fff0700012000fcffffefffffffff0f00000000fc7f000000060000000001e0fff7ff002000fafffffffffd1f000080011000feffff0700ff1f000080ff3f00020000f0ffffdfff078000000004c000f8ff024000088000f0ff050000000001e0ff070000100006c0ff0700024000f87f001000fe3f011000002000048000100000400000000000000080ff0f0004c0ff070001c0ff0780ff1f00fc7f000800004000fcffff0f000400001000fd5f000080ff0f0000c0ff0f00fe1f00f4fffe1f00faffffffff012000008001f0fffd7f00f8fffe5f000000002000fe7f00000001e0ff0700ff1f000280ff170000a0ff0780ffffff078000f8ff
Cipher Text : f0af922faecdcbcd728c0e1016e008757c761d395fe357f1f7fa91b0dded3e45c0def52a19d5690da3a5712f0d16bc26d9ac7687ebda4936ede50d1ea58c9fb1bc9ef083cbd589527a4d27313af5f936d7c451097df750d0f8117e6ed70d5bea97cd9bec5b59b58cf8cf265237e6e353efe36efc2bb7780d762f17b91819194036a2aeb48871738be906a13711eda41c02d57266f574a169395a25537083f921154644b8b896e5fa1b56f00ac8e980b038fedcffa5f2ccc04a249a9b4db02dab9764d483220ad5f1f64692c5fa3980c9079ff6b65a4cd2339119796aafc51ae55486e2ab473c518cb95d8b94c52b501e4faf5eb4c1328d13584ac337ba02a76bd39643762ac880fecb210609fc399c8836da1c3baeeef257e334d9755bce1b784757820e3b09c8d1273a6dbdc6b1e7d561b33ccafea6d79cd5743d1f85f506c834a04596c8819a8caba4d4d0686a381ddf64d19749fdf32ee805d1505f5eea8d45d211cea4f9ed4b212d7ae8c81235d14ed872635f04b416417255c5b45eca6c9c027ce7892d5d446feea136c2b99b9b6ff1a9585d2d81fe0f351f06bbdf0b1a043167bf262875085437d0db0578d4731dd2ec767eeb0aeeda535f0cb1ba8ea4319a05d06035692ce35ae763229731dac0d725cf357bdf96ad1e8d77744e8900d08b67609dee50229a34ef1b355a8b14c9bb742784972f18ff5416f83a53d7a7d3e8a21abf091218c5bfb755f2d21d775bd690a21053a6838eb935eae23e99bbd6ca802169ed0386bf8241782e69f452a0055230c7c5f4537df0132b43458a80a422a12c407ac8ceb9e608e40b48d23c714a4c01a6e80ed77a48bfcbd7282e1822688eb699f9b1b1fde3f98c4d02e634e2c15402643abb6a91efcedd0d5fad19f7e20b2e7da007c4cbdf23f73b54f16c97aac7a7f7bac5930a498b0134764c203b5bd7638ba78898ebdc0d4964efa3a91afe6ad45e6ea861a88354060ab6b54898acc48d19b2288da0ae1753deffb17c19c6af98061dfebff9eb8eeed95da7df14d5f6dd9e368550e2d2f9b3e2cbd8ba59b68161b49c0b4c508756e6fc60285baa64965201f6e7d53d257a884d5d195edbd8385519032c98b4c1f7d388ad23ff2f2be63f8d11b38fdf4a8d454683952f6dc1ca51c5324561edfab65f5382090bb75b4fb8d3bd6b088d1ac4cd0ec30e4b76779704bb8c32a7749096e77a117cf336e6ee1f743e4bd0cfa12bb67be1c39bb27ee3527b9fa2ab1c4e35087104d68d8821ecca8bdb6a142b6d9e617c135fd309cdab06bf88ded02b0d4ffc4c5c3f917d90f5cc45b3fe45c12ac33d9cd391efc1a348449e6bb394d98b74488cd79a602c786a0e0aa04b1d952c85624f2e9bf68e9a09079fcddd37482ad3727d5897f1391606b267b1e860e881bcacecf1767fed251eadeb9d96b56be5f88bfd37fc4f3e16ccf33af59476610e304578d21e25e1c310552899e1dc2411c87fce4d6b1fa4bebc89c986d5297de07884e523788117f1c930615887a36a19e36eb6572aa9
Session Key : eb8b0fce5ee3f0d15755f7b72726d61a1f11cad9bddeb15b049884bda7eb8b92
```