Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ cpmaddpackage(URI "gh:google/benchmark@1.9.4" OPTIONS
"BENCHMARK_ENABLE_TESTING Off")

add_executable(deb-benchmark benchmark.cpp)
target_link_libraries(deb-benchmark PRIVATE deb_obj deb_DevHeader
benchmark::benchmark_main)
target_link_libraries(deb-benchmark PRIVATE deb benchmark::benchmark_main)

enable_language(C)
cpmaddpackage(
Expand All @@ -33,6 +32,5 @@ cpmaddpackage(
c)

add_executable(deb-benchmark-blake3 benchmark_blake3.cpp)
target_link_libraries(
deb-benchmark-blake3 PRIVATE deb_obj deb_DevHeader benchmark::benchmark_main
BLAKE3::blake3)
target_link_libraries(deb-benchmark-blake3
PRIVATE deb benchmark::benchmark_main BLAKE3::blake3)
53 changes: 53 additions & 0 deletions benchmark/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,30 @@ template <Preset T> static void bm_decryption(benchmark::State &state) {
}
}

template <Preset T> static void bm_decryption_inplace(benchmark::State &state) {
const Preset preset = T;
const auto ns = get_num_secret(preset);
std::vector<Message> msg_v;
for (Size i = 0; i < ns; ++i) {
msg_v.push_back(gen_random_message(get_num_slots(preset)));
}

SecretKey sk = SecretKeyGenerator::GenSecretKey(preset);
EncryptorT<T> encryptor;
DecryptorT<T> decryptor;
Ciphertext ctxt(preset);
encryptor.encrypt(msg_v, sk, ctxt);

std::optional<Ciphertext> ctxt_copy;
for (auto _ : state) {
state.PauseTiming();
ctxt_copy.emplace(ctxt.deepCopy());
state.ResumeTiming();
decryptor.decryptInplace(ctxt_copy.value(), sk, msg_v.data());
benchmark::DoNotOptimize(msg_v.data());
benchmark::ClobberMemory();
}
}
template <Preset T>
static void bm_seckey_coeff_encryption(benchmark::State &state) {
const Preset preset = T;
Expand Down Expand Up @@ -176,6 +200,31 @@ static void bm_coeff_decryption(benchmark::State &state) {
}
}

template <Preset T>
static void bm_coeff_decryption_inplace(benchmark::State &state) {
const Preset preset = T;
const auto ns = get_num_secret(preset);
std::vector<CoeffMessage> msg_v;
for (Size i = 0; i < ns; ++i) {
msg_v.push_back(gen_random_coeff(get_degree(preset)));
}
SecretKey sk = SecretKeyGenerator::GenSecretKey(preset);
EncryptorT<T> encryptor(preset);
DecryptorT<T> decryptor(preset);

Ciphertext ctxt(preset);
encryptor.encrypt(msg_v, sk, ctxt);

std::optional<Ciphertext> ctxt_copy;
for (auto _ : state) {
state.PauseTiming();
ctxt_copy.emplace(ctxt.deepCopy());
state.ResumeTiming();
decryptor.decryptInplace(ctxt_copy.value(), sk, msg_v.data());
benchmark::DoNotOptimize(msg_v.data());
benchmark::ClobberMemory();
}
}
template <Size degree, u64 prime>
static void bm_forward_ntt(benchmark::State &state) {
utils::NTT ntt(degree, prime);
Expand Down Expand Up @@ -218,11 +267,15 @@ static void bm_backward_ntt(benchmark::State &state) {
->Unit(benchmark::kMicrosecond); \
BENCHMARK_TEMPLATE(bm_decryption, Preset::PRESET_##PRESET) \
->Unit(benchmark::kMicrosecond); \
BENCHMARK_TEMPLATE(bm_decryption_inplace, Preset::PRESET_##PRESET) \
->Unit(benchmark::kMicrosecond); \
BENCHMARK_TEMPLATE(bm_seckey_coeff_encryption, Preset::PRESET_##PRESET) \
->Unit(benchmark::kMicrosecond); \
BENCHMARK_TEMPLATE(bm_enckey_coeff_encryption, Preset::PRESET_##PRESET) \
->Unit(benchmark::kMicrosecond); \
BENCHMARK_TEMPLATE(bm_coeff_decryption, Preset::PRESET_##PRESET) \
->Unit(benchmark::kMicrosecond); \
BENCHMARK_TEMPLATE(bm_coeff_decryption_inplace, Preset::PRESET_##PRESET)\
->Unit(benchmark::kMicrosecond);

PRESET_LIST
Expand Down
56 changes: 44 additions & 12 deletions include/deb/Decryptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
#include <type_traits>

namespace deb {
// TODO: make template for Decryptor
// to support constexpr functions with various presets
/**
* @brief Provides CKKS decryption and decoding utilities.
*/
Expand All @@ -38,10 +36,11 @@ class DecryptorT : public PresetTraits<P, U> {
public:
/**
* @brief Creates a decryptor for the given preset.
* @param preset Target preset that defines polynomial sizes and moduli.
* @param target_preset Target preset that defines polynomial sizes and
* moduli.
*/
explicit DecryptorT();
explicit DecryptorT(const Preset preset);
explicit DecryptorT(const Preset target_preset);

template <typename MSG,
std::enable_if_t<!std::is_pointer_v<std::decay_t<MSG>>, int> = 0>
Expand Down Expand Up @@ -69,6 +68,10 @@ class DecryptorT : public PresetTraits<P, U> {
void decrypt(const CiphertextT<U> &ctxt, const SecretKeyT<U> &sk, MSG *msg,
Real scale = 0) const;

template <typename MSG>
void decryptInplace(CiphertextT<U> &ctxt, const SecretKeyT<U> &sk, MSG *msg,
Real scale = 0) const;

template <typename MSG>
/**
* @brief Decrypts into a vector-like container, validating secret-unit
Expand All @@ -86,21 +89,47 @@ class DecryptorT : public PresetTraits<P, U> {
decrypt(ctxt, sk, msg.data(), scale);
}

private:
/**
* @brief Internal decryption function that produces a decrypted polynomial
* plaintext.
* @param ctxt Ciphertext input.
* @param sx Secret key polynomial used for decryption.
* @param ax Optional auxiliary polynomial for decryption (e.g., from
* switching key).
* @return Decrypted polynomial plaintext.
*/
PolynomialT<U>
innerDecrypt(const CiphertextT<U> &ctxt, const PolynomialT<U> &sx,
const std::optional<PolynomialT<U>> &ax = std::nullopt) const;

/**
* @brief Internal decode function that handles both single-poly and
* poly-pair cases.
* @tparam CMSG Coefficient message type (e.g., CoeffMessage,
* FCoeffMessage).
* @param ptxt Decrypted polynomial plaintext.
* @param coeff Coefficient message that receives the decoded coefficients.
* @param scale Scaling factor for decoding.
*/
template <typename CMSG>
void innerDecode(const PolynomialT<U> &ptxt, CMSG &coeff, Real scale) const;
/**
* @brief Decodes a decrypted polynomial into a message-like object.
* @tparam MSG Message container or view type.
* @param ptxt Decrypted polynomial plaintext.
* @param msg Message object that receives decoded values.
* @param scale Scaling factor for decoding.
*/
template <typename MSG>
void decode(const PolynomialT<U> &ptxt, MSG &msg, Real scale) const;

private:
template <typename CMSG>
void decodeWithSinglePoly(const PolynomialT<U> &ptxt, CMSG &coeff,
Real scale) const;
template <typename CMSG>
void decodeWithPolyPair(const PolynomialT<U> &ptxt, CMSG &coeff,
Real scale) const;
template <typename CMSG>
void decodeWithoutFFT(const PolynomialT<U> &ptxt, CMSG &coeff,
Real scale) const;
template <typename MSG>
void decode(const PolynomialT<U> &ptxt, MSG &msg, Real scale) const;

utils::FFT fft_;
};
Expand All @@ -112,6 +141,9 @@ class DecryptorT : public PresetTraits<P, U> {
prefix template void DecryptorT<preset, u_type>::decrypt<msg_t>( \
const CiphertextT<u_type> &ctxt, const SecretKeyT<u_type> &sk, \
msg_t *msg, Real scale) const; \
prefix template void DecryptorT<preset, u_type>::decryptInplace<msg_t>( \
CiphertextT<u_type> & ctxt, const SecretKeyT<u_type> &sk, msg_t *msg, \
Real scale) const; \
prefix template void DecryptorT<preset, u_type>::decrypt<msg_t>( \
const CiphertextT<u_type> &ctxt, const SecretKeyT<u_type> &sk, \
std::vector<msg_t> &msg, Real scale) const;
Expand All @@ -134,11 +166,11 @@ class DecryptorT : public PresetTraits<P, U> {
const PolynomialT<u_type> &ptxt, FCoeffMessage &coeff, Real scale) \
const; \
prefix template void \
DecryptorT<preset, u_type>::decodeWithoutFFT<CoeffMessage>( \
DecryptorT<preset, u_type>::innerDecode<CoeffMessage>( \
const PolynomialT<u_type> &ptxt, CoeffMessage &coeff, Real scale) \
const; \
prefix template void \
DecryptorT<preset, u_type>::decodeWithoutFFT<FCoeffMessage>( \
DecryptorT<preset, u_type>::innerDecode<FCoeffMessage>( \
const PolynomialT<u_type> &ptxt, FCoeffMessage &coeff, Real scale) \
const; \
prefix template void DecryptorT<preset, u_type>::decode<Message>( \
Expand Down
74 changes: 57 additions & 17 deletions include/deb/Encryptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,28 +82,29 @@ class EncryptorT : public PresetTraits<P, U> {
public:
/**
* @brief Constructs an encryptor bound to a preset and optional RNG seed.
* @param preset Target preset.
* @param target_preset Target preset.
* @param seeds Optional deterministic seed.
*/
explicit EncryptorT(std::optional<const RNGSeed> seeds = std::nullopt);
explicit EncryptorT(Preset actual_preset,
explicit EncryptorT(Preset target_preset,
std::optional<const RNGSeed> seeds = std::nullopt);
/**
* @brief Constructs an encryptor with a custom random generator.
* @param actual_preset Target preset.
* @param target_preset Target preset.
* @param rng Custom random generator instance.
*/
explicit EncryptorT(Preset actual_preset,
explicit EncryptorT(Preset target_preset,
std::shared_ptr<RandomGenerator> rng);

template <typename MSG, typename KEY,
std::enable_if_t<!std::is_pointer_v<std::decay_t<MSG>>, int> = 0>
/**
* @brief Encrypts a message-like object reference with the provided key.
* @tparam MSG Message representation type.
* @tparam MSG Message representation type (e.g., Message, FMessage,
* CoeffMessage, FCoeffMessage).
* @tparam KEY Secret or switching key type.
* @param msg Input message object.
* @param key Encryption key or switch key.
* @param key Secret key or Switching(Encryption) key.
* @param ctxt Ciphertext that receives the encryption result.
* @param opt Optional encryption options.
*/
Expand All @@ -112,9 +113,10 @@ class EncryptorT : public PresetTraits<P, U> {

template <typename MSG, typename KEY>
/**
* @brief Encrypts a vector of messages element-wise.
* @brief Encrypts a vector of messages with multi-secret parameters. The
* message vector size must match num_secret.
* @param msg Vector with input messages.
* @param key Encryption key.
* @param key Secret key or Switching(Encryption) key.
* @param ctxt Ciphertext result container.
* @param opt Optional encryption options.
*/
Expand All @@ -124,32 +126,70 @@ class EncryptorT : public PresetTraits<P, U> {

template <typename MSG, typename KEY>
/**
* @brief Encrypts raw message arrays.
* @brief Encrypts a raw array of messages with multi-secret parameters. The
* array size must match num_secret.
* @param msg Pointer to message sequence.
* @param key Encryption key.
* @param key Secret key or Switching(Encryption) key.
* @param ctxt Ciphertext result container.
* @param opt Optional encryption options.
*/
void encrypt(const MSG *msg, const KEY &key, CiphertextT<U> &ctxt,
const EncryptOptions &opt = default_opt) const;

private:
template <typename KEY>
/**
* @brief Core encryption routine that produces a ciphertext from a
* plaintext polynomial and key.
* @tparam KEY Secret or switching key type.
* @param ptxt Encoded plaintext polynomial.
* @param key Secret or Switching(Encryption) key.
* @param num_polyunit Number of PolyUnitT entries to encrypt.
* @param ctxt Ciphertext result container.
*/
void innerEncrypt([[maybe_unused]] const PolynomialT<U> &ptxt,
[[maybe_unused]] const KEY &key,
[[maybe_unused]] Size num_polyunit,
[[maybe_unused]] CiphertextT<U> &ctxt) const;

template <typename MSG>
void embeddingToN(const MSG &msg, const Real &delta, PolynomialT<U> &ptxt,
const Size size) const;
/**
* @brief Core encode routine that embeds a message into a plaintext
* polynomial.
* @tparam MSG Message representation type (e.g., Message, FMessage,
* CoeffMessage, FCoeffMessage).
* @param msg Input message object.
* @param delta Scaling factor for embedding.
* @param ptxt Output plaintext polynomial.
* @param size Number of PolyUnitT entries to embed.
*/
void innerEncode(const MSG &msg, const Real &delta, PolynomialT<U> &ptxt,
const Size size) const;

template <typename MSG>
void encodeWithoutNTT(const MSG &msg, PolynomialT<U> &ptxt, const Size size,
const Real scale) const;
/**
* @brief Encodes a message into a plaintext polynomial.
* @tparam MSG Message representation type (e.g., Message, FMessage,
* CoeffMessage, FCoeffMessage).
* @param msg Input message object.
* @param ptxt Output plaintext polynomial.
* @param size Number of PolyUnitT entries to encode.
* @param scale Scaling factor for embedding.
*/
void encode(const MSG &msg, PolynomialT<U> &ptxt, const Size size,
const Real scale) const;

private:
/**
* @brief Samples a zero-one polynomial.
* @param num_polyunit Number of PolyUnitT entries to sample.
*/
void sampleZO(const Size num_polyunit) const;

/**
* @brief Samples a Gaussian polynomial.
* @param num_polyunit Number of PolyUnitT entries to sample.
* @param do_ntt Whether to apply NTT to the sampled polynomial.
*/
void sampleGaussian(const Size num_polyunit, const bool do_ntt) const;

std::shared_ptr<RandomGenerator> rng_;
Expand Down Expand Up @@ -182,10 +222,10 @@ class EncryptorT : public PresetTraits<P, U> {
#define DECL_ENCRYPT_TEMPLATE_MSG(preset, u_type, msg_t, prefix) \
DECL_ENCRYPT_TEMPLATE_MSG_KEY(preset, u_type, msg_t, SecretKeyT, prefix) \
DECL_ENCRYPT_TEMPLATE_MSG_KEY(preset, u_type, msg_t, SwitchKeyT, prefix) \
prefix template void EncryptorT<preset, u_type>::embeddingToN<msg_t>( \
prefix template void EncryptorT<preset, u_type>::innerEncode<msg_t>( \
const msg_t &msg, const Real &delta, PolynomialT<u_type> &ptxt, \
const Size size) const; \
prefix template void EncryptorT<preset, u_type>::encodeWithoutNTT<msg_t>( \
prefix template void EncryptorT<preset, u_type>::encode<msg_t>( \
const msg_t &msg, PolynomialT<u_type> &ptxt, const Size size, \
const Real scale) const;

Expand Down
8 changes: 4 additions & 4 deletions include/deb/KeyGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,19 @@ class KeyGeneratorT : public PresetTraits<P, U> {
/**
* @brief Builds a key generator for a preset when no secret key is
* provided. An external secret key must be given for key generation calls.
* @param preset Target preset whose parameters drive key sizes.
* @param target_preset Target preset whose parameters drive key sizes.
* @param seeds Optional deterministic RNG seed material used when new
* samples are required.
*/
explicit KeyGeneratorT(std::optional<const RNGSeed> seeds = std::nullopt);
explicit KeyGeneratorT(const Preset preset,
explicit KeyGeneratorT(const Preset target_preset,
std::optional<const RNGSeed> seeds = std::nullopt);
/**
* @brief Builds a key generator with a custom random generator.
* @param preset Target preset whose parameters drive key sizes.
* @param target_preset Target preset whose parameters drive key sizes.
* @param rng Custom random generator instance.
*/
explicit KeyGeneratorT(const Preset preset,
explicit KeyGeneratorT(const Preset target_preset,
std::shared_ptr<RandomGenerator> rng);

KeyGeneratorT(const KeyGeneratorT &) = delete;
Expand Down
6 changes: 3 additions & 3 deletions include/deb/SeedGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,22 @@ class SeedGenerator {
* @return Reference to the singleton instance.
*/
static SeedGenerator &
GetInstance(std::optional<const RNGSeed> seeds = std::nullopt);
GetInstance(const std::optional<RNGSeed> &seeds = std::nullopt);

/**
* @brief Reinitializes the underlying RNG with the provided seed.
* @param seeds Optional deterministic seed; when empty a random seed is
* chosen.
*/
static void Reseed(const std::optional<const RNGSeed> &seeds);
static void Reseed(const std::optional<RNGSeed> &seeds);
/**
* @brief Generates a new random seed suitable for deterministic APIs.
* @return Fresh RNG seed.
*/
static RNGSeed Gen();

private:
SeedGenerator(std::optional<const RNGSeed> seeds);
SeedGenerator(const std::optional<RNGSeed> &seeds);

/**
* @brief Internal helper that produces a new seed from the RNG state.
Expand Down
Loading
Loading