refactor(tfhe): transition GlweSecretKey

- serialization work still pending
This commit is contained in:
Arthur Meyre
2022-11-18 16:47:44 +01:00
committed by jborfila
parent 3185310610
commit 120e7b5a6b
12 changed files with 195 additions and 20 deletions

View File

@@ -0,0 +1,36 @@
use crate::core_crypto::commons::crypto::secret::generators::SecretRandomGenerator;
use crate::core_crypto::commons::math::random::{
ByteRandomGenerator, RandomGenerable, UniformBinary,
};
use crate::core_crypto::commons::numeric::Numeric;
use crate::core_crypto::commons::traits::ContainerMut;
use crate::core_crypto::entities::glwe_secret_key::{GlweSecretKey, GlweSecretKeyBase};
use crate::core_crypto::specification::parameters::{GlweDimension, PolynomialSize};
pub fn allocate_and_generate_new_binary_glwe_secret_key<Scalar, Gen>(
glwe_dimension: GlweDimension,
polynomial_size: PolynomialSize,
generator: &mut SecretRandomGenerator<Gen>,
) -> GlweSecretKey<Scalar>
where
Scalar: RandomGenerable<UniformBinary> + Numeric,
Gen: ByteRandomGenerator,
{
let mut glwe_secret_key =
GlweSecretKey::from_container(vec![Scalar::ZERO; glwe_dimension.0], polynomial_size);
generate_binary_glwe_secret_key(&mut glwe_secret_key, generator);
glwe_secret_key
}
pub fn generate_binary_glwe_secret_key<Scalar, InCont, Gen>(
glwe_secret_key: &mut GlweSecretKeyBase<InCont>,
generator: &mut SecretRandomGenerator<Gen>,
) where
Scalar: RandomGenerable<UniformBinary>,
InCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
generator.fill_slice_with_random_uniform_binary(glwe_secret_key.as_mut())
}

View File

@@ -0,0 +1,34 @@
use crate::core_crypto::commons::crypto::secret::generators::SecretRandomGenerator;
use crate::core_crypto::commons::math::random::{
ByteRandomGenerator, RandomGenerable, UniformBinary,
};
use crate::core_crypto::commons::numeric::Numeric;
use crate::core_crypto::commons::traits::ContainerMut;
use crate::core_crypto::entities::lwe_secret_key::{LweSecretKey, LweSecretKeyBase};
use crate::core_crypto::specification::parameters::LweDimension;
pub fn allocate_and_generate_new_binary_lwe_secret_key<Scalar, Gen>(
lwe_dimension: LweDimension,
generator: &mut SecretRandomGenerator<Gen>,
) -> LweSecretKey<Scalar>
where
Scalar: RandomGenerable<UniformBinary> + Numeric,
Gen: ByteRandomGenerator,
{
let mut lwe_secret_key = LweSecretKey::from_container(vec![Scalar::ZERO; lwe_dimension.0]);
generate_binary_lwe_secret_key(&mut lwe_secret_key, generator);
lwe_secret_key
}
pub fn generate_binary_lwe_secret_key<Scalar, InCont, Gen>(
lwe_secret_key: &mut LweSecretKeyBase<InCont>,
generator: &mut SecretRandomGenerator<Gen>,
) where
Scalar: RandomGenerable<UniformBinary>,
InCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
generator.fill_slice_with_random_uniform_binary(lwe_secret_key.as_mut())
}

View File

@@ -1,3 +1,5 @@
pub mod glwe_secret_key_generation;
pub mod lwe_encryption;
pub mod lwe_linear_algebra;
pub mod lwe_secret_key_generation;
pub mod slice_algorithms;

View File

@@ -49,6 +49,12 @@ impl DefaultEngine {
) -> &mut ImplEncryptionRandomGenerator<ActivatedRandomGenerator> {
&mut self.encryption_generator
}
pub fn get_secret_generator(
&mut self,
) -> &mut ImplSecretRandomGenerator<ActivatedRandomGenerator> {
&mut self.secret_generator
}
}
impl AbstractEngine for DefaultEngine {

View File

@@ -1,5 +1,5 @@
use crate::core_crypto::commons::math::random::{
ByteRandomGenerator, Gaussian, RandomGenerable, RandomGenerator, Seed,
ByteRandomGenerator, Gaussian, RandomGenerable, RandomGenerator, Seed, UniformBinary,
};
use crate::core_crypto::commons::math::tensor::Tensor;
use crate::core_crypto::commons::math::torus::UnsignedTorus;
@@ -52,4 +52,11 @@ impl<G: ByteRandomGenerator> SecretRandomGenerator<G> {
self.0
.random_gaussian_tensor(length, 0.0, Scalar::GAUSSIAN_KEY_LOG_STD.get_standard_dev())
}
pub(crate) fn fill_slice_with_random_uniform_binary<Scalar>(&mut self, slice: &mut [Scalar])
where
Scalar: RandomGenerable<UniformBinary>,
{
self.0.fill_slice_with_random_uniform_binary(slice);
}
}

View File

@@ -252,6 +252,13 @@ impl<G: ByteRandomGenerator> RandomGenerator<G> {
Scalar::fill_tensor(self, UniformBinary, output);
}
pub fn fill_slice_with_random_uniform_binary<Scalar>(&mut self, output: &mut [Scalar])
where
Scalar: RandomGenerable<UniformBinary>,
{
Scalar::fill_slice(self, UniformBinary, output);
}
/// Generates a tensor of random binary values of a given size.
///
/// # Example

View File

@@ -0,0 +1,75 @@
use crate::core_crypto::commons::traits::{Container, ContainerMut};
use crate::core_crypto::entities::lwe_secret_key::LweSecretKeyBase;
use crate::core_crypto::specification::parameters::{GlweDimension, PolynomialSize};
#[derive(Clone, Debug, PartialEq)]
pub struct GlweSecretKeyBase<C: Container> {
data: C,
polynomial_size: PolynomialSize,
}
impl<T, C: Container<Element = T>> AsRef<[T]> for GlweSecretKeyBase<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweSecretKeyBase<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
impl<Scalar, C: Container<Element = Scalar>> GlweSecretKeyBase<C> {
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> Self {
assert!(
container.container_len() % polynomial_size.0 == 0,
"The provided container length is not valid. \
It needs to be dividable by polynomial_size. \
Got container length: {} and polynomial_size: {polynomial_size:?}",
container.container_len()
);
GlweSecretKeyBase {
data: container,
polynomial_size,
}
}
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
pub fn glwe_dimension(&self) -> GlweDimension {
GlweDimension(self.data.container_len() / self.polynomial_size.0)
}
pub fn into_lwe_secret_key(self) -> LweSecretKeyBase<C> {
LweSecretKeyBase::from_container(self.data)
}
}
pub type GlweSecretKey<Scalar> = GlweSecretKeyBase<Vec<Scalar>>;
// TODO REFACTOR
// Remove the back and forth conversions
impl From<GlweSecretKey<u64>> for crate::core_crypto::prelude::GlweSecretKey64 {
fn from(new_glwe_secret_key: GlweSecretKey<u64>) -> Self {
use crate::core_crypto::commons::crypto::secret::GlweSecretKey as PrivateGlweSecretKey;
use crate::core_crypto::prelude::GlweSecretKey64;
GlweSecretKey64(PrivateGlweSecretKey::binary_from_container(
new_glwe_secret_key.data,
new_glwe_secret_key.polynomial_size,
))
}
}
impl From<crate::core_crypto::prelude::GlweSecretKey64> for GlweSecretKey<u64> {
fn from(old_glwe_secret_key: crate::core_crypto::prelude::GlweSecretKey64) -> Self {
use crate::core_crypto::commons::math::tensor::IntoTensor;
let polynomial_size = old_glwe_secret_key.0.polynomial_size();
GlweSecretKey::<u64>::from_container(
old_glwe_secret_key.0.into_tensor().into_container(),
polynomial_size,
)
}
}

View File

@@ -1,4 +1,5 @@
pub mod cleartext;
pub mod encoded;
pub mod glwe_secret_key;
pub mod lwe_ciphertext;
pub mod lwe_secret_key;

View File

@@ -1,5 +1,6 @@
//! Module with the definition of the ClientKey.
use crate::core_crypto::entities::glwe_secret_key::GlweSecretKey;
use crate::core_crypto::entities::lwe_secret_key::LweSecretKey;
use crate::core_crypto::prelude::*;
use crate::shortint::ciphertext::Ciphertext;
@@ -20,7 +21,7 @@ use std::fmt::Debug;
pub struct ClientKey {
/// The actual encryption / decryption key
pub(crate) lwe_secret_key: LweSecretKey<u64>,
pub(crate) glwe_secret_key: GlweSecretKey64,
pub(crate) glwe_secret_key: GlweSecretKey<u64>,
/// Key used as the output of the keyswitch operation
pub(crate) lwe_secret_key_after_ks: LweSecretKey<u64>,
pub parameters: Parameters,
@@ -341,11 +342,13 @@ impl Serialize for ClientKey {
let tmp_lwe_secret_key_after_ks: LweSecretKey64 =
self.lwe_secret_key_after_ks.clone().into();
let tmp_glwe_secret_key: GlweSecretKey64 = self.glwe_secret_key.clone().into();
let lwe_secret_key = ser_eng
.serialize(&tmp_lwe_secret_key)
.map_err(serde::ser::Error::custom)?;
let glwe_secret_key = ser_eng
.serialize(&self.glwe_secret_key)
.serialize(&tmp_glwe_secret_key)
.map_err(serde::ser::Error::custom)?;
let lwe_secret_key_after_ks = ser_eng
.serialize(&tmp_lwe_secret_key_after_ks)
@@ -379,11 +382,13 @@ impl<'de> Deserialize<'de> for ClientKey {
.deserialize(thing.lwe_secret_key_after_ks.as_slice())
.map_err(serde::de::Error::custom)?;
let tmp_glwe_secret_key: GlweSecretKey64 = de_eng
.deserialize(thing.glwe_secret_key.as_slice())
.map_err(serde::de::Error::custom)?;
Ok(Self {
lwe_secret_key: tmp_lwe_secret_key.into(),
glwe_secret_key: de_eng
.deserialize(thing.glwe_secret_key.as_slice())
.map_err(serde::de::Error::custom)?,
glwe_secret_key: tmp_glwe_secret_key.into(),
lwe_secret_key_after_ks: tmp_lwe_secret_key_after_ks.into(),
parameters: thing.parameters,
})

View File

@@ -1,10 +1,11 @@
//! All the `ShortintEngine` method related to client side (encrypt / decrypt)
use super::{EngineResult, ShortintEngine};
use crate::core_crypto::algorithms::glwe_secret_key_generation::allocate_and_generate_new_binary_glwe_secret_key;
use crate::core_crypto::algorithms::lwe_encryption::{
allocate_and_encrypt_new_lwe_ciphertext, decrypt_lwe_ciphertext,
};
use crate::core_crypto::algorithms::lwe_secret_key_generation::allocate_and_generate_new_binary_lwe_secret_key;
use crate::core_crypto::entities::encoded::Encoded;
use crate::core_crypto::prelude::*;
use crate::shortint::ciphertext::Degree;
use crate::shortint::parameters::{CarryModulus, MessageModulus};
use crate::shortint::{Ciphertext, ClientKey, Parameters};
@@ -12,24 +13,25 @@ use crate::shortint::{Ciphertext, ClientKey, Parameters};
impl ShortintEngine {
pub fn new_client_key(&mut self, parameters: Parameters) -> EngineResult<ClientKey> {
// generate the lwe secret key
let small_lwe_secret_key: LweSecretKey64 = self
.engine
.generate_new_lwe_secret_key(parameters.lwe_dimension)?;
let small_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
parameters.lwe_dimension,
self.engine.get_secret_generator(),
);
// generate the rlwe secret key
let glwe_secret_key: GlweSecretKey64 = self
.engine
.generate_new_glwe_secret_key(parameters.glwe_dimension, parameters.polynomial_size)?;
let glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
parameters.glwe_dimension,
parameters.polynomial_size,
self.engine.get_secret_generator(),
);
let large_lwe_secret_key = self
.engine
.transform_glwe_secret_key_to_lwe_secret_key(glwe_secret_key.clone())?;
let large_lwe_secret_key = glwe_secret_key.clone().into_lwe_secret_key();
// pack the keys in the client key set
Ok(ClientKey {
lwe_secret_key: large_lwe_secret_key.into(),
lwe_secret_key: large_lwe_secret_key,
glwe_secret_key,
lwe_secret_key_after_ks: small_lwe_secret_key.into(),
lwe_secret_key_after_ks: small_lwe_secret_key,
parameters,
})
}

View File

@@ -44,7 +44,7 @@ impl ShortintEngine {
// Remove the clone + into
let bootstrap_key: LweBootstrapKey64 = self.par_engine.generate_new_lwe_bootstrap_key(
&cks.lwe_secret_key_after_ks.clone().into(),
&cks.glwe_secret_key,
&cks.glwe_secret_key.clone().into(),
cks.parameters.pbs_base_log,
cks.parameters.pbs_level,
var_rlwe,

View File

@@ -23,7 +23,7 @@ impl ShortintEngine {
.engine
.generate_new_lwe_circuit_bootstrap_private_functional_packing_keyswitch_keys(
&cks.lwe_secret_key.clone().into(),
&cks.glwe_secret_key,
&cks.glwe_secret_key.clone().into(),
cks.parameters.pfks_base_log,
cks.parameters.pfks_level,
Variance(cks.parameters.pfks_modular_std_dev.get_variance()),