Progress on the SEAL BFV implementation

This commit is contained in:
York Jasper Niebuhr 2025-11-28 22:19:04 +01:00
parent 0893f6044c
commit fab47a227a
2 changed files with 74 additions and 31 deletions

View File

@ -13,33 +13,8 @@ namespace homcert::bfv {
constexpr std::size_t VECSIZE = 8192;
constexpr std::size_t PLAINMOD = 16760833; // 8192*2*1023+1 and prime
template<std::size_t N, typename = void>
struct smallest_uint;
template<std::size_t N>
struct smallest_uint<N, std::enable_if_t<(N <= UINT8_MAX)>> {
using type = std::uint8_t;
};
template<std::size_t N>
struct smallest_uint<N, std::enable_if_t<(UINT8_MAX < N && N <= UINT16_MAX)>> {
using type = std::uint16_t;
};
template<std::size_t N>
struct smallest_uint<N, std::enable_if_t<(UINT16_MAX < N && N <= UINT32_MAX)>> {
using type = std::uint32_t;
};
template<std::size_t N>
struct smallest_uint<N, std::enable_if_t<(UINT32_MAX < N)>> {
using type = std::uint64_t;
};
struct plaintext {
using coefficient = typename smallest_uint<PLAINMOD>::type;
std::array<coefficient, VECSIZE> coefficients;
std::array<std::uint64_t, VECSIZE> slots;
// Arithmetic...
};
@ -87,8 +62,8 @@ struct context {
virtual void new_components() = 0; // context default constructs empty
virtual void has_components(int& components) const = 0;
virtual void clone_components(int components, std::shared_ptr<context>& ptr) const = 0;
// virtual void dump_components(int components, void* buf, std::size_t& n) const = 0;
// virtual void load_components(int components, const void* buf, std::size_t n) = 0;
virtual void dump_components(int components, void* buf, std::size_t& n) const = 0;
virtual void load_components(const void* buf, std::size_t n) = 0;
virtual void allocate(ciphertext& ct) = 0;
virtual void free(ciphertext ct) = 0;
@ -123,6 +98,8 @@ struct seal_context : public context {
void new_components() override;
void has_components(int& components) const override;
void clone_components(int components, std::shared_ptr<context>& ptr) const override;
void dump_components(int components, void* buf, std::size_t& n) const override;
void load_components(const void* buf, std::size_t n) override;
void allocate(ciphertext& ct) override;
void free(ciphertext ct) override;
void serialize(ciphertext ct, void* buf, std::size_t& n) const override;

View File

@ -81,10 +81,25 @@ struct seal_context_data {
static minfree ctx_id_factory { 0 };
static std::unordered_map<int, seal_context_data> ctxs;
static seal::Plaintext encode_plaintext(const seal::BatchEncoder& encoder, const plaintext& pt) {
seal::Plaintext res;
try {
encoder.encode(gsl::span<const uint64_t>(pt.slots), res);
} catch (const std::exception& e) {
std::string what;
what += "Microsoft SEAL failed to encode data (";
what += e.what();
what += ")";
throw bfv_exception(bfv_exception::REASON::CTX_INTERNAL, what);
}
return std::move(res);
}
seal_context::seal_context() : context{}, m_id{ -1 } {
if (!seal_bfv_ctx || !seal_bfv_ctx->parameters_set())
throw bfv_exception(bfv_exception::REASON::CTX_INVALID,
"Missing Microsoft SEAL parameter context!");
return;
int tmp_id;
if (!ctx_id_factory.min(tmp_id))
@ -173,6 +188,24 @@ void seal_context::clone_components(int components, std::shared_ptr<context>& pt
// TODO
}
void seal_context::dump_components(int components, void* buf, std::size_t& n) const {
if (!ctxs.contains(m_id))
throw bfv_exception(bfv_exception::REASON::CTX_INVALID,
"Object does not hold a valid Microsoft SEAL context!");
seal_context_data& data = ctxs.at(m_id);
// TODO
}
void seal_context::load_components(const void* buf, std::size_t n) {
if (!ctxs.contains(m_id))
throw bfv_exception(bfv_exception::REASON::CTX_INVALID,
"Object does not hold a valid Microsoft SEAL context!");
seal_context_data& data = ctxs.at(m_id);
// TODO
}
void seal_context::allocate(ciphertext& ct) {
ct = -1;
@ -276,6 +309,8 @@ void seal_context::deserialize(ciphertext ct, const void* buf, std::size_t n) co
throw bfv_exception(bfv_exception::REASON::CTX_INTERNAL,
"Microsoft SEAL failed to deserialize the specified data!");
}
ctbuf.initialized = true;
}
void seal_context::encrypt(const plaintext& pt, ciphertext ct) const {
@ -284,7 +319,30 @@ void seal_context::encrypt(const plaintext& pt, ciphertext ct) const {
"Object does not hold a valid Microsoft SEAL context!");
seal_context_data& data = ctxs.at(m_id);
// TODO
if (!(data.components & PUBLIC_COMPONENT))
throw bfv_exception(bfv_exception::REASON::CTX_COMPONENT,
"Context does not hold required PUBLIC_COMPONENT!");
if (!data.ciphertexts.contains(ct))
throw bfv_exception(bfv_exception::REASON::CTX_INVALID_ARGUMENT,
"The specified ciphertext does not exist in this context!");
ct_buffer& ctbuf = data.ciphertexts.at(ct);
seal::Plaintext encoded = encode_plaintext(*data.pub.encoder, pt);
try {
data.pub.encryptor->encrypt(encoded, ctbuf.value);
} catch (const std::exception& e) {
std::string what;
what += "Microsoft SEAL failed to encrypt the given plaintext (";
what += e.what();
what += ")";
throw bfv_exception(bfv_exception::REASON::CTX_INTERNAL, what);
}
ctbuf.initialized = true;
}
void seal_context::decrypt(ciphertext ct, plaintext& pt) const {
@ -399,6 +457,14 @@ void seal_context::clone_components(int components, std::shared_ptr<context>& pt
throw bfv_exception(bfv_exception::REASON::CTX_NOT_IMPLEMENTED, "BFV context for Microsoft SEAL is not implemented");
}
void seal_context::dump_components(int components, void* buf, std::size_t& n) const {
throw bfv_exception(bfv_exception::REASON::CTX_NOT_IMPLEMENTED, "BFV context for Microsoft SEAL is not implemented");
}
void seal_context::load_components(const void* buf, std::size_t n) {
throw bfv_exception(bfv_exception::REASON::CTX_NOT_IMPLEMENTED, "BFV context for Microsoft SEAL is not implemented");
}
void seal_context::allocate(ciphertext& ct) {
throw bfv_exception(bfv_exception::REASON::CTX_NOT_IMPLEMENTED, "BFV context for Microsoft SEAL is not implemented");
}