Files
ml-kem/example/kem.cpp
2022-11-01 09:09:02 +04:00

79 lines
2.7 KiB
C++

#include "kyber_kem.hpp"
#include <cassert>
#include <iostream>
// Compile it with
//
// g++ -std=c++20 -Wall -O3 -I ./include -I ./sha3/include example/kem.cpp
int
main()
{
// Kyber-512 Key Encapsulation Mechanism (KEM) parameters
//
// See table 1 of Kyber specification for all suggested parameters
// https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf
constexpr size_t k = 2;
constexpr size_t eta1 = 3;
constexpr size_t eta2 = 2;
constexpr size_t du = 10;
constexpr size_t dv = 4;
// compile time compute byte length of Kyber-512 KEM public key, secret key
// and cipher text
constexpr size_t pklen = kyber_utils::get_ccakem_public_key_len<k>();
constexpr size_t sklen = kyber_utils::get_ccakem_secret_key_len<k>();
constexpr size_t ctlen = kyber_utils::get_ccakem_cipher_len<k, du, dv>();
constexpr size_t klen = 32;
// dynamic allocation request of memory resources
uint8_t* pubkey = static_cast<uint8_t*>(std::malloc(pklen));
uint8_t* seckey = static_cast<uint8_t*>(std::malloc(sklen));
uint8_t* cipher = static_cast<uint8_t*>(std::malloc(ctlen));
uint8_t* shrd_key0 = static_cast<uint8_t*>(std::malloc(klen));
uint8_t* shrd_key1 = static_cast<uint8_t*>(std::malloc(klen));
std::memset(pubkey, 0, pklen);
std::memset(seckey, 0, sklen);
std::memset(cipher, 0, ctlen);
// CCA-secure KEM key generation
kyber_kem::keygen<k, eta1>(pubkey, seckey);
// CCA-secure key encapsulation using public key, producing KDF
auto skdf = kyber_kem::encapsulate<k, eta1, eta2, du, dv>(pubkey, cipher);
// CCA-secure key decapsulation using secret key, producing KDF
auto rkdf = kyber_kem::decapsulate<k, eta1, eta2, du, dv>(seckey, cipher);
// key encapsulator ( who had public key ), derives 32 -bytes key from its KDF
skdf.read(shrd_key0, klen);
// key decapsulator ( who used secret key ), derives same 32 -bytes key
rkdf.read(shrd_key1, klen);
// check that both parties who intended to share a secret key ( can be used
// with symmetric key primitives ) over insecure public channel did that and
// arrived at same 32 -bytes value.
bool flg = false;
for (size_t i = 0; i < klen; i++) {
flg |= static_cast<bool>(shrd_key0[i] ^ shrd_key1[i]);
}
{
using namespace kyber_utils;
std::cout << "pubkey : " << to_hex(pubkey, pklen) << "\n";
std::cout << "seckey : " << to_hex(seckey, sklen) << "\n";
std::cout << "shared secret 0 : " << to_hex(shrd_key0, klen) << "\n";
std::cout << "shared secret 1 : " << to_hex(shrd_key1, klen) << "\n";
}
std::free(pubkey);
std::free(seckey);
std::free(cipher);
std::free(shrd_key0);
std::free(shrd_key1);
// defer assertion until end ( let memory allocation be freed first )
assert(!flg);
return EXIT_SUCCESS;
}