Signed-off-by: Anjan Roy <hello@itzmeanjan.in>
Caution
This Kyber implementation is conformant with Kyber specification https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf and I also try to make it constant-time but be informed that it is not yet audited. If you consider using it in production, be careful !
kyber
CRYSTALS-Kyber: Post-Quantum Public-key Encryption & Key-establishment Algorithm
Motivation
Kyber is being standardized by NIST as post-quantum secure key encapsulation mechanism (KEM), which can be used for key establishment.
Kyber offers an IND-CCA2-secure Key Encapsulation Mechanism - its security is based on the hardness of solving the learning-with-errors (LWE) problem in module (i.e. structured) lattices.
Kyber Key Encapsulation Mechanism is built on top of IND-CPA-secure Kyber Public Key Encryption, where two communicating parties, both generating their key pairs, while publishing their public keys to each other, can encrypt fixed length ( = 32 -bytes ) message using peer's public key. Cipher text can be decrypted by corresponding secret key ( which is private to the keypair owner ) and 32 -bytes message can be recovered back. Then a slightly tweaked Fujisaki–Okamoto (FO) transform is applied on IND-CPA-secure Kyber PKE - giving us the IND-CCA2-secure KEM construction. In KEM scheme, two parties interested in establishing a secure communication channel over public & insecure channel, can generate a shared secret key ( of arbitrary byte length ) from a key derivation function ( i.e. KDF which is SHAKE256 Xof in this context ) which is obtained by both of these parties as result of seeding SHAKE256 Xof with same secret. This secret is 32 -bytes and that's what is communicated by sender to receiver using underlying Kyber PKE scheme.
| Algorithm | Input | Output |
|---|---|---|
| KEM KeyGen | - | Public Key and Secret Key |
| Encapsulation | Public Key | Cipher Text and SHAKE256 KDF |
| Decapsulation | Secret Key and Cipher Text | SHAKE256 KDF |
Here I'm maintaining kyber - a header-only and easy-to-use ( see more in usage ) C++ library implementing Kyber KEM, supporting Kyber-{512, 768, 1024} parameter sets, as defined in table 1 of Kyber specification. sha3 and subtle are two dependencies of this library, which are pinned to specific git commits, using git submodule.
Note
Find Kyber specification https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf - this is the document that I followed when implementing Kyber. I suggest you go through the specification to get an in-depth understanding of Kyber PQC suite.
Note
Find progress of NIST PQC standardization effort @ https://csrc.nist.gov/projects/post-quantum-cryptography.
Prerequisites
- A C++ compiler with C++20 standard library such as
clang++/g++.
$ clang++ --version
Ubuntu clang version 17.0.2 (1~exp1ubuntu2.1)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ g++ --version
g++ (Ubuntu 13.2.0-4ubuntu3) 13.2.0
- Build tools such as
make,cmake.
$ make --version
GNU Make 4.3
$ cmake --version
cmake version 3.25.1
- For testing Kyber KEM implementation, you need to globally install
google-testlibrary and headers. Follow this guide, if you don't have it installed. - For benchmarking Kyber KEM implementation, targeting CPU systems, you'll need to have
google-benchmarkheader and library globally installed. I found guide @ https://github.com/google/benchmark#installation helpful.
Note
If you are on a machine running GNU/Linux kernel and you want to obtain CPU cycle count for KEM routines, you should consider building
google-benchmarklibrary withlibPFMsupport, following https://gist.github.com/itzmeanjan/05dc3e946f635d00c5e0b21aae6203a7, a step-by-step guide. Find more about libPFM @ https://perfmon2.sourceforge.net.
Tip
Git submodule based dependencies will mostly be imported automatically, but in case that doesn't work, you can manually initialize and update them by issuing
$ git submodule update --initfrom inside the root of this repository.
Testing
For testing functional correctness and conformance with Kyber specification, you have to issue
Note
Known Answer Test (KAT) files living in this directory are generated by following (reproducible) steps, described in https://gist.github.com/itzmeanjan/c8f5bc9640d0f0bdd2437dfe364d7710.
make -j # Run tests without any sort of sanitizers
make asan_test -j # Run tests with AddressSanitizer enabled
make ubsan_test -j # Run tests with UndefinedBehaviourSanitizer enabled
Note: Randomizing tests' orders with a seed of 61247 .
[==========] Running 10 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 10 tests from KyberKEM
[ RUN ] KyberKEM.ArithmeticOverZq
[ OK ] KyberKEM.ArithmeticOverZq (116 ms)
[ RUN ] KyberKEM.NumberTheoreticTransform
[ OK ] KyberKEM.NumberTheoreticTransform (0 ms)
[ RUN ] KyberKEM.Kyber768KnownAnswerTests
[ OK ] KyberKEM.Kyber768KnownAnswerTests (8 ms)
[ RUN ] KyberKEM.Kyber512KnownAnswerTests
[ OK ] KyberKEM.Kyber512KnownAnswerTests (5 ms)
[ RUN ] KyberKEM.CompressDecompressZq
[ OK ] KyberKEM.CompressDecompressZq (94 ms)
[ RUN ] KyberKEM.Kyber1024KnownAnswerTests
[ OK ] KyberKEM.Kyber1024KnownAnswerTests (13 ms)
[ RUN ] KyberKEM.Kyber768KeygenEncapsDecaps
[ OK ] KyberKEM.Kyber768KeygenEncapsDecaps (0 ms)
[ RUN ] KyberKEM.Kyber512KeygenEncapsDecaps
[ OK ] KyberKEM.Kyber512KeygenEncapsDecaps (0 ms)
[ RUN ] KyberKEM.PolynomialSerialization
[ OK ] KyberKEM.PolynomialSerialization (0 ms)
[ RUN ] KyberKEM.Kyber1024KeygenEncapsDecaps
[ OK ] KyberKEM.Kyber1024KeygenEncapsDecaps (0 ms)
[----------] 10 tests from KyberKEM (238 ms total)
[----------] Global test environment tear-down
[==========] 10 tests from 1 test suite ran. (238 ms total)
[ PASSED ] 10 tests.
Benchmarking
For benchmarking Kyber KEM routines ( i.e. keygen, encaps and decaps ) for various suggested parameter sets, you have to issue.
make benchmark # If you haven't built google-benchmark library with libPFM support.
make perf # If you have built google-benchmark library with libPFM support.
Note
Benchmarking expects presence of
google-benchmarkheader and library in global namespace ( so that it can be found by the compiler ).
Caution
When benchmarking, ensure that you've disabled CPU frequency scaling, by following guide @ https://github.com/google/benchmark/blob/main/docs/reducing_variance.md.
Note
make perf- was issued when collecting following benchmarks. Notice, cycles column, denoting cost of executing Kyber KEM routines in terms of CPU cycles. Follow this for more details.
On 12th Gen Intel(R) Core(TM) i7-1260P ( compiled with Clang-17.0.2 )
2023-12-17T16:35:19+04:00
Running ./build/perf.out
Run on (16 X 648.989 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.63, 0.49, 0.35
----------------------------------------------------------------------------------------------
Benchmark Time CPU Iterations CYCLES items_per_second
----------------------------------------------------------------------------------------------
kyber512/decap_mean 16.8 us 16.8 us 10 78.2371k 59.3682k/s
kyber512/decap_median 16.8 us 16.8 us 10 78.0903k 59.5332k/s
kyber512/decap_stddev 0.213 us 0.213 us 10 1.61104k 748.863/s
kyber512/decap_cv 1.26 % 1.26 % 10 2.06% 1.26%
kyber512/decap_min 16.5 us 16.5 us 10 75.9006k 58.3612k/s
kyber512/decap_max 17.1 us 17.1 us 10 80.2234k 60.4726k/s
kyber512/keygen_mean 12.0 us 12.0 us 10 55.2343k 83.4374k/s
kyber512/keygen_median 12.0 us 12.0 us 10 55.2033k 83.3267k/s
kyber512/keygen_stddev 0.143 us 0.143 us 10 910.895 988.689/s
kyber512/keygen_cv 1.19 % 1.20 % 10 1.65% 1.18%
kyber512/keygen_min 11.8 us 11.8 us 10 54.1517k 81.2428k/s
kyber512/keygen_max 12.3 us 12.3 us 10 57.0565k 84.7691k/s
kyber768/keygen_mean 19.9 us 19.9 us 10 91.4059k 50.2463k/s
kyber768/keygen_median 19.9 us 19.9 us 10 91.0785k 50.1954k/s
kyber768/keygen_stddev 0.180 us 0.181 us 10 1.05886k 457.283/s
kyber768/keygen_cv 0.91 % 0.91 % 10 1.16% 0.91%
kyber768/keygen_min 19.6 us 19.6 us 10 90.2107k 49.5364k/s
kyber768/keygen_max 20.2 us 20.2 us 10 93.7315k 50.9569k/s
kyber768/encap_mean 26.3 us 26.3 us 10 119.902k 38.0206k/s
kyber768/encap_median 26.3 us 26.3 us 10 119.44k 37.9685k/s
kyber768/encap_stddev 0.225 us 0.225 us 10 2.0148k 326.026/s
kyber768/encap_cv 0.85 % 0.85 % 10 1.68% 0.86%
kyber768/encap_min 25.9 us 25.9 us 10 117.959k 37.5131k/s
kyber768/encap_max 26.7 us 26.7 us 10 124.856k 38.6767k/s
kyber1024/encap_mean 40.1 us 40.1 us 10 183.584k 24.9219k/s
kyber1024/encap_median 40.0 us 40.0 us 10 182.834k 25.005k/s
kyber1024/encap_stddev 0.462 us 0.462 us 10 2.02064k 285.263/s
kyber1024/encap_cv 1.15 % 1.15 % 10 1.10% 1.14%
kyber1024/encap_min 39.4 us 39.4 us 10 180.861k 24.4381k/s
kyber1024/encap_max 40.9 us 40.9 us 10 187.784k 25.367k/s
kyber1024/keygen_mean 31.3 us 31.3 us 10 142.994k 32.0037k/s
kyber1024/keygen_median 31.2 us 31.2 us 10 141.812k 32.0502k/s
kyber1024/keygen_stddev 0.468 us 0.467 us 10 3.09301k 476.014/s
kyber1024/keygen_cv 1.50 % 1.50 % 10 2.16% 1.49%
kyber1024/keygen_min 30.5 us 30.5 us 10 139.185k 31.0694k/s
kyber1024/keygen_max 32.2 us 32.2 us 10 148.231k 32.7634k/s
kyber1024/decap_mean 42.5 us 42.5 us 10 195.395k 23.5308k/s
kyber1024/decap_median 42.5 us 42.5 us 10 194.307k 23.5284k/s
kyber1024/decap_stddev 0.341 us 0.342 us 10 2.27441k 188.876/s
kyber1024/decap_cv 0.80 % 0.80 % 10 1.16% 0.80%
kyber1024/decap_min 42.0 us 42.0 us 10 192.669k 23.198k/s
kyber1024/decap_max 43.1 us 43.1 us 10 198.878k 23.8111k/s
kyber512/encap_mean 15.4 us 15.4 us 10 70.3054k 65.0965k/s
kyber512/encap_median 15.4 us 15.4 us 10 69.6619k 65.1279k/s
kyber512/encap_stddev 0.225 us 0.226 us 10 1.99248k 957.196/s
kyber512/encap_cv 1.47 % 1.47 % 10 2.83% 1.47%
kyber512/encap_min 15.0 us 15.0 us 10 68.2471k 63.7025k/s
kyber512/encap_max 15.7 us 15.7 us 10 73.4948k 66.8462k/s
kyber768/decap_mean 28.1 us 28.1 us 10 129.269k 35.6001k/s
kyber768/decap_median 28.1 us 28.1 us 10 128.604k 35.5936k/s
kyber768/decap_stddev 0.159 us 0.159 us 10 1.61556k 200.417/s
kyber768/decap_cv 0.57 % 0.56 % 10 1.25% 0.56%
kyber768/decap_min 27.8 us 27.8 us 10 127.678k 35.1656k/s
kyber768/decap_max 28.4 us 28.4 us 10 131.651k 35.9414k/s
On ARM Cortex-A72 i.e. Raspberry Pi 4B ( compiled with Clang-17.0.2 )
2023-12-17T18:03:53+05:30
Running ./build/perf.out
Run on (4 X 1800 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x4)
L1 Instruction 48 KiB (x4)
L2 Unified 1024 KiB (x1)
Load Average: 0.48, 1.44, 1.61
Performance counters not supported.
-----------------------------------------------------------------------------------
Benchmark Time CPU Iterations items_per_second
-----------------------------------------------------------------------------------
kyber768/encap_mean 194 us 194 us 10 5.16056k/s
kyber768/encap_median 193 us 193 us 10 5.17224k/s
kyber768/encap_stddev 1.31 us 1.29 us 10 34.0107/s
kyber768/encap_cv 0.67 % 0.66 % 10 0.66%
kyber768/encap_min 193 us 193 us 10 5.09692k/s
kyber768/encap_max 196 us 196 us 10 5.19123k/s
kyber1024/keygen_mean 254 us 254 us 10 3.93486k/s
kyber1024/keygen_median 254 us 254 us 10 3.93138k/s
kyber1024/keygen_stddev 0.713 us 0.712 us 10 11.0375/s
kyber1024/keygen_cv 0.28 % 0.28 % 10 0.28%
kyber1024/keygen_min 253 us 253 us 10 3.92136k/s
kyber1024/keygen_max 255 us 255 us 10 3.95326k/s
kyber1024/encap_mean 296 us 296 us 10 3.38308k/s
kyber1024/encap_median 296 us 296 us 10 3.38211k/s
kyber1024/encap_stddev 0.574 us 0.586 us 10 6.71083/s
kyber1024/encap_cv 0.19 % 0.20 % 10 0.20%
kyber1024/encap_min 295 us 295 us 10 3.37455k/s
kyber1024/encap_max 296 us 296 us 10 3.39256k/s
kyber768/decap_mean 212 us 212 us 10 4.71816k/s
kyber768/decap_median 212 us 212 us 10 4.71786k/s
kyber768/decap_stddev 0.741 us 0.744 us 10 16.577/s
kyber768/decap_cv 0.35 % 0.35 % 10 0.35%
kyber768/decap_min 211 us 211 us 10 4.69116k/s
kyber768/decap_max 213 us 213 us 10 4.74494k/s
kyber768/keygen_mean 158 us 158 us 10 6.31632k/s
kyber768/keygen_median 158 us 158 us 10 6.31299k/s
kyber768/keygen_stddev 0.453 us 0.445 us 10 17.7648/s
kyber768/keygen_cv 0.29 % 0.28 % 10 0.28%
kyber768/keygen_min 158 us 158 us 10 6.29411k/s
kyber768/keygen_max 159 us 159 us 10 6.34639k/s
kyber1024/decap_mean 321 us 321 us 10 3.11987k/s
kyber1024/decap_median 321 us 321 us 10 3.11851k/s
kyber1024/decap_stddev 0.564 us 0.569 us 10 5.53764/s
kyber1024/decap_cv 0.18 % 0.18 % 10 0.18%
kyber1024/decap_min 320 us 320 us 10 3.1111k/s
kyber1024/decap_max 321 us 321 us 10 3.12971k/s
kyber512/decap_mean 129 us 129 us 10 7.74209k/s
kyber512/decap_median 129 us 129 us 10 7.75584k/s
kyber512/decap_stddev 0.869 us 0.858 us 10 50.8408/s
kyber512/decap_cv 0.67 % 0.66 % 10 0.66%
kyber512/decap_min 128 us 128 us 10 7.60927k/s
kyber512/decap_max 131 us 131 us 10 7.79796k/s
kyber512/encap_mean 116 us 116 us 10 8.63463k/s
kyber512/encap_median 116 us 116 us 10 8.63491k/s
kyber512/encap_stddev 0.318 us 0.316 us 10 23.5414/s
kyber512/encap_cv 0.27 % 0.27 % 10 0.27%
kyber512/encap_min 115 us 115 us 10 8.6006k/s
kyber512/encap_max 116 us 116 us 10 8.66881k/s
kyber512/keygen_mean 92.7 us 92.7 us 10 10.7837k/s
kyber512/keygen_median 92.6 us 92.6 us 10 10.7982k/s
kyber512/keygen_stddev 0.750 us 0.753 us 10 86.1452/s
kyber512/keygen_cv 0.81 % 0.81 % 10 0.80%
kyber512/keygen_min 92.1 us 92.0 us 10 10.5513k/s
kyber512/keygen_max 94.8 us 94.8 us 10 10.8653k/s
Usage
kyber is written as a header-only C++ library, majorly targeting 64 -bit platforms and it's pretty easy to get started with. All you need to do is following.
- Clone
kyberrepository.
cd
# Multi-step cloning and importing of submodules
git clone https://github.com/itzmeanjan/kyber.git && pushd kyber && git submodule update --init && popd
# Or do single step cloning and importing of submodules
git clone https://github.com/itzmeanjan/kyber.git --recurse-submodules
- Write your program while including proper header files ( based on which variant of Kyber KEM you want to use, see include directory ), which includes declarations ( and definitions ) of all required KEM routines and constants ( such as byte length of public/ private keys and cipher text ).
// main.cpp
#include "kyber512_kem.hpp"
#include <algorithm>
#include <array>
#include <cassert>
int
main()
{
std::array<uint8_t, 32> d{}; // seed
std::array<uint8_t, 32> z{}; // seed
std::array<uint8_t, kyber512_kem::PKEY_LEN> pkey{};
std::array<uint8_t, kyber512_kem::SKEY_LEN> skey{};
std::array<uint8_t, 32> m{}; // seed
std::array<uint8_t, kyber512_kem::CIPHER_LEN> cipher{};
// Be careful !
//
// Read API documentation in include/prng.hpp
prng::prng_t prng;
prng.read(d);
prng.read(z);
prng.read(m);
kyber512_kem::keygen(d, z, pkey, skey);
auto skdf = kyber512_kem::encapsulate(m, pkey, cipher);
auto rkdf = kyber512_kem::decapsulate(skey, cipher);
std::array<uint8_t, 32> sender_key{};
skdf.squeeze(sender_key);
std::array<uint8_t, 32> receiver_key{};
rkdf.squeeze(receiver_key);
assert(std::ranges::equal(sender_key, receiver_key));
return 0;
}
- When compiling your program, let your compiler know where it can find
kyber,sha3andsubtleheaders, which includes their definitions ( kyber being a header-only library ) too.
# Assuming `kyber` was cloned just under $HOME
KYBER_HEADERS=~/kyber/include
SHA3_HEADERS=~/kyber/sha3/include
SUBTLE_HEADERS=~/kyber/subtle/include
g++ -std=c++20 -Wall -O3 -march=native -I $KYBER_HEADERS -I $SHA3_HEADERS -I $SUBTLE_HEADERS main.cpp
| Kyber KEM Variant | Namespace | Header |
|---|---|---|
| Kyber512 KEM Routines | kyber512_kem:: |
include/kyber512_kem.hpp |
| Kyber768 KEM Routines | kyber768_kem:: |
include/kyber768_kem.hpp |
| Kyber1024 KEM Routines | kyber1024_kem:: |
include/kyber1024_kem.hpp |
Note
Kyber parameter sets are selected from table 1 of Kyber specification https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf.
See example program, where I show how to use Kyber512 KEM API. You can almost similarly use Kyber768 or Kyber1024 KEM API, by just importing correct header file and using KEM functions/ constants from respective namespace.
g++ -std=c++20 -Wall -Wextra -pedantic -O3 -march=native -I ./include -I ./sha3/include -I ./subtle/include/ examples/kyber512_kem.cpp && ./a.out
Kyber512 KEM
pubkey : 175782d35b2666833aee098617626d88dbcc47091a011882d52105acc218c9287a95276a3259a6a94aa386d8148886abdcc1841f39260ce4754ebacc1fd36102905d4c623d0b27930b4c249ee7380758c0ac5982b0e932eda95184a40f55c451d835861ca2b314dbce97829f1b92752dda592d8960b2540f464988ea1c974c63467c439b1de540490b0af0491a6507951ebc971887bd2b4a11327381d99586f10668c83abe92fb649b113da7ec666729bc1cc38a1de137dd3cc4e3a6abb9881a2ee63e7df3ad6cb680664ba1559ca17448c968b7c867ac5f324911ffd43993b8a7b8f57094c786877c1208fa7f53e51d6f1a46ae71bc81f78ebe5808d48200b7e1bc81ec3d31070a6993aa5db237eb3a4c592aa559a73bd769583a0ad095ec1669b952be4a71fe8603f5d597f007a048cc9d7fea6735383b6b8bbf896b74dc48a21840a92c497a9bc7434b0241a9e42e6428515d477c4e0b3678fab1d619b794f01b828648e7577bb2e5297915b9fdf33cb291a37de51b51c7aca6f07994193bd981134da2340c23a93cda8b68e429ac801d3748b8d112b57e388511e3305e50a51184b623607447468be94351cd0b9111a119b4b3c6f270c1cfea749a2ac89455590280c369163946481dbaeb4693dbb376202db2d8464c61aea6411cd887080f5c59e1587da01510cd1b0e8b030a5c200639ba26376134e88279891b90373cc92e7a76c0aaa33d084ab3f61e175010996652e441300ad5aefda9cc88f17fef2102b643179e0a49a60c47ce06c5b1a0b150b09ca4593e5dd48a9b1979d103ba862c43ed354d2ec99575b70e741808288aa0e1cb792c0a458d4584ddfa1870d7b797e2aac7d4cc08916015401338d8841d226d9656661cda93f53343e0f906b82bce8f25428b02a639a47f7dda5b946a3785656fb6d083df5a5ec7493cc017a2469b1f43c96f2e3bbc9d6cb07bec82d721a4cfba6ca2c59b0e01bda98585692b9da753923f830b52c843b6d963f959ad60189f42d61df7808f4d131c4d233e246c4735193e516452061701e6114cf1587a54c79105f48fdce9c2134bb60550b242945ea011ec54c570054b93d96f072426b7c9b524db8d2f136b7db2d1f38897
seckey : a598a250c2008688af8f71a285abae5b528a19479acf915cd2f92a7365bc757c670accc4b2190aa77b7d0c76355962a0ea9b6a1f4400be77797a6851776815032307913aa475b733a1ba698b2134ea25a57bd9b979e2bcb7d99f24f06ee760227486ae1cdaba79065bc3180d79a0906c514e5b973435c00f34b87e882643ef6b42bcbca4a3b65207abb5dca76e49a9be7a6013d256bc09b1211b70bb28e2151200c6c1e00082e88634600a29e3cf5ff541051c703ac373a91228a6d30491221df6749e22b21429612ed4ba07a7d7789717809e498f2e3a1b8a6a40afe0a7d2460350074a2a5127cc20c0b03446977a612a096324337cd5bc455f77cdbe4600e147b02fe58bc9c383b1e84ea3bc5755d3a87ce515b07c96741a72d9eb702d445acc3374531c70ef221216db2c9198110d83084f7b508da18fd34b8ee9f45d1204a627609d09a89c73e8bfc1f987c6bc906fac0d01720b169061b3d8015a5121a0d3beab454a03cc24a9bc5725e6c4aaf44d8f8b7242443f289c0751226448ec794a02a1ba411caeabb99f7a90510b8812a91a0ad69f1476408940381724a1dbfb7f69642788267b068c585bf41bf3f857fd14bcd9506b95b6a257d7481a07628004944e136a4c97842c13451e960cf4e08a8b6666e17a6aac016d701c1a00c82072939a092397c7104d7fd6332b860034f2ace5191e2792cf10e21f5166304bf329696128d63640b7882809b750f1f89e5d513fa08a8439e1ad5fe0affd887b0f06ab91798c35d48f39261af3dab7ddbc899be21d1f751b8d317b8e280f400b637ac6a471b4065973a6253235c94117e22083562b715ce680fafb78da9113f0f52692c52625ea8e1c24a1d8837beb963a5ab078455c8a43cbab68dc4eaa4c7646c9bb45803442250e935738944c7228aa3f7137567eb1231c63bff7552a7858525b92bdca832a41cb20fb24647a62af1da27e50c41f3cd070ed8c1d1213c22b1540a5c1412d67ab4ff334c2e5217c06a5f8a93c0637bd0fb4736c19591f67c378aa80f7c9587b346bbfe81eff8574c7e0acc3164c3df048019639a80377b97457175782d35b2666833aee098617626d88dbcc47091a011882d52105acc218c9287a95276a3259a6a94aa386d8148886abdcc1841f39260ce4754ebacc1fd36102905d4c623d0b27930b4c249ee7380758c0ac5982b0e932eda95184a40f55c451d835861ca2b314dbce97829f1b92752dda592d8960b2540f464988ea1c974c63467c439b1de540490b0af0491a6507951ebc971887bd2b4a11327381d99586f10668c83abe92fb649b113da7ec666729bc1cc38a1de137dd3cc4e3a6abb9881a2ee63e7df3ad6cb680664ba1559ca17448c968b7c867ac5f324911ffd43993b8a7b8f57094c786877c1208fa7f53e51d6f1a46ae71bc81f78ebe5808d48200b7e1bc81ec3d31070a6993aa5db237eb3a4c592aa559a73bd769583a0ad095ec1669b952be4a71fe8603f5d597f007a048cc9d7fea6735383b6b8bbf896b74dc48a21840a92c497a9bc7434b0241a9e42e6428515d477c4e0b3678fab1d619b794f01b828648e7577bb2e5297915b9fdf33cb291a37de51b51c7aca6f07994193bd981134da2340c23a93cda8b68e429ac801d3748b8d112b57e388511e3305e50a51184b623607447468be94351cd0b9111a119b4b3c6f270c1cfea749a2ac89455590280c369163946481dbaeb4693dbb376202db2d8464c61aea6411cd887080f5c59e1587da01510cd1b0e8b030a5c200639ba26376134e88279891b90373cc92e7a76c0aaa33d084ab3f61e175010996652e441300ad5aefda9cc88f17fef2102b643179e0a49a60c47ce06c5b1a0b150b09ca4593e5dd48a9b1979d103ba862c43ed354d2ec99575b70e741808288aa0e1cb792c0a458d4584ddfa1870d7b797e2aac7d4cc08916015401338d8841d226d9656661cda93f53343e0f906b82bce8f25428b02a639a47f7dda5b946a3785656fb6d083df5a5ec7493cc017a2469b1f43c96f2e3bbc9d6cb07bec82d721a4cfba6ca2c59b0e01bda98585692b9da753923f830b52c843b6d963f959ad60189f42d61df7808f4d131c4d233e246c4735193e516452061701e6114cf1587a54c79105f48fdce9c2134bb60550b242945ea011ec54c570054b93d96f072426b7c9b524db8d2f136b7db2d1f3889778f791d583227a702cdfa4a9f95014df019495f14e02318b3704dc3794af523705be75f29753f47b2888ceef235d82caca9f983b40bf10b29672da272113a973
cipher : bcee459c896ea378dcc458a532c35c029eff6b8cf8adc83f484fb6f9bfe32612f7c936cbf4dbd7c5262288dc3966a0d769f94a0bd57913a60a71efae09321c22c53839d836cef5fb8bf5c630bd3b3d657492eabfc7e67a42a631c95391656f0fce607a181e418144dff3d97f1192a2825a94da5113bcffc2e5f3e043f7583e6159902ddd009f8bcb18046a05695917bdef48accc2e3708f8536aabb420a7fd7989c60bca6c1941af45eac2f03cf71c8506721f8cd69bd3c573f036e3e8ae72b85632d06e0cab6fa1fea078d84aa1a116ac58ee632a0542b2d0e6a7026ae814ceeb46478d1cefd082c9b19efa7bb6ddd7abda8e43eab7b5a5204449273ea056b36d3797371f855d0c7ff0436279b21b831ad0970c26cc39f8627deb932689b8df48e73b1b5893987fa4dbc65571a78287f1573beeb85db52a3edbad6f50725bcbfa40423e3ce1ab00c16ea3922bc42e6782ce224ccfb3c978d8704584b9768a8edb6a950c0208b1c1c9a6a4e0d6300a9cfe788389697460efc41308448e9752d2022dfdecd118440346e2fabb07559b76301943f3b186adaaba09828efb28db1cd4a5e82e01f360451cb3c487f371af05725ea0e7d61932a8dc38108e99182e9b50d2aa828a773a2e18f5271ac75e5a5c50b9221f893e5f7076732beb0ffb9e4b82e1c0648192c9547870372b78c6a3e3a1b00d904a4a1492d5944e0510acee62e40c78cecef97922b04807cdd47d4d403a7bb16316598e6eee760b257382d9648c9920c3395717d8ac829bd37465c0f3e7f0c7e6fc351aac802edb722200776906eb36f622c0b8702958e44317961f583265a83b8cfcd9eed80f15b9ef848ebb7355df9718a60c532e20074854797685b3e4a25f929fce9ad02a5af114f92210abd3b73fddf28f116c2d4c27ceda6428a3892eb0c18fc12b07596e4153f2a3df9aa440957704bc56bbbee06cd99def3218c046344b4c5a811840a088bcbbad76fca4a20b9bf608873b2830afd6097b05022e8b1d42af3e5e4f00303adc9f130a84cdde3fef9335ccd1120b3f2050f17ef0c10fd226268965cbfc13738ada0632
shared secret : 508ac79bf97e90d75267159ba5189b73c48ab41a91aec0f32edd6cd1e66465b5
Caution
Before you consider using Psuedo Random Number Generator which comes with this library implementation, I strongly advice you to go through include/prng.hpp.
Note
Looking at API documentation, in header files, can give you good idea of how to use Kyber KEM API. Note, this library doesn't expose any raw pointer based interface, rather everything is wrapped under statically defined
std::span- which one can easily create fromstd::{array, vector}. I opt for using statically definedstd::spanbased function interfaces because we always know, at compile-time, how many bytes the seeds/ keys/ cipher-texts/ shared-secrets are, for various different Kyber KEM parameters. This gives much better type safety and compile-time error reporting.