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 timing leakage free, using dudect (see https://github.com/oreparaz/dudect) 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 only 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 FujisakiOkamoto (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, subtle and dudect (for timing leakage tests) are 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.

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-test library 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-benchmark header 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-benchmark library with libPFM support, 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 --init from 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 50193 .
[==========] Running 10 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 10 tests from KyberKEM
[ RUN      ] KyberKEM.ArithmeticOverZq
[       OK ] KyberKEM.ArithmeticOverZq (126 ms)
[ RUN      ] KyberKEM.Kyber768KeygenEncapsDecaps
[       OK ] KyberKEM.Kyber768KeygenEncapsDecaps (0 ms)
[ RUN      ] KyberKEM.Kyber512KeygenEncapsDecaps
[       OK ] KyberKEM.Kyber512KeygenEncapsDecaps (0 ms)
[ RUN      ] KyberKEM.Kyber768KnownAnswerTests
[       OK ] KyberKEM.Kyber768KnownAnswerTests (8 ms)
[ RUN      ] KyberKEM.Kyber512KnownAnswerTests
[       OK ] KyberKEM.Kyber512KnownAnswerTests (5 ms)
[ RUN      ] KyberKEM.CompressDecompressZq
[       OK ] KyberKEM.CompressDecompressZq (98 ms)
[ RUN      ] KyberKEM.Kyber1024KnownAnswerTests
[       OK ] KyberKEM.Kyber1024KnownAnswerTests (13 ms)
[ RUN      ] KyberKEM.NumberTheoreticTransform
[       OK ] KyberKEM.NumberTheoreticTransform (0 ms)
[ RUN      ] KyberKEM.PolynomialSerialization
[       OK ] KyberKEM.PolynomialSerialization (0 ms)
[ RUN      ] KyberKEM.Kyber1024KeygenEncapsDecaps
[       OK ] KyberKEM.Kyber1024KeygenEncapsDecaps (0 ms)
[----------] 10 tests from KyberKEM (253 ms total)

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

In case you're interested in running timing leakage tests using dudect, execute following

Note

dudect is integrated into this library implementation of Kyber KEM to find any sort of timing leakages. It checks for constant-timeness of all vital functions including Fujisaki-Okamoto transform, used in decapsulation step. It doesn't check constant-timeness of function which samples public matrix A, because that fails the check anyway, due to use of uniform rejection sampling. As matrix A is public, it's not critical that it must be strictly constant-time.

make dudect_test -j # Only on x86_64 machine
                    # Each executable is run for at max 3 mins.

Tip

dudect documentation says if t statistic is < 10, we're probably good, yes probably. You may want to read dudect documentation @ https://github.com/oreparaz/dudect. Also you might find the original paper @ https://ia.cr/2016/1123 interesting.

meas:    0.10 M, max t:   +2.35, max tau: 7.27e-03, (5/tau)^2: 4.73e+05. For the moment, maybe constant time.
meas:    0.12 M, max t:   +1.89, max tau: 5.57e-03, (5/tau)^2: 8.06e+05. For the moment, maybe constant time.
meas:    3.10 M, max t:   +2.48, max tau: 1.41e-03, (5/tau)^2: 1.26e+07. For the moment, maybe constant time.
meas:    2.07 M, max t:   +1.72, max tau: 1.20e-03, (5/tau)^2: 1.75e+07. For the moment, maybe constant time.
meas:    2.10 M, max t:   +1.66, max tau: 1.14e-03, (5/tau)^2: 1.91e+07. For the moment, maybe constant time.
meas:    6.01 M, max t:   +1.67, max tau: 6.82e-04, (5/tau)^2: 5.37e+07. For the moment, maybe constant time.
meas:    7.31 M, max t:   +1.67, max tau: 6.18e-04, (5/tau)^2: 6.54e+07. For the moment, maybe constant time.
meas:    7.96 M, max t:   +2.04, max tau: 7.22e-04, (5/tau)^2: 4.80e+07. For the moment, maybe constant time.
meas:    9.41 M, max t:   +1.70, max tau: 5.54e-04, (5/tau)^2: 8.14e+07. For the moment, maybe constant time.
meas:    9.89 M, max t:   +1.59, max tau: 5.05e-04, (5/tau)^2: 9.78e+07. For the moment, maybe constant time.
meas:    0.99 M, max t:   +2.16, max tau: 2.18e-03, (5/tau)^2: 5.28e+06. For the moment, maybe constant time.
meas:    0.14 M, max t:   +2.04, max tau: 5.44e-03, (5/tau)^2: 8.45e+05. For the moment, maybe constant time.
meas:    2.31 M, max t:   +2.90, max tau: 1.90e-03, (5/tau)^2: 6.89e+06. For the moment, maybe constant time.
meas:    3.03 M, max t:   +3.55, max tau: 2.04e-03, (5/tau)^2: 5.99e+06. For the moment, maybe constant time.
meas:    3.56 M, max t:   +3.23, max tau: 1.71e-03, (5/tau)^2: 8.56e+06. For the moment, maybe constant time.
meas:    4.18 M, max t:   +2.42, max tau: 1.18e-03, (5/tau)^2: 1.78e+07. For the moment, maybe constant time.
meas:    7.16 M, max t:   +2.40, max tau: 8.96e-04, (5/tau)^2: 3.12e+07. For the moment, maybe constant time.
meas:    8.25 M, max t:   +2.21, max tau: 7.68e-04, (5/tau)^2: 4.24e+07. For the moment, maybe constant time.
meas:    9.20 M, max t:   +2.27, max tau: 7.48e-04, (5/tau)^2: 4.47e+07. For the moment, maybe constant time.
meas:   10.23 M, max t:   +2.45, max tau: 7.66e-04, (5/tau)^2: 4.26e+07. For the moment, maybe constant time.
meas:    6.93 M, max t:   +2.54, max tau: 9.65e-04, (5/tau)^2: 2.69e+07. For the moment, maybe constant time.
meas:    7.49 M, max t:   +2.54, max tau: 9.30e-04, (5/tau)^2: 2.89e+07. For the moment, maybe constant time.
meas:    8.04 M, max t:   +2.16, max tau: 7.61e-04, (5/tau)^2: 4.32e+07. For the moment, maybe constant time.
meas:    8.57 M, max t:   +2.08, max tau: 7.10e-04, (5/tau)^2: 4.96e+07. For the moment, maybe constant time.
meas:    9.15 M, max t:   +2.03, max tau: 6.72e-04, (5/tau)^2: 5.54e+07. For the moment, maybe constant time.
meas:    0.15 M, max t:   +1.80, max tau: 4.60e-03, (5/tau)^2: 1.18e+06. For the moment, maybe constant time.
meas:    8.04 M, max t:   +1.90, max tau: 6.70e-04, (5/tau)^2: 5.57e+07. For the moment, maybe constant time.
meas:   10.31 M, max t:   +2.04, max tau: 6.35e-04, (5/tau)^2: 6.20e+07. For the moment, maybe constant time.
meas:   10.38 M, max t:   +2.05, max tau: 6.35e-04, (5/tau)^2: 6.19e+07. For the moment, maybe constant time.
meas:    9.19 M, max t:   +1.99, max tau: 6.56e-04, (5/tau)^2: 5.80e+07. For the moment, maybe constant time.
meas:    9.24 M, max t:   +2.04, max tau: 6.69e-04, (5/tau)^2: 5.58e+07. For the moment, maybe constant time.
meas:    1.02 M, max t:   +1.98, max tau: 1.97e-03, (5/tau)^2: 6.47e+06. For the moment, maybe constant time.
meas:    2.10 M, max t:   +2.10, max tau: 1.45e-03, (5/tau)^2: 1.19e+07. For the moment, maybe constant time.
meas:    1.40 M, max t:   +1.81, max tau: 1.52e-03, (5/tau)^2: 1.08e+07. For the moment, maybe constant time.
meas:    1.41 M, max t:   +2.21, max tau: 1.86e-03, (5/tau)^2: 7.22e+06. For the moment, maybe constant time.
meas:    1.81 M, max t:   +2.95, max tau: 2.19e-03, (5/tau)^2: 5.20e+06. For the moment, maybe constant time.
meas:    2.54 M, max t:   +2.96, max tau: 1.86e-03, (5/tau)^2: 7.26e+06. For the moment, maybe constant time.
meas:    3.15 M, max t:   +2.77, max tau: 1.56e-03, (5/tau)^2: 1.02e+07. For the moment, maybe constant time.
meas:    4.94 M, max t:   +2.46, max tau: 1.11e-03, (5/tau)^2: 2.04e+07. For the moment, maybe constant time.
meas:    0.91 M, max t:   +2.06, max tau: 2.17e-03, (5/tau)^2: 5.32e+06. For the moment, maybe constant time.
meas:    1.21 M, max t:   +2.19, max tau: 1.99e-03, (5/tau)^2: 6.32e+06. For the moment, maybe constant time.
meas:    1.44 M, max t:   +2.24, max tau: 1.87e-03, (5/tau)^2: 7.17e+06. For the moment, maybe constant time.
meas:    8.74 M, max t:   +2.32, max tau: 7.87e-04, (5/tau)^2: 4.04e+07. For the moment, maybe constant time.
meas:    9.65 M, max t:   +2.42, max tau: 7.80e-04, (5/tau)^2: 4.11e+07. For the moment, maybe constant time.
meas:   10.57 M, max t:   +2.22, max tau: 6.82e-04, (5/tau)^2: 5.38e+07. For the moment, maybe constant time.
meas:   11.71 M, max t:   +2.45, max tau: 7.16e-04, (5/tau)^2: 4.88e+07. For the moment, maybe constant time.

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-benchmark header 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 GCC-13.2.0 )

2023-12-28T22:37:22+04:00
Running ./build/perf.out
Run on (16 X 3037.9 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.57, 0.62, 0.43
---------------------------------------------------------------------------------------------------------
Benchmark                        Time             CPU   Iterations     CYCLES items_per_second      rdtsc
---------------------------------------------------------------------------------------------------------
kyber512/keygen_mean          14.1 us         14.1 us           10   64.2551k       71.0585k/s   35.0906k
kyber512/keygen_median        14.1 us         14.1 us           10    64.358k       71.1093k/s    35.062k
kyber512/keygen_stddev       0.139 us        0.140 us           10    336.699        706.085/s    347.453
kyber512/keygen_cv            0.99 %          0.99 %            10      0.52%            0.99%      0.99%
kyber512/keygen_min           13.8 us         13.8 us           10   63.5224k       69.9823k/s    34.448k
kyber512/keygen_max           14.3 us         14.3 us           10   64.6034k       72.3792k/s    35.627k
kyber1024/keygen_mean         37.6 us         37.6 us           10   173.352k       26.5753k/s   93.9093k
kyber1024/keygen_median       37.4 us         37.4 us           10   173.215k       26.7224k/s    93.369k
kyber1024/keygen_stddev      0.653 us        0.653 us           10     786.61        458.727/s   1.62786k
kyber1024/keygen_cv           1.73 %          1.74 %            10      0.45%            1.73%      1.73%
kyber1024/keygen_min          36.8 us         36.8 us           10   172.387k       25.8361k/s    91.825k
kyber1024/keygen_max          38.7 us         38.7 us           10   174.533k       27.1731k/s    96.567k
kyber1024/decap_mean          47.8 us         47.8 us           10   220.881k        20.936k/s   119.188k
kyber1024/decap_median        47.7 us         47.7 us           10   220.494k       20.9441k/s   119.135k
kyber1024/decap_stddev       0.327 us        0.326 us           10    876.006        142.939/s    815.352
kyber1024/decap_cv            0.68 %          0.68 %            10      0.40%            0.68%      0.68%
kyber1024/decap_min           47.3 us         47.4 us           10   219.937k       20.7556k/s   118.145k
kyber1024/decap_max           48.2 us         48.2 us           10   222.431k       21.1193k/s   120.224k
kyber768/keygen_mean          23.6 us         23.6 us           10   108.277k       42.3383k/s   58.9271k
kyber768/keygen_median        23.6 us         23.6 us           10   108.008k       42.3843k/s   58.8515k
kyber768/keygen_stddev       0.356 us        0.355 us           10    861.437        631.197/s    887.049
kyber768/keygen_cv            1.51 %          1.50 %            10      0.80%            1.49%      1.51%
kyber768/keygen_min           23.2 us         23.2 us           10   107.164k       41.1642k/s     57.96k
kyber768/keygen_max           24.3 us         24.3 us           10   109.738k       43.0367k/s    60.599k
kyber768/encap_mean           29.2 us         29.2 us           10   133.283k       34.1969k/s   72.9656k
kyber768/encap_median         29.2 us         29.2 us           10   133.036k       34.2633k/s   72.8075k
kyber768/encap_stddev        0.446 us        0.446 us           10    696.703        513.482/s   1.11308k
kyber768/encap_cv             1.53 %          1.53 %            10      0.52%            1.50%      1.53%
kyber768/encap_min            28.8 us         28.8 us           10   132.576k       33.0903k/s    71.751k
kyber768/encap_max            30.2 us         30.2 us           10   134.318k        34.768k/s    75.392k
kyber768/decap_mean           31.8 us         31.8 us           10   146.582k       31.4757k/s   79.2733k
kyber768/decap_median         31.8 us         31.8 us           10   146.415k       31.4736k/s   79.2685k
kyber768/decap_stddev        0.346 us        0.345 us           10    842.496        342.357/s    864.056
kyber768/decap_cv             1.09 %          1.09 %            10      0.57%            1.09%      1.09%
kyber768/decap_min            31.3 us         31.3 us           10   145.565k       31.0697k/s     78.03k
kyber768/decap_max            32.2 us         32.2 us           10   148.349k       31.9721k/s    80.298k
kyber512/decap_mean           19.8 us         19.8 us           10   90.6467k       50.6123k/s   49.2887k
kyber512/decap_median         19.9 us         19.9 us           10   90.5468k        50.349k/s   49.5365k
kyber512/decap_stddev        0.282 us        0.282 us           10     386.91        725.855/s    703.452
kyber512/decap_cv             1.43 %          1.43 %            10      0.43%            1.43%      1.43%
kyber512/decap_min            19.4 us         19.4 us           10   90.2405k       49.6676k/s    48.316k
kyber512/decap_max            20.1 us         20.1 us           10   91.6688k       51.6211k/s    50.221k
kyber1024/encap_mean          44.3 us         44.3 us           10   203.866k       22.5631k/s   110.616k
kyber1024/encap_median        44.1 us         44.1 us           10   203.541k       22.7015k/s   109.918k
kyber1024/encap_stddev       0.781 us        0.780 us           10   1.19386k        393.859/s   1.94932k
kyber1024/encap_cv            1.76 %          1.76 %            10      0.59%            1.75%      1.76%
kyber1024/encap_min           43.4 us         43.4 us           10   202.563k       21.9678k/s   108.235k
kyber1024/encap_max           45.5 us         45.5 us           10   206.041k       23.0525k/s   113.597k
kyber512/encap_mean           17.8 us         17.8 us           10   81.0681k        56.056k/s   44.4971k
kyber512/encap_median         17.9 us         17.9 us           10   81.0694k       55.9365k/s   44.5815k
kyber512/encap_stddev        0.260 us        0.259 us           10    200.398        822.202/s    648.275
kyber512/encap_cv             1.46 %          1.45 %            10      0.25%            1.47%      1.46%
kyber512/encap_min            17.4 us         17.4 us           10   80.8481k       55.0013k/s    43.277k
kyber512/encap_max            18.2 us         18.2 us           10   81.4717k       57.6231k/s    45.351k

On ARM Cortex-A72 i.e. Raspberry Pi 4B ( compiled with GCC-13.2.0 )

2023-12-28T23:28:27+04:00
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.96, 0.80, 0.34
----------------------------------------------------------------------------------------------
Benchmark                        Time             CPU   Iterations     CYCLES items_per_second
----------------------------------------------------------------------------------------------
kyber1024/encap_mean           225 us          224 us           10   402.708k       4.46187k/s
kyber1024/encap_median         224 us          224 us           10       402k       4.46839k/s
kyber1024/encap_stddev        1.04 us         1.01 us           10   1.83888k        19.9568/s
kyber1024/encap_cv            0.46 %          0.45 %            10      0.46%            0.45%
kyber1024/encap_min            224 us          223 us           10   400.783k       4.42744k/s
kyber1024/encap_max            226 us          226 us           10   405.835k       4.48239k/s
kyber1024/decap_mean           252 us          251 us           10   451.164k       3.98273k/s
kyber1024/decap_median         252 us          251 us           10   451.455k        3.9805k/s
kyber1024/decap_stddev       0.813 us        0.807 us           10   1.42897k        12.8137/s
kyber1024/decap_cv            0.32 %          0.32 %            10      0.32%            0.32%
kyber1024/decap_min            250 us          250 us           10   448.489k       3.96263k/s
kyber1024/decap_max            253 us          252 us           10   453.484k       4.00678k/s
kyber512/keygen_mean          69.0 us         68.8 us           10   123.701k       14.5275k/s
kyber512/keygen_median        69.0 us         68.8 us           10   123.636k       14.5345k/s
kyber512/keygen_stddev       0.200 us        0.200 us           10    356.274         42.215/s
kyber512/keygen_cv            0.29 %          0.29 %            10      0.29%            0.29%
kyber512/keygen_min           68.6 us         68.5 us           10   123.032k       14.4587k/s
kyber512/keygen_max           69.3 us         69.2 us           10   124.294k       14.6072k/s
kyber768/keygen_mean           119 us          119 us           10   213.373k       8.42213k/s
kyber768/keygen_median         119 us          119 us           10   213.278k       8.42447k/s
kyber768/keygen_stddev       0.408 us        0.383 us           10    695.469        27.1211/s
kyber768/keygen_cv            0.34 %          0.32 %            10      0.33%            0.32%
kyber768/keygen_min            119 us          118 us           10   212.479k       8.36808k/s
kyber768/keygen_max            120 us          120 us           10   214.775k       8.45855k/s
kyber768/decap_mean            170 us          169 us           10   304.171k       5.90762k/s
kyber768/decap_median          170 us          169 us           10   304.077k       5.90893k/s
kyber768/decap_stddev        0.660 us        0.626 us           10   1.12079k        21.8452/s
kyber768/decap_cv             0.39 %          0.37 %            10      0.37%            0.37%
kyber768/decap_min             169 us          168 us           10   302.481k       5.86956k/s
kyber768/decap_max             171 us          170 us           10   306.146k       5.94026k/s
kyber512/decap_mean            107 us          107 us           10   191.962k       9.36013k/s
kyber512/decap_median          107 us          107 us           10    191.84k       9.36637k/s
kyber512/decap_stddev        0.529 us        0.539 us           10    966.932        46.9797/s
kyber512/decap_cv             0.49 %          0.50 %            10      0.50%            0.50%
kyber512/decap_min             106 us          106 us           10   190.437k       9.25135k/s
kyber512/decap_max             108 us          108 us           10   194.256k       9.43608k/s
kyber512/encap_mean           90.4 us         90.2 us           10   162.028k       11.0908k/s
kyber512/encap_median         90.4 us         90.2 us           10   162.064k       11.0875k/s
kyber512/encap_stddev        0.191 us        0.181 us           10    309.007        22.3167/s
kyber512/encap_cv             0.21 %          0.20 %            10      0.19%            0.20%
kyber512/encap_min            90.0 us         89.9 us           10    161.51k       11.0601k/s
kyber512/encap_max            90.6 us         90.4 us           10   162.418k       11.1282k/s
kyber768/encap_mean            148 us          148 us           10    265.56k       6.76723k/s
kyber768/encap_median          148 us          148 us           10   265.539k       6.76699k/s
kyber768/encap_stddev        0.537 us        0.454 us           10    823.561        20.7123/s
kyber768/encap_cv             0.36 %          0.31 %            10      0.31%            0.31%
kyber768/encap_min             147 us          147 us           10   264.361k       6.71907k/s
kyber768/encap_max             149 us          149 us           10    267.48k       6.79829k/s
kyber1024/keygen_mean          189 us          188 us           10   338.248k       5.31272k/s
kyber1024/keygen_median        188 us          188 us           10   337.954k       5.31735k/s
kyber1024/keygen_stddev      0.422 us        0.408 us           10     726.17        11.5098/s
kyber1024/keygen_cv           0.22 %          0.22 %            10      0.21%            0.22%
kyber1024/keygen_min           188 us          188 us           10   337.245k       5.29872k/s
kyber1024/keygen_max           189 us          189 us           10   339.141k       5.32926k/

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 kyber repository.
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, sha3 and subtle headers, 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 from std::{array, vector}. I opt for using statically defined std::span based 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.

Description
No description provided
Readme BSD-3-Clause 7.1 MiB
Languages
C++ 90.4%
Makefile 6.1%
Python 2.9%
Shell 0.6%