Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return components from symmetric encryptions #8

Merged
merged 3 commits into from
Feb 11, 2024
Merged
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
67 changes: 67 additions & 0 deletions native/src/seal/c/encryptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,73 @@ SEAL_C_FUNC Encryptor_EncryptSymmetric(
}
}

SEAL_C_FUNC Encryptor_EncryptSymmetricReturnComponents(
void *thisptr, void *plaintext, void *destination, void *e_destination,
void *remainder_destination, void *pool_handle)
{
Encryptor *encryptor = FromVoid<Encryptor>(thisptr);
IfNullRet(encryptor, E_POINTER);
Plaintext *plain = FromVoid<Plaintext>(plaintext);
IfNullRet(plain, E_POINTER);
Ciphertext *cipher = FromVoid<Ciphertext>(destination);
IfNullRet(cipher, E_POINTER);
PolynomialArray *e_dest = FromVoid<PolynomialArray>(e_destination);
IfNullRet(e_dest, E_POINTER);
Plaintext *r_dest = FromVoid<Plaintext>(remainder_destination);
IfNullRet(r_dest, E_POINTER);
unique_ptr<MemoryPoolHandle> pool = MemHandleFromVoid(pool_handle);

try
{
encryptor->encrypt_symmetric(*plain, *cipher, *e_dest, *r_dest, {}, *pool);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
}

SEAL_C_FUNC Encryptor_EncryptSymmetricReturnComponentsSetSeed(
void *thisptr, void *plaintext, void *destination, void *e_destination, void *remainder_destination, void *seed,
void *pool_handle)
{
Encryptor *encryptor = FromVoid<Encryptor>(thisptr);
IfNullRet(encryptor, E_POINTER);
Plaintext *plain = FromVoid<Plaintext>(plaintext);
IfNullRet(plain, E_POINTER);
Ciphertext *cipher = FromVoid<Ciphertext>(destination);
IfNullRet(cipher, E_POINTER);
PolynomialArray *e_dest = FromVoid<PolynomialArray>(e_destination);
IfNullRet(e_dest, E_POINTER);
Plaintext *r_dest = FromVoid<Plaintext>(remainder_destination);
IfNullRet(r_dest, E_POINTER);
std::array<std::uint64_t, prng_seed_uint64_count> *seed_array =
FromVoid<std::array<std::uint64_t, prng_seed_uint64_count>>(seed);
IfNullRet(seed_array, E_POINTER);
unique_ptr<MemoryPoolHandle> pool = MemHandleFromVoid(pool_handle);

auto seed_arr = std::optional<std::array<std::uint64_t, prng_seed_uint64_count>>{ *seed_array };

try
{
encryptor->encrypt_symmetric(*plain, *cipher, *e_dest, *r_dest, seed_arr, *pool);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
}

SEAL_C_FUNC Encryptor_EncryptZeroSymmetric1(
void *thisptr, uint64_t *parms_id, bool save_seed, void *destination, void *pool_handle)
{
Expand Down
6 changes: 6 additions & 0 deletions native/src/seal/c/encryptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ SEAL_C_FUNC Encryptor_EncryptZero2(void *thisptr, void *destination, void *pool_
SEAL_C_FUNC Encryptor_EncryptSymmetric(
void *thisptr, void *plaintext, bool save_seed, void *destination, void *pool_handle);

SEAL_C_FUNC Encryptor_EncryptSymmetricReturnComponents(
void *thisptr, void *plaintext, void *destination, void *e_destination, void *remainder_destination, void *pool_handle);

SEAL_C_FUNC Encryptor_EncryptSymmetricReturnComponentsSetSeed(
void *thisptr, void *plaintext, void *destination, void *e_destination, void *remainder_destination, void *seed, void *pool_handle);

SEAL_C_FUNC Encryptor_EncryptZeroSymmetric1(
void *thisptr, uint64_t *parms_id, bool save_seed, void *destination, void *pool_handle);

Expand Down
27 changes: 26 additions & 1 deletion native/src/seal/c/polyarray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,32 @@ SEAL_C_FUNC PolynomialArray_CreateFromPublicKey(void *memoryPoolHandle, void *co
}
}

SEAL_C_FUNC PolynomialArray_Copy(void *copy, void **poly_array) {
SEAL_C_FUNC PolynomialArray_CreateFromSecretKey(
void *memoryPoolHandle, void *context, void *secret_key, void **poly_array)
{
const SEALContext *ctx = FromVoid<SEALContext>(context);
IfNullRet(ctx, E_POINTER);

const SecretKey *sk = FromVoid<SecretKey>(secret_key);
IfNullRet(sk, E_POINTER);

IfNullRet(poly_array, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(memoryPoolHandle);

try
{
PolynomialArray *array = new PolynomialArray(*ctx, *sk, *handle);
*poly_array = array;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}

SEAL_C_FUNC PolynomialArray_Copy(void *copy, void **poly_array)
{
PolynomialArray *copyptr = FromVoid<PolynomialArray>(copy);
IfNullRet(copyptr, E_POINTER);
IfNullRet(poly_array, E_POINTER);
Expand Down
2 changes: 2 additions & 0 deletions native/src/seal/c/polyarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ SEAL_C_FUNC PolynomialArray_CreateFromCiphertext(void *memoryPoolHandle, void *c

SEAL_C_FUNC PolynomialArray_CreateFromPublicKey(void *memoryPoolHandle, void *context, void *public_key, void **poly_array);

SEAL_C_FUNC PolynomialArray_CreateFromSecretKey(void *memoryPoolHandle, void *context, void *secret_key, void **poly_array);

SEAL_C_FUNC PolynomialArray_Copy(void *copy, void **poly_array);

SEAL_C_FUNC PolynomialArray_Destroy(void *thisptr);
Expand Down
4 changes: 3 additions & 1 deletion native/src/seal/encryptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ namespace seal
parms_id,
is_ntt_form,
save_seed,
destination
export_components,
destination,
e_destination
);
}
}
Expand Down
40 changes: 40 additions & 0 deletions native/src/seal/encryptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,46 @@ namespace seal
encrypt_internal(plain, false, false, destination, pool);
}

/**
Encrypts a plaintext with the public key and stores the result in
destination. In addition, returns the e parameters from the
encryption.

The encryption parameters for the resulting ciphertext correspond to:
1) in BFV/BGV, the highest (data) level in the modulus switching chain,
2) in CKKS, the encryption parameters of the plaintext.
Dynamic memory allocations in the process are allocated from the memory
pool pointed to by the given MemoryPoolHandle.

@param[in] plain The plaintext to encrypt
@param[in] disable_special_modulus Whether to disable the special modulus.
Only applies to BFV.
@param[out] destination The ciphertext to overwrite with the encrypted
plaintext
@param[out] e_destination The polynomial array to write into with the e
parameter from BFV. This is required to be un-reserved when passed in.
@param[out] remainder_destination The polynomial array to write into with the rounding component from BFV.
Should be unreserved when passed in.
@param[in] pool The MemoryPoolHandle pointing to a valid memory pool
@throws std::logic_error if a public key is not set
@throws std::invalid_argument if plain is not valid for the encryption
parameters
@throws std::invalid_argument if plain is not in default NTT form
@throws std::invalid_argument if pool is uninitialized
*/
inline void encrypt_symmetric(
const Plaintext &plain, Ciphertext &destination, PolynomialArray &e_destination,
Plaintext &remainder_destination, std::optional<prng_seed_type> seed = std::nullopt,
MemoryPoolHandle pool = MemoryManager::GetPool()) const
{
// The u component isn't relevant for symmetric encryptions
PolynomialArray u_destination;

encrypt_internal(
plain, false, false, true, true, destination, u_destination, e_destination, remainder_destination, seed,
pool);
}

/**
Encrypts a plaintext with the secret key and returns the ciphertext as
a serializable object.
Expand Down
7 changes: 5 additions & 2 deletions native/src/seal/keygenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "seal/keygenerator.h"
#include "seal/randomtostd.h"
#include "seal/polyarray.h"
#include "seal/util/common.h"
#include "seal/util/galois.h"
#include "seal/util/ntt.h"
Expand Down Expand Up @@ -111,7 +112,8 @@ namespace seal
}

PublicKey public_key;
encrypt_zero_symmetric(secret_key_, context_, context_data.parms_id(), true, save_seed, public_key.data());
PolynomialArray e_destination;
encrypt_zero_symmetric(secret_key_, context_, context_data.parms_id(), true, save_seed, false, public_key.data(), e_destination);

// Set the parms_id for public key
public_key.parms_id() = context_data.parms_id();
Expand Down Expand Up @@ -319,11 +321,12 @@ namespace seal

// KSwitchKeys data allocated from pool given by MemoryManager::GetPool.
destination.resize(decomp_mod_count);
PolynomialArray e_destination;

SEAL_ITERATE(iter(new_key, key_modulus, destination, size_t(0)), decomp_mod_count, [&](auto I) {
SEAL_ALLOCATE_GET_COEFF_ITER(temp, coeff_count, pool_);
encrypt_zero_symmetric(
secret_key_, context_, key_context_data.parms_id(), true, save_seed, get<2>(I).data());
secret_key_, context_, key_context_data.parms_id(), true, save_seed, false, get<2>(I).data(), e_destination);
uint64_t factor = barrett_reduce_64(key_modulus.back().value(), get<1>(I));
multiply_poly_scalar_coeffmod(get<0>(I), coeff_count, factor, get<1>(I), temp);

Expand Down
32 changes: 31 additions & 1 deletion native/src/seal/polyarray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,41 @@ namespace seal
}
}

PolynomialArray::PolynomialArray(
const SEALContext &context,
const SecretKey &secret_key,
MemoryPoolHandle pool
) : PolynomialArray(pool) {

auto &pt = secret_key.data();
auto &parms = context.first_context_data()->parms();
auto &plain_modulus = parms.plain_modulus();
auto &coeff_modulus = parms.coeff_modulus();
auto coeff_modulus_size = coeff_modulus.size();
auto poly_modulus_degree = pt.coeff_count();

auto is_ntt_form = pt.is_ntt_form();
size_t coeff_count = parms.poly_modulus_degree();
auto &context_data = *context.get_context_data(parms.parms_id());
auto ntt_tables = context_data.small_ntt_tables();

reserve(1, poly_modulus_degree, {plain_modulus});

const auto data_ptr = pt.data();
insert_polynomial(0, data_ptr);

// Convert out of NTT form for each polynomial.
if (is_ntt_form) {
for (size_t i = 0; i < coeff_modulus_size; i++) {
inverse_ntt_negacyclic_harvey(get_polynomial(0) + i * coeff_count, ntt_tables[i]);
}
}
}

PolynomialArray::PolynomialArray(const PolynomialArray &copy): PolynomialArray(copy.pool_) {
// These parameters in the result object are internally stored once
// reserve is called.
auto poly_size = copy.poly_size();
auto coeff_modulus_size = copy.coeff_modulus_size();
auto coeff_modulus = copy.coeff_modulus_;
auto poly_modulus_degree = copy.poly_modulus_degree();

Expand Down
8 changes: 8 additions & 0 deletions native/src/seal/polyarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "seal/ciphertext.h"
#include "seal/memorymanager.h"
#include "seal/publickey.h"
#include "seal/secretkey.h"
#include <stdexcept>

using namespace seal::util;
Expand Down Expand Up @@ -45,6 +46,13 @@ namespace seal
const SEALContext &context, const PublicKey &public_key, MemoryPoolHandle pool
);

/**
Create a PolynomialArray from a secret key.
*/
PolynomialArray(
const SEALContext &context, const SecretKey &secret_key, MemoryPoolHandle pool
);

/**
Creates a new ciphertext by copying a given one.
Expand Down
24 changes: 12 additions & 12 deletions native/src/seal/util/rlwe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,7 @@ namespace seal
// = public_key[j] * u + p * e[j] in BGV
// where e[j] <-- chi, u <-- R_3

// Note: if you need to seed this encryption with a known value,
// then this code can be uncommented. Otherwise we do not actually
// use the seed if it is provided to ensure the library is not
// accidentally insecure.
// Note: if a seed is provided, encryption is deterministic and inherently insecure.
auto prng = seed.has_value() ? parms.random_generator()->create(seed.value())
: parms.random_generator()->create();

Expand Down Expand Up @@ -318,7 +315,9 @@ namespace seal
parms_id_type parms_id,
bool is_ntt_form,
bool save_seed,
bool export_components,
Ciphertext &destination,
PolynomialArray &e_destination,
optional<prng_seed_type> seed
)
{
Expand Down Expand Up @@ -360,18 +359,15 @@ namespace seal
destination.scale() = 1.0;
destination.correction_factor() = 1;

// Note: if you need to seed this encryption with a known value,
// then this code can be uncommented. Otherwise we do not actually
// use the seed if it is provided to ensure the library is not
// accidentally insecure.
// auto bootstrap_prng = seed.has_value()
// ? parms.random_generator()->create(seed.value())
// : parms.random_generator()->create();
// Note: if a seed is provided, encryption is deterministic and inherently insecure.
auto bootstrap_prng = seed.has_value()
? parms.random_generator()->create(seed.value())
: parms.random_generator()->create();
samtay marked this conversation as resolved.
Show resolved Hide resolved

// Create an instance of a random number generator. We use this for sampling
// a seed for a second PRNG used for sampling u (the seed can be public
// information. This PRNG is also used for sampling the noise/error below.
auto bootstrap_prng = parms.random_generator()->create();
// auto bootstrap_prng = parms.random_generator()->create();

// Sample a public seed for generating uniform randomness
prng_seed_type public_prng_seed;
Expand Down Expand Up @@ -405,6 +401,10 @@ namespace seal
// Sample e <-- chi
auto noise(allocate_poly(coeff_count, coeff_modulus_size, pool));
SEAL_NOISE_SAMPLER(bootstrap_prng, parms, noise.get());
if (export_components) {
e_destination.reserve(1, coeff_count, coeff_modulus);
e_destination.insert_polynomial(0, noise.get());
}

// Calculate -(as+ e) (mod q) and store in c[0] in BFV/CKKS
// Calculate -(as+pe) (mod q) and store in c[0] in BGV
Expand Down
4 changes: 4 additions & 0 deletions native/src/seal/util/rlwe.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,14 @@ namespace seal
Create an encryption of zero with a secret key and store in a ciphertext.

@param[out] destination The output ciphertext - an encryption of zero
@param[out] e The e component.
@param[in] secret_key The secret key used for encryption
@param[in] context The SEALContext containing a chain of ContextData
@param[in] parms_id Indicates the level of encryption
@param[in] is_ntt_form If true, store ciphertext in NTT form
@param[in] save_seed If true, the second component of ciphertext is
replaced with the random seed used to sample this component
@param[in] export_components Whether to export the ciphertext noise component (e_i)
@param[in] (Optional) Set seed for a deterministic encryption. NOTE:
while one can provide this parameter, it is currently disabled in the
encryption function. If you want to provide a seed, you will need to
Expand All @@ -134,7 +136,9 @@ namespace seal
parms_id_type parms_id,
bool is_ntt_form,
bool save_seed,
bool export_components,
Ciphertext &destination,
PolynomialArray &e_destination,
std::optional<prng_seed_type> seed = std::nullopt
);
} // namespace util
Expand Down
Loading