refactor(tfhe): add GGSW encryption with coherency test between old and new

This commit is contained in:
Arthur Meyre
2022-11-24 16:45:46 +01:00
committed by jborfila
parent 07f496ac23
commit d0d0b542ac
26 changed files with 1439 additions and 41 deletions

View File

@@ -0,0 +1,224 @@
use crate::core_crypto::algorithms::slice_algorithms::*;
use crate::core_crypto::algorithms::*;
use crate::core_crypto::commons::crypto::secret::generators::EncryptionRandomGenerator;
use crate::core_crypto::commons::math::decomposition::DecompositionLevel;
use crate::core_crypto::commons::math::random::ByteRandomGenerator;
use crate::core_crypto::commons::math::torus::UnsignedTorus;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::dispersion::DispersionParameter;
pub fn encrypt_ggsw_ciphertext<Scalar, KeyCont, OutputCont, Gen>(
glwe_secret_key: &GlweSecretKeyBase<KeyCont>,
output: &mut GgswCiphertextBase<OutputCont>,
encoded: Plaintext<Scalar>,
noise_parameters: impl DispersionParameter,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: UnsignedTorus,
Gen: ByteRandomGenerator,
KeyCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
{
// ck_dim_eq!(self.key_size() => output.glwe_size().to_glwe_dimension());
assert!(
output.polynomial_size() == glwe_secret_key.polynomial_size(),
"Mismatch between polynomial sizes of output cipertexts and input secret key. \
Got {:?} in output, and {:?} in secret key.",
output.polynomial_size(),
glwe_secret_key.polynomial_size()
);
assert!(
output.glwe_size().to_glwe_dimension() == glwe_secret_key.glwe_dimension(),
"Mismatch between GlweDimension of output cipertexts and input secret key. \
Got {:?} in output, and {:?} in secret key.",
output.glwe_size().to_glwe_dimension(),
glwe_secret_key.glwe_dimension()
);
// Generators used to have same sequential and parallel key generation
let gen_iter = generator
.fork_ggsw_to_ggsw_levels::<Scalar>(
output.decomposition_level_count(),
output.glwe_size(),
output.polynomial_size(),
)
.expect("Failed to split generator into ggsw levels");
let output_glwe_size = output.glwe_size();
let output_polynomial_size = output.polynomial_size();
let decomp_base_log = output.decomposition_base_log();
for (level_index, (mut level_matrix, mut generator)) in
output.iter_mut().zip(gen_iter).enumerate()
{
let decomp_level = DecompositionLevel(level_index + 1);
let factor = encoded
.0
.wrapping_neg()
.wrapping_mul(Scalar::ONE << (Scalar::BITS - (decomp_base_log.0 * decomp_level.0)));
// We iterate over the rows of the level matrix, the last row needs special treatment
let gen_iter = generator
.fork_ggsw_level_to_glwe::<Scalar>(output_glwe_size, output_polynomial_size)
.expect("Failed to split generator into glwe");
let last_row_index = level_matrix.glwe_size().0 - 1;
let sk_poly_list = glwe_secret_key.as_polynomial_list();
for ((row_index, mut row_as_glwe), mut generator) in level_matrix
.as_mut_glwe_list()
.iter_mut()
.enumerate()
.zip(gen_iter)
{
encrypt_ggsw_level_matrix_row(
glwe_secret_key,
(row_index, last_row_index),
factor,
&sk_poly_list,
&mut row_as_glwe,
noise_parameters,
&mut generator,
);
}
}
}
fn encrypt_ggsw_level_matrix_row<Scalar, KeyCont, InputCont, OutputCont, Gen>(
glwe_secret_key: &GlweSecretKeyBase<KeyCont>,
(row_index, last_row_index): (usize, usize),
factor: Scalar,
sk_poly_list: &PolynomialListBase<InputCont>,
row_as_glwe: &mut GlweCiphertextBase<OutputCont>,
noise_parameters: impl DispersionParameter,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: UnsignedTorus,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
if row_index < last_row_index {
// Not the last row
let sk_poly = sk_poly_list.get(row_index);
// Copy the key polynomial to the output body, to avoid allocating a temporary buffer
let mut body = row_as_glwe.get_mut_body();
body.as_mut().copy_from_slice(sk_poly.as_ref());
update_with_wrapping_scalar_mul(body.as_mut(), factor);
encrypt_glwe_ciphertext_in_place(glwe_secret_key, row_as_glwe, noise_parameters, generator);
} else {
// The last row needs a slightly different treatment
let mut body = row_as_glwe.get_mut_body();
body.as_mut().fill(Scalar::ZERO);
body.as_mut()[0] = factor.wrapping_neg();
encrypt_glwe_ciphertext_in_place(glwe_secret_key, row_as_glwe, noise_parameters, generator);
}
}
#[cfg(test)]
mod test {
use crate::core_crypto::algorithms::encrypt_ggsw_ciphertext;
use crate::core_crypto::commons::crypto::encoding::PlaintextList;
use crate::core_crypto::commons::crypto::secret::generators::{
DeterministicSeeder, EncryptionRandomGenerator,
};
use crate::core_crypto::commons::crypto::secret::GlweSecretKey;
use crate::core_crypto::commons::math::random::Seeder;
use crate::core_crypto::commons::math::tensor::*;
use crate::core_crypto::commons::math::torus::UnsignedTorus;
use crate::core_crypto::commons::test_tools;
use crate::core_crypto::entities::{GgswCiphertext, GlweSecretKeyBase, Plaintext};
use crate::core_crypto::prelude::{
DecompositionBaseLog, DecompositionLevelCount, LogStandardDev,
};
use concrete_csprng::generators::SoftwareRandomGenerator;
use crate::core_crypto::commons::crypto::ggsw::StandardGgswCiphertext;
fn test_refactored_ggsw<T: UnsignedTorus>() {
// random settings
let nb_ct = test_tools::random_ciphertext_count(10);
let dimension = test_tools::random_glwe_dimension(5);
let polynomial_size = test_tools::random_polynomial_size(200);
let noise_parameters = LogStandardDev::from_log_standard_dev(-50.);
let decomp_level = DecompositionLevelCount(3);
let decomp_base_log = DecompositionBaseLog(7);
let mut secret_generator = test_tools::new_secret_random_generator();
// generates a secret key
let sk = GlweSecretKey::generate_binary(dimension, polynomial_size, &mut secret_generator);
// generates random plaintexts
let plaintext_vector =
PlaintextList::from_tensor(secret_generator.random_uniform_tensor::<T>(nb_ct.0));
for plaintext in plaintext_vector.plaintext_iter() {
let main_seed = test_tools::random_seed();
// Use a deterministic seeder to get the seeds that will be used during the tests
let mut deterministic_seeder =
DeterministicSeeder::<SoftwareRandomGenerator>::new(main_seed);
let _ = deterministic_seeder.seed();
let mask_seed = deterministic_seeder.seed();
let mut generator = EncryptionRandomGenerator::<SoftwareRandomGenerator>::new(
mask_seed,
&mut DeterministicSeeder::<SoftwareRandomGenerator>::new(main_seed),
);
let mut refactored_ggsw = GgswCiphertext::new(
T::ZERO,
dimension.to_glwe_size(),
polynomial_size,
decomp_base_log,
decomp_level,
);
encrypt_ggsw_ciphertext(
&GlweSecretKeyBase::from_container(sk.as_tensor().as_slice(), polynomial_size),
&mut refactored_ggsw,
Plaintext(plaintext.0),
noise_parameters,
&mut generator,
);
// control encryption
let mut ggsw = StandardGgswCiphertext::allocate(
T::ZERO,
polynomial_size,
dimension.to_glwe_size(),
decomp_level,
decomp_base_log,
);
// Recreate a generator with the known mask seed
let mut generator = EncryptionRandomGenerator::<SoftwareRandomGenerator>::new(
mask_seed,
&mut DeterministicSeeder::<SoftwareRandomGenerator>::new(main_seed),
);
sk.encrypt_constant_ggsw(&mut ggsw, plaintext, noise_parameters, &mut generator);
assert_eq!(refactored_ggsw.as_ref(), ggsw.as_tensor().as_slice());
}
}
#[test]
fn test_refactored_ggsw_u32() {
test_refactored_ggsw::<u32>()
}
#[test]
fn test_refactored_ggsw_u64() {
test_refactored_ggsw::<u64>()
}
}

View File

@@ -0,0 +1,46 @@
use crate::core_crypto::algorithms::polynomial_algorithms::*;
use crate::core_crypto::commons::crypto::secret::generators::EncryptionRandomGenerator;
use crate::core_crypto::commons::math::random::ByteRandomGenerator;
use crate::core_crypto::commons::math::torus::UnsignedTorus;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::dispersion::DispersionParameter;
pub fn encrypt_glwe_ciphertext_in_place<Scalar, KeyCont, OutputCont, Gen>(
glwe_secret_key: &GlweSecretKeyBase<KeyCont>,
output: &mut GlweCiphertextBase<OutputCont>,
noise_parameters: impl DispersionParameter,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: UnsignedTorus,
KeyCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
assert!(
output.glwe_size().to_glwe_dimension() == glwe_secret_key.glwe_dimension(),
"Mismatch between GlweDimension of output cipertext and input secret key. \
Got {:?} in output, and {:?} in secret key.",
output.glwe_size().to_glwe_dimension(),
glwe_secret_key.glwe_dimension()
);
assert!(
output.polynomial_size() == glwe_secret_key.polynomial_size(),
"Mismatch between PolynomialSize of output cipertext and input secret key. \
Got {:?} in output, and {:?} in secret key.",
output.polynomial_size(),
glwe_secret_key.polynomial_size()
);
let (mut mask, mut body) = output.get_mut_mask_and_body();
generator.fill_slice_with_random_mask(mask.as_mut());
generator.update_slice_with_wrapping_add_random_noise(body.as_mut(), noise_parameters);
update_polynomial_with_wrapping_add_multisum(
&mut body.as_mut_polynomial(),
&mask.as_polynomial_list(),
&glwe_secret_key.as_polynomial_list(),
);
}

View File

@@ -5,7 +5,7 @@ use crate::core_crypto::commons::math::random::{
use crate::core_crypto::commons::numeric::Numeric;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::{GlweDimension, PolynomialSize};
use crate::core_crypto::specification::parameters::*;
pub fn allocate_and_generate_new_binary_glwe_secret_key<Scalar, Gen>(
glwe_dimension: GlweDimension,

View File

@@ -8,7 +8,7 @@ use crate::core_crypto::commons::numeric::UnsignedInteger;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::dispersion::DispersionParameter;
use crate::core_crypto::specification::parameters::LweSize;
use crate::core_crypto::specification::parameters::*;
pub fn encrypt_lwe_ciphertext<Scalar, KeyCont, OutputCont, Gen>(
lwe_secret_key: &LweSecretKeyBase<KeyCont>,
@@ -22,6 +22,14 @@ pub fn encrypt_lwe_ciphertext<Scalar, KeyCont, OutputCont, Gen>(
OutputCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
assert!(
output.lwe_size().to_lwe_dimension() == lwe_secret_key.lwe_dimension(),
"Mismatch between LweDimension of output cipertext and input secret key. \
Got {:?} in output, and {:?} in secret key.",
output.lwe_size().to_lwe_dimension(),
lwe_secret_key.lwe_dimension()
);
let (mut mask, body) = output.get_mut_mask_and_body();
generator.fill_slice_with_random_mask(mask.as_mut());
@@ -97,6 +105,14 @@ where
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
{
assert!(
lwe_ciphertext.lwe_size().to_lwe_dimension() == lwe_secret_key.lwe_dimension(),
"Mismatch between LweDimension of output cipertext and input secret key. \
Got {:?} in output, and {:?} in secret key.",
lwe_ciphertext.lwe_size().to_lwe_dimension(),
lwe_secret_key.lwe_dimension()
);
let (mask, body) = lwe_ciphertext.get_mask_and_body();
Plaintext(

View File

@@ -6,9 +6,7 @@ use crate::core_crypto::commons::math::torus::UnsignedTorus;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::dispersion::DispersionParameter;
use crate::core_crypto::specification::parameters::{
DecompositionBaseLog, DecompositionLevelCount, PlaintextCount,
};
use crate::core_crypto::specification::parameters::*;
pub fn generate_binary_binary_lwe_keyswitch_key<
Scalar,

View File

@@ -44,7 +44,7 @@ pub fn lwe_ciphertext_in_place_cleartext_multiplication<Scalar, InCont>(
Scalar: UnsignedInteger,
InCont: ContainerMut<Element = Scalar>,
{
update_with_scalar_wrapping_mul(lhs.as_mut(), rhs.0);
update_with_wrapping_scalar_mul(lhs.as_mut(), rhs.0);
}
pub fn lwe_ciphertext_in_place_subtraction<Scalar, LhsCont, RhsCont>(

View File

@@ -5,7 +5,7 @@ use crate::core_crypto::commons::math::random::{
use crate::core_crypto::commons::numeric::Numeric;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::LweDimension;
use crate::core_crypto::specification::parameters::*;
pub fn allocate_and_generate_new_binary_lwe_secret_key<Scalar, Gen>(
lwe_dimension: LweDimension,

View File

@@ -1,13 +1,18 @@
pub mod ggsw_encryption;
pub mod glwe_encryption;
pub mod glwe_secret_key_generation;
pub mod lwe_ciphertext_keyswitch;
pub mod lwe_encryption;
pub mod lwe_keyswitch_key_generation;
pub mod lwe_linear_algebra;
pub mod lwe_secret_key_generation;
pub mod polynomial_algorithms;
pub mod slice_algorithms;
// No pub use for slice algorithms which would not interest higher level users
// No pub use for slice and polynomial algorithms which would not interest higher level users
// They can still be used via `use crate::core_crypto::algorithms::slice_algorithms::*;`
pub use ggsw_encryption::*;
pub use glwe_encryption::*;
pub use glwe_secret_key_generation::*;
pub use lwe_ciphertext_keyswitch::*;
pub use lwe_encryption::*;

View File

@@ -0,0 +1,62 @@
use crate::core_crypto::commons::numeric::UnsignedInteger;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
pub fn update_polynomial_with_wrapping_add_multisum<Scalar, OutputCont, InputCont1, InputCont2>(
output: &mut PolynomialBase<OutputCont>,
poly_list_1: &PolynomialListBase<InputCont1>,
poly_list_2: &PolynomialListBase<InputCont2>,
) where
Scalar: UnsignedInteger,
OutputCont: ContainerMut<Element = Scalar>,
InputCont1: Container<Element = Scalar>,
InputCont2: Container<Element = Scalar>,
{
for (poly_1, poly_2) in poly_list_1.iter().zip(poly_list_2.iter()) {
update_polynomial_with_wrapping_add_mul(output, &poly_1, &poly_2);
}
}
pub fn update_polynomial_with_wrapping_add_mul<Scalar, OutputCont, InputCont1, InputCont2>(
output: &mut PolynomialBase<OutputCont>,
lhs: &PolynomialBase<InputCont1>,
rhs: &PolynomialBase<InputCont2>,
) where
Scalar: UnsignedInteger,
OutputCont: ContainerMut<Element = Scalar>,
InputCont1: Container<Element = Scalar>,
InputCont2: Container<Element = Scalar>,
{
assert!(
output.polynomial_size() == lhs.polynomial_size(),
"Output polynomial size {:?} is not the same as input lhs polynomial {:?}.",
output.polynomial_size(),
lhs.polynomial_size(),
);
assert!(
output.polynomial_size() == rhs.polynomial_size(),
"Output polynomial size {:?} is not the same as input rhs polynomial {:?}.",
output.polynomial_size(),
rhs.polynomial_size(),
);
let degree = output.degree();
let polynomial_size = output.polynomial_size();
for (lhs_degree, &lhs_coeff) in lhs.iter().enumerate() {
for (rhs_degree, &rhs_coeff) in rhs.iter().enumerate() {
let target_degree = lhs_degree + rhs_degree;
if target_degree <= degree {
let output_coefficient = &mut output.as_mut()[target_degree];
*output_coefficient =
(*output_coefficient).wrapping_add(lhs_coeff.wrapping_mul(rhs_coeff));
} else {
let target_degree = target_degree % polynomial_size.0;
let output_coefficient = &mut output.as_mut()[target_degree];
*output_coefficient =
(*output_coefficient).wrapping_sub(lhs_coeff.wrapping_mul(rhs_coeff));
}
}
}
}

View File

@@ -77,7 +77,7 @@ where
.for_each(|elt| *elt = (*elt).wrapping_neg());
}
pub fn update_with_scalar_wrapping_mul<Scalar>(lhs: &mut [Scalar], rhs: Scalar)
pub fn update_with_wrapping_scalar_mul<Scalar>(lhs: &mut [Scalar], rhs: Scalar)
where
Scalar: UnsignedInteger,
{

View File

@@ -4,6 +4,7 @@ use crate::core_crypto::commons::math::random::{
ByteRandomGenerator, Gaussian, RandomGenerable, RandomGenerator, Seed, Seeder, Uniform,
};
use crate::core_crypto::commons::math::tensor::AsMutTensor;
use crate::core_crypto::commons::math::torus::UnsignedTorus;
use crate::core_crypto::commons::numeric::UnsignedInteger;
use crate::core_crypto::prelude::{
@@ -202,6 +203,22 @@ impl<G: ByteRandomGenerator> EncryptionRandomGenerator<G> {
self.noise
.fill_tensor_with_random_gaussian(output, 0., std.get_standard_dev());
}
// Adds noise on top of existing data for in place encryption
pub(crate) fn update_slice_with_wrapping_add_random_noise<Scalar>(
&mut self,
output: &mut [Scalar],
std: impl DispersionParameter,
) where
Scalar: UnsignedTorus,
(Scalar, Scalar): RandomGenerable<Gaussian<f64>>,
{
self.noise.update_slice_with_wrapping_add_random_gaussian(
output,
0.,
std.get_standard_dev(),
);
}
}
#[cfg(feature = "__commons_parallel")]

View File

@@ -3,6 +3,7 @@ use crate::core_crypto::commons::math::random::{
UniformWithZeros,
};
use crate::core_crypto::commons::math::tensor::{AsMutSlice, AsMutTensor, Tensor};
use crate::core_crypto::commons::math::torus::UnsignedTorus;
use crate::core_crypto::commons::numeric::{FloatingPoint, Numeric};
use concrete_csprng::generators::{BytesPerChild, ChildrenCount, ForkError};
#[cfg(feature = "__commons_parallel")]
@@ -622,6 +623,27 @@ impl<G: ByteRandomGenerator> RandomGenerator<G> {
});
}
pub fn update_slice_with_wrapping_add_random_gaussian<Float, Scalar>(
&mut self,
output: &mut [Scalar],
mean: Float,
std: Float,
) where
Scalar: UnsignedTorus,
Float: FloatingPoint,
(Scalar, Scalar): RandomGenerable<Gaussian<Float>>,
{
output.chunks_mut(2).for_each(|s| {
let (g1, g2) = <(Scalar, Scalar)>::generate_one(self, Gaussian { std, mean });
if let Some(elem) = s.get_mut(0) {
*elem = (*elem).wrapping_add(g1);
}
if let Some(elem) = s.get_mut(1) {
*elem = (*elem).wrapping_add(g2);
}
});
}
/// Generates a new tensor of floating point values, randomly sampled from a gaussian
/// distribution:
///

View File

@@ -179,51 +179,44 @@ pub mod test_tools {
/// Returns a random plaintext count in [1;max].
pub fn random_plaintext_count(max: usize) -> PlaintextCount {
assert_ne!(max, 0, "Max cannot be 0");
let mut rng = rand::thread_rng();
PlaintextCount((rng.gen::<usize>() % (max - 1)) + 1)
let max = std::cmp::max(2, max);
PlaintextCount(random_usize_between(1..max + 1))
}
/// Returns a random ciphertext count in [1;max].
pub fn random_ciphertext_count(max: usize) -> CiphertextCount {
assert_ne!(max, 0, "Max cannot be 0");
let mut rng = rand::thread_rng();
CiphertextCount((rng.gen::<usize>() % (max - 1)) + 1)
let max = std::cmp::max(2, max);
CiphertextCount(random_usize_between(1..max + 1))
}
/// Returns a random LWE dimension in [1;max].
pub fn random_lwe_dimension(max: usize) -> LweDimension {
assert_ne!(max, 0, "Max cannot be 0");
let mut rng = rand::thread_rng();
LweDimension((rng.gen::<usize>() % (max - 1)) + 1)
let max = std::cmp::max(2, max);
LweDimension(random_usize_between(1..max + 1))
}
/// Returns a random GLWE dimension in [1;max].
pub fn random_glwe_dimension(max: usize) -> GlweDimension {
assert_ne!(max, 0, "Max cannot be 0");
let mut rng = rand::thread_rng();
GlweDimension((rng.gen::<usize>() % (max - 1)) + 1)
let max = std::cmp::max(2, max);
GlweDimension(random_usize_between(1..max + 1))
}
/// Returns a random polynomial size in [2;max].
pub fn random_polynomial_size(max: usize) -> PolynomialSize {
assert_ne!(max, 0, "Max cannot be 0");
let mut rng = rand::thread_rng();
PolynomialSize((rng.gen::<usize>() % (max - 2)) + 2)
let max = std::cmp::max(3, max);
PolynomialSize(random_usize_between(2..max + 1))
}
/// Returns a random base log in [2;max].
pub fn random_base_log(max: usize) -> DecompositionBaseLog {
assert_ne!(max, 0, "Max cannot be 0");
let mut rng = rand::thread_rng();
DecompositionBaseLog((rng.gen::<usize>() % (max - 2)) + 2)
let max = std::cmp::max(3, max);
DecompositionBaseLog(random_usize_between(2..max + 1))
}
/// Returns a random level count in [2;max].
pub fn random_level_count(max: usize) -> DecompositionLevelCount {
assert_ne!(max, 0, "Max cannot be 0");
let mut rng = rand::thread_rng();
DecompositionLevelCount((rng.gen::<usize>() % (max - 2)) + 2)
let max = std::cmp::max(3, max);
DecompositionLevelCount(random_usize_between(2..max + 1))
}
pub fn random_i32_between(range: std::ops::Range<i32>) -> i32 {

View File

@@ -113,6 +113,17 @@ pub trait ContiguousEntityContainer: AsRef<[Self::PODElement]> {
Self::SelfView::<'_>::create_from(container_right, self_meta),
)
}
fn get(&self, index: usize) -> Self::ElementView<'_> {
// index here is the number of ref_elements, we need to multiply by the size of a single
// element to know where to reference the underlying container
let start = index * self.get_element_view_pod_size();
let stop = start + self.get_element_view_pod_size();
let meta = self.get_element_view_creation_metadata();
Self::ElementView::<'_>::create_from(&self.as_ref()[start..stop], meta)
}
}
pub trait ContiguousEntityContainerMut:
@@ -171,4 +182,15 @@ pub trait ContiguousEntityContainerMut:
Self::SelfMutView::<'_>::create_from(container_right, self_meta),
)
}
fn get_mut(&mut self, index: usize) -> Self::ElementMutView<'_> {
// index here is the number of ref_elements, we need to multiply by the size of a single
// element to know where to reference the underlying container
let start = index * self.get_element_view_pod_size();
let stop = start + self.get_element_view_pod_size();
let meta = self.get_element_view_creation_metadata();
Self::ElementMutView::<'_>::create_from(&mut self.as_mut()[start..stop], meta)
}
}

View File

@@ -0,0 +1,232 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::*;
pub struct GgswCiphertextBase<C: Container> {
data: C,
polynomial_size: PolynomialSize,
glwe_size: GlweSize,
decomp_base_log: DecompositionBaseLog,
}
impl<T, C: Container<Element = T>> AsRef<[T]> for GgswCiphertextBase<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GgswCiphertextBase<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
pub fn ggsw_ciphertext_size(
glwe_size: GlweSize,
polynomial_size: PolynomialSize,
decomp_level_count: DecompositionLevelCount,
) -> usize {
decomp_level_count.0 * ggsw_level_matrix_size(glwe_size, polynomial_size)
}
pub fn ggsw_level_matrix_size(glwe_size: GlweSize, polynomial_size: PolynomialSize) -> usize {
glwe_size.0 * glwe_size.0 * polynomial_size.0
}
impl<Scalar, C: Container<Element = Scalar>> GgswCiphertextBase<C> {
pub fn from_container(
container: C,
glwe_size: GlweSize,
polynomial_size: PolynomialSize,
decomp_base_log: DecompositionBaseLog,
) -> Self {
assert!(
container.container_len() > 0,
"Got an empty container to create a GgswCiphertextBase"
);
assert!(
container.container_len() % (glwe_size.0 * glwe_size.0 * polynomial_size.0) == 0,
"The provided container length is not valid. \
It needs to be dividable by glwe_size * glwe_size * polynomial_size: {}. \
Got container length: {} and glwe_size: {glwe_size:?}, \
polynomial_size: {polynomial_size:?}.",
glwe_size.0 * glwe_size.0 * polynomial_size.0,
container.container_len()
);
GgswCiphertextBase {
data: container,
polynomial_size,
glwe_size,
decomp_base_log,
}
}
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
pub fn glwe_size(&self) -> GlweSize {
self.glwe_size
}
pub fn decomposition_base_log(&self) -> DecompositionBaseLog {
self.decomp_base_log
}
pub fn decomposition_level_count(&self) -> DecompositionLevelCount {
DecompositionLevelCount(self.data.container_len() / self.ggsw_level_matrix_size())
}
pub fn ggsw_level_matrix_size(&self) -> usize {
// GlweSize GlweCiphertext(glwe_size, polynomial_size) per level
ggsw_level_matrix_size(self.glwe_size, self.polynomial_size)
}
}
pub type GgswCiphertext<Scalar> = GgswCiphertextBase<Vec<Scalar>>;
pub type GgswCiphertextView<'data, Scalar> = GgswCiphertextBase<&'data [Scalar]>;
pub type GgswCiphertextMutView<'data, Scalar> = GgswCiphertextBase<&'data mut [Scalar]>;
impl<Scalar: Copy> GgswCiphertext<Scalar> {
pub fn new(
fill_with: Scalar,
glwe_size: GlweSize,
polynomial_size: PolynomialSize,
decomp_base_log: DecompositionBaseLog,
decomp_level_count: DecompositionLevelCount,
) -> GgswCiphertext<Scalar> {
GgswCiphertext::from_container(
vec![fill_with; ggsw_ciphertext_size(glwe_size, polynomial_size, decomp_level_count)],
glwe_size,
polynomial_size,
decomp_base_log,
)
}
}
#[derive(Clone, Copy)]
pub struct GgswCiphertextCreationMetadata(
pub GlweSize,
pub PolynomialSize,
pub DecompositionBaseLog,
);
impl<C: Container> CreateFrom<C> for GgswCiphertextBase<C> {
type Metadata = GgswCiphertextCreationMetadata;
#[inline]
fn create_from(from: C, meta: Self::Metadata) -> GgswCiphertextBase<C> {
let GgswCiphertextCreationMetadata(glwe_size, polynomial_size, decomp_base_log) = meta;
GgswCiphertextBase::from_container(from, glwe_size, polynomial_size, decomp_base_log)
}
}
pub struct GgswLevelMatrix<C: Container> {
data: C,
glwe_size: GlweSize,
polynomial_size: PolynomialSize,
}
impl<C: Container> GgswLevelMatrix<C> {
pub fn glwe_size(&self) -> GlweSize {
self.glwe_size
}
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
pub fn from_container(
container: C,
glwe_size: GlweSize,
polynomial_size: PolynomialSize,
) -> GgswLevelMatrix<C> {
assert!(
container.container_len() == ggsw_level_matrix_size(glwe_size, polynomial_size),
"The provided container length is not valid. \
Expected length of {} (glwe_size * glwe_size * polynomial_size), got {}",
ggsw_level_matrix_size(glwe_size, polynomial_size),
container.container_len(),
);
GgswLevelMatrix {
data: container,
glwe_size,
polynomial_size,
}
}
pub fn as_glwe_list(&self) -> GlweCiphertextListView<'_, C::Element> {
GlweCiphertextListView::from_container(
self.data.as_ref(),
self.polynomial_size,
self.glwe_size,
)
}
}
impl<C: ContainerMut> GgswLevelMatrix<C> {
pub fn as_mut_glwe_list(&mut self) -> GlweCiphertextListMutView<'_, C::Element> {
GlweCiphertextListMutView::from_container(
self.data.as_mut(),
self.polynomial_size,
self.glwe_size,
)
}
}
#[derive(Clone, Copy)]
pub struct GgswLevelMatrixCreationMetadata(pub GlweSize, pub PolynomialSize);
impl<C: Container> CreateFrom<C> for GgswLevelMatrix<C> {
type Metadata = GgswLevelMatrixCreationMetadata;
#[inline]
fn create_from(from: C, meta: Self::Metadata) -> GgswLevelMatrix<C> {
let GgswLevelMatrixCreationMetadata(glwe_size, polynomial_size) = meta;
GgswLevelMatrix::from_container(from, glwe_size, polynomial_size)
}
}
impl<C: Container> ContiguousEntityContainer for GgswCiphertextBase<C> {
type PODElement = C::Element;
type ElementViewMetadata = GgswLevelMatrixCreationMetadata;
type ElementView<'this> = GgswLevelMatrix<&'this [Self::PODElement]>
where
Self: 'this;
type SelfViewMetadata = ();
type SelfView<'this> = DummyCreateFrom
where
Self: 'this;
fn get_element_view_creation_metadata(&self) -> Self::ElementViewMetadata {
GgswLevelMatrixCreationMetadata(self.glwe_size, self.polynomial_size)
}
fn get_element_view_pod_size(&self) -> usize {
self.ggsw_level_matrix_size()
}
/// Unimplement for [`GgswCiphertextBase`]. At the moment it does not make sense to
/// return "sub" GgswCiphertext.
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
unimplemented!(
"This function is not supported for GgswCiphertext. \
At the moment it does not make sense to return 'sub' GgswCiphertext."
)
}
}
impl<C: ContainerMut> ContiguousEntityContainerMut for GgswCiphertextBase<C> {
type ElementMutView<'this> = GgswLevelMatrix<&'this mut [Self::PODElement]>
where
Self: 'this;
type SelfMutView<'this> = DummyCreateFrom
where
Self: 'this;
}

View File

@@ -0,0 +1,183 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::*;
pub struct GgswCiphertextListBase<C: Container> {
data: C,
glwe_size: GlweSize,
polynomial_size: PolynomialSize,
decomp_base_log: DecompositionBaseLog,
decomp_level_count: DecompositionLevelCount,
}
impl<T, C: Container<Element = T>> AsRef<[T]> for GgswCiphertextListBase<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GgswCiphertextListBase<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
impl<Scalar, C: Container<Element = Scalar>> GgswCiphertextListBase<C> {
pub fn from_container(
container: C,
glwe_size: GlweSize,
polynomial_size: PolynomialSize,
decomp_base_log: DecompositionBaseLog,
decomp_level_count: DecompositionLevelCount,
) -> GgswCiphertextListBase<C> {
assert!(
container.container_len()
% (decomp_level_count.0 * glwe_size.0 * glwe_size.0 * polynomial_size.0)
== 0,
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count * glwe_size * glwe_size * polynomial_size: \
{}.Got container length: {} and decomp_level_count: {decomp_level_count:?}, \
glwe_size: {glwe_size:?}, polynomial_size: {polynomial_size:?}",
decomp_level_count.0 * glwe_size.0 * glwe_size.0 * polynomial_size.0,
container.container_len()
);
GgswCiphertextListBase {
data: container,
glwe_size,
polynomial_size,
decomp_base_log,
decomp_level_count,
}
}
pub fn glwe_size(&self) -> GlweSize {
self.glwe_size
}
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
pub fn decomposition_base_log(&self) -> DecompositionBaseLog {
self.decomp_base_log
}
pub fn decomposition_level_count(&self) -> DecompositionLevelCount {
self.decomp_level_count
}
pub fn ggsw_ciphertext_count(&self) -> GgswCiphertextCount {
GgswCiphertextCount(
self.data.container_len()
/ ggsw_ciphertext_size(
self.glwe_size,
self.polynomial_size,
self.decomp_level_count,
),
)
}
}
pub type GgswCiphertextList<Scalar> = GgswCiphertextListBase<Vec<Scalar>>;
pub type GgswCiphertextListView<'data, Scalar> = GgswCiphertextListBase<&'data [Scalar]>;
pub type GgswCiphertextListMutView<'data, Scalar> = GgswCiphertextListBase<&'data mut [Scalar]>;
impl<Scalar: Copy> GgswCiphertextList<Scalar> {
pub fn new(
fill_with: Scalar,
glwe_size: GlweSize,
polynomial_size: PolynomialSize,
decomp_base_log: DecompositionBaseLog,
decomp_level_count: DecompositionLevelCount,
ciphertext_count: GgswCiphertextCount,
) -> GgswCiphertextList<Scalar> {
GgswCiphertextListBase::from_container(
vec![
fill_with;
ciphertext_count.0
* ggsw_ciphertext_size(glwe_size, polynomial_size, decomp_level_count)
],
glwe_size,
polynomial_size,
decomp_base_log,
decomp_level_count,
)
}
}
#[derive(Clone, Copy)]
pub struct GgswCiphertextListCreationMetadata(
pub GlweSize,
pub PolynomialSize,
pub DecompositionBaseLog,
pub DecompositionLevelCount,
);
impl<C: Container> CreateFrom<C> for GgswCiphertextListBase<C> {
type Metadata = GgswCiphertextListCreationMetadata;
#[inline]
fn create_from(from: C, meta: Self::Metadata) -> GgswCiphertextListBase<C> {
let GgswCiphertextListCreationMetadata(
glwe_size,
polynomial_size,
decomp_base_log,
decomp_level_count,
) = meta;
GgswCiphertextListBase::from_container(
from,
glwe_size,
polynomial_size,
decomp_base_log,
decomp_level_count,
)
}
}
impl<C: Container> ContiguousEntityContainer for GgswCiphertextListBase<C> {
type PODElement = C::Element;
type ElementViewMetadata = GgswCiphertextCreationMetadata;
type ElementView<'this> = GgswCiphertextView<'this, Self::PODElement>
where
Self: 'this;
type SelfViewMetadata = GgswCiphertextListCreationMetadata;
type SelfView<'this> = GgswCiphertextListView<'this, Self::PODElement>
where
Self: 'this;
fn get_element_view_creation_metadata(&self) -> GgswCiphertextCreationMetadata {
GgswCiphertextCreationMetadata(self.glwe_size, self.polynomial_size, self.decomp_base_log)
}
fn get_element_view_pod_size(&self) -> usize {
ggsw_ciphertext_size(
self.glwe_size,
self.polynomial_size,
self.decomp_level_count,
)
}
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
GgswCiphertextListCreationMetadata(
self.glwe_size,
self.polynomial_size,
self.decomp_base_log,
self.decomp_level_count,
)
}
}
impl<C: ContainerMut> ContiguousEntityContainerMut for GgswCiphertextListBase<C> {
type ElementMutView<'this> = GgswCiphertextMutView<'this, Self::PODElement>
where
Self: 'this;
type SelfMutView<'this> = GgswCiphertextListMutView<'this, Self::PODElement>
where
Self: 'this;
}

View File

@@ -0,0 +1,250 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::*;
pub struct GlweBody<C: Container> {
data: C,
}
impl<C: Container> GlweBody<C> {
pub fn from_container(container: C) -> GlweBody<C> {
assert!(
container.container_len() > 0,
"Got an empty container to create a GlweBody"
);
GlweBody { data: container }
}
pub fn polynomial_size(&self) -> PolynomialSize {
PolynomialSize(self.data.container_len())
}
pub fn as_polynomial(&self) -> PolynomialView<'_, C::Element> {
PolynomialView::from_container(self.as_ref())
}
}
impl<C: ContainerMut> GlweBody<C> {
pub fn as_mut_polynomial(&mut self) -> PolynomialMutView<'_, C::Element> {
PolynomialMutView::from_container(self.as_mut())
}
}
pub struct GlweMask<C: Container> {
data: C,
polynomial_size: PolynomialSize,
}
impl<C: Container> GlweMask<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()
);
GlweMask {
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 as_polynomial_list(&self) -> PolynomialListView<'_, C::Element> {
PolynomialListView::from_container(self.as_ref(), self.polynomial_size)
}
}
impl<C: ContainerMut> GlweMask<C> {
pub fn as_mut_polynomial_list(&mut self) -> PolynomialListMutView<'_, C::Element> {
let polynomial_size = self.polynomial_size;
PolynomialListMutView::from_container(self.as_mut(), polynomial_size)
}
}
impl<T, C: Container<Element = T>> AsRef<[T]> for GlweMask<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweMask<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
impl<T, C: Container<Element = T>> AsRef<[T]> for GlweBody<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweBody<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
pub fn glwe_ciphertext_size(polynomial_size: PolynomialSize, glwe_size: GlweSize) -> usize {
polynomial_size.0 * glwe_size.0
}
pub fn glwe_ciphertext_mask_size(
polynomial_size: PolynomialSize,
glwe_dimension: GlweDimension,
) -> usize {
polynomial_size.0 * glwe_dimension.0
}
#[derive(Clone, Debug, PartialEq)]
pub struct GlweCiphertextBase<C: Container> {
data: C,
polynomial_size: PolynomialSize,
}
impl<T, C: Container<Element = T>> AsRef<[T]> for GlweCiphertextBase<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweCiphertextBase<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
impl<Scalar, C: Container<Element = Scalar>> GlweCiphertextBase<C> {
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> GlweCiphertextBase<C> {
assert!(
container.container_len() > 0,
"Got an empty container to create a GlweCiphertext"
);
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()
);
GlweCiphertextBase {
data: container,
polynomial_size,
}
}
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
pub fn glwe_size(&self) -> GlweSize {
GlweSize(self.as_ref().container_len() / self.polynomial_size.0)
}
pub fn get_mask_and_body(&self) -> (GlweMask<&[Scalar]>, GlweBody<&[Scalar]>) {
let (mask, body) = self.data.as_ref().split_at(glwe_ciphertext_mask_size(
self.polynomial_size,
self.glwe_size().to_glwe_dimension(),
));
(
GlweMask::from_container(mask, self.polynomial_size),
GlweBody::from_container(body),
)
}
pub fn get_body(&self) -> GlweBody<&[Scalar]> {
let body = &self.data.as_ref()[glwe_ciphertext_mask_size(
self.polynomial_size,
self.glwe_size().to_glwe_dimension(),
)..];
GlweBody::from_container(body)
}
pub fn get_mask(&self) -> GlweMask<&[Scalar]> {
GlweMask::from_container(
&self.as_ref()[0..glwe_ciphertext_mask_size(
self.polynomial_size,
self.glwe_size().to_glwe_dimension(),
)],
self.polynomial_size,
)
}
}
impl<Scalar, C: ContainerMut<Element = Scalar>> GlweCiphertextBase<C> {
pub fn get_mut_mask_and_body(&mut self) -> (GlweMask<&mut [Scalar]>, GlweBody<&mut [Scalar]>) {
let polynomial_size = self.polynomial_size();
let glwe_dimension = self.glwe_size().to_glwe_dimension();
let (mask, body) = self
.data
.as_mut()
.split_at_mut(glwe_ciphertext_mask_size(polynomial_size, glwe_dimension));
(
GlweMask::from_container(mask, polynomial_size),
GlweBody::from_container(body),
)
}
pub fn get_mut_body(&mut self) -> GlweBody<&mut [Scalar]> {
let polynomial_size = self.polynomial_size();
let glwe_dimension = self.glwe_size().to_glwe_dimension();
let body =
&mut self.data.as_mut()[glwe_ciphertext_mask_size(polynomial_size, glwe_dimension)..];
GlweBody::from_container(body)
}
pub fn get_mut_mask(&mut self) -> GlweMask<&mut [Scalar]> {
let polynomial_size = self.polynomial_size();
let glwe_dimension = self.glwe_size().to_glwe_dimension();
GlweMask::from_container(
&mut self.as_mut()[0..glwe_ciphertext_mask_size(polynomial_size, glwe_dimension)],
polynomial_size,
)
}
}
pub type GlweCiphertext<Scalar> = GlweCiphertextBase<Vec<Scalar>>;
pub type GlweCiphertextView<'data, Scalar> = GlweCiphertextBase<&'data [Scalar]>;
pub type GlweCiphertextMutView<'data, Scalar> = GlweCiphertextBase<&'data mut [Scalar]>;
impl<Scalar: Copy> GlweCiphertext<Scalar> {
pub fn new(
fill_with: Scalar,
polynomial_size: PolynomialSize,
glwe_size: GlweSize,
) -> GlweCiphertext<Scalar> {
GlweCiphertext::from_container(
vec![fill_with; glwe_ciphertext_size(polynomial_size, glwe_size)],
polynomial_size,
)
}
}
#[derive(Clone, Copy)]
pub struct GlweCiphertextCreationMetadata(pub PolynomialSize);
impl<C: Container> CreateFrom<C> for GlweCiphertextBase<C> {
type Metadata = GlweCiphertextCreationMetadata;
#[inline]
fn create_from(from: C, meta: Self::Metadata) -> GlweCiphertextBase<C> {
let GlweCiphertextCreationMetadata(polynomial_size) = meta;
GlweCiphertextBase::from_container(from, polynomial_size)
}
}

View File

@@ -0,0 +1,126 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::*;
pub struct GlweCiphertextListBase<C: Container> {
data: C,
polynomial_size: PolynomialSize,
glwe_size: GlweSize,
}
impl<T, C: Container<Element = T>> AsRef<[T]> for GlweCiphertextListBase<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweCiphertextListBase<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
impl<Scalar, C: Container<Element = Scalar>> GlweCiphertextListBase<C> {
pub fn from_container(
container: C,
polynomial_size: PolynomialSize,
glwe_size: GlweSize,
) -> GlweCiphertextListBase<C> {
assert!(
container.container_len() % glwe_ciphertext_size(polynomial_size, glwe_size) == 0,
"The provided container length is not valid. \
It needs to be dividable by polynomial_size * glwe_size. \
Got container length: {}, polynomial_size: {polynomial_size:?} glwe_size: {glwe_size:?}.",
container.container_len()
);
GlweCiphertextListBase {
data: container,
polynomial_size,
glwe_size,
}
}
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
pub fn glwe_size(&self) -> GlweSize {
self.glwe_size
}
pub fn glwe_ciphertext_count(&self) -> GlweCiphertextCount {
GlweCiphertextCount(
self.data.container_len() / glwe_ciphertext_size(self.polynomial_size, self.glwe_size),
)
}
}
pub type GlweCiphertextList<Scalar> = GlweCiphertextListBase<Vec<Scalar>>;
pub type GlweCiphertextListView<'data, Scalar> = GlweCiphertextListBase<&'data [Scalar]>;
pub type GlweCiphertextListMutView<'data, Scalar> = GlweCiphertextListBase<&'data mut [Scalar]>;
impl<Scalar: Copy> GlweCiphertextList<Scalar> {
pub fn new(
fill_with: Scalar,
polynomial_size: PolynomialSize,
glwe_size: GlweSize,
ciphertext_count: GlweCiphertextCount,
) -> GlweCiphertextList<Scalar> {
GlweCiphertextList::from_container(
vec![fill_with; glwe_ciphertext_size(polynomial_size, glwe_size) * ciphertext_count.0],
polynomial_size,
glwe_size,
)
}
}
#[derive(Clone, Copy)]
pub struct GlweCiphertextListCreationMetadata(pub PolynomialSize, pub GlweSize);
impl<C: Container> CreateFrom<C> for GlweCiphertextListBase<C> {
type Metadata = GlweCiphertextListCreationMetadata;
#[inline]
fn create_from(from: C, meta: Self::Metadata) -> GlweCiphertextListBase<C> {
let GlweCiphertextListCreationMetadata(polynomial_size, glwe_size) = meta;
GlweCiphertextListBase::from_container(from, polynomial_size, glwe_size)
}
}
impl<C: Container> ContiguousEntityContainer for GlweCiphertextListBase<C> {
type PODElement = C::Element;
type ElementViewMetadata = GlweCiphertextCreationMetadata;
type ElementView<'this> = GlweCiphertextView<'this, Self::PODElement>
where
Self: 'this;
type SelfViewMetadata = GlweCiphertextListCreationMetadata;
type SelfView<'this> = GlweCiphertextListView<'this, Self::PODElement>
where
Self: 'this;
fn get_element_view_creation_metadata(&self) -> GlweCiphertextCreationMetadata {
GlweCiphertextCreationMetadata(self.polynomial_size())
}
fn get_element_view_pod_size(&self) -> usize {
glwe_ciphertext_size(self.polynomial_size(), self.glwe_size())
}
fn get_self_view_creation_metadata(&self) -> GlweCiphertextListCreationMetadata {
GlweCiphertextListCreationMetadata(self.polynomial_size(), self.glwe_size())
}
}
impl<C: ContainerMut> ContiguousEntityContainerMut for GlweCiphertextListBase<C> {
type ElementMutView<'this> = GlweCiphertextMutView<'this, Self::PODElement>
where
Self: 'this;
type SelfMutView<'this> = GlweCiphertextListMutView<'this, Self::PODElement>
where
Self: 'this;
}

View File

@@ -1,6 +1,6 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::{GlweDimension, PolynomialSize};
use crate::core_crypto::specification::parameters::*;
#[derive(Clone, Debug, PartialEq)]
pub struct GlweSecretKeyBase<C: Container> {
@@ -50,6 +50,10 @@ impl<Scalar, C: Container<Element = Scalar>> GlweSecretKeyBase<C> {
pub fn into_lwe_secret_key(self) -> LweSecretKeyBase<C> {
LweSecretKeyBase::from_container(self.data)
}
pub fn as_polynomial_list(&self) -> PolynomialListView<'_, C::Element> {
PolynomialListView::from_container(self.as_ref(), self.polynomial_size)
}
}
pub type GlweSecretKey<Scalar> = GlweSecretKeyBase<Vec<Scalar>>;

View File

@@ -1,5 +1,5 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::specification::parameters::{LweDimension, LweSize};
use crate::core_crypto::specification::parameters::*;
pub struct LweBody<T>(pub T);
pub struct LweMask<C: Container> {

View File

@@ -1,8 +1,7 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::{LweCiphertextCount, LweSize};
use crate::core_crypto::specification::parameters::*;
#[derive(Clone, Debug, PartialEq)]
pub struct LweCiphertextListBase<C: Container> {
data: C,
lwe_size: LweSize,

View File

@@ -1,8 +1,6 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::{
DecompositionBaseLog, DecompositionLevelCount, LweDimension, LweSize,
};
use crate::core_crypto::specification::parameters::*;
#[derive(Clone, Debug, PartialEq)]
pub struct LweKeyswitchKeyBase<C: Container> {
@@ -132,7 +130,7 @@ impl<C: Container> ContiguousEntityContainer for LweKeyswitchKeyBase<C> {
where
Self: 'this;
fn get_element_view_creation_metadata(&self) -> Self::ElementViewMetadata {
fn get_element_view_creation_metadata(&self) -> LweCiphertextListCreationMetadata {
LweCiphertextListCreationMetadata(self.output_lwe_size())
}
@@ -142,8 +140,11 @@ impl<C: Container> ContiguousEntityContainer for LweKeyswitchKeyBase<C> {
/// Unimplement for [`LweKeyswitchKeyBase`]. At the moment it does not make sense to
/// return "sub" keyswitch keys.
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
unimplemented!("At the moment it does not make sense to return 'sub' keyswitch keys.")
fn get_self_view_creation_metadata(&self) {
unimplemented!(
"This function is not supported for LweKeyswitchKey. \
At the moment it does not make sense to return 'sub' keyswitch keys."
)
}
}

View File

@@ -1,4 +1,8 @@
pub mod cleartext;
pub mod ggsw_ciphertext;
pub mod ggsw_ciphertext_list;
pub mod glwe_ciphertext;
pub mod glwe_ciphertext_list;
pub mod glwe_secret_key;
pub mod lwe_ciphertext;
pub mod lwe_ciphertext_list;
@@ -6,8 +10,14 @@ pub mod lwe_keyswitch_key;
pub mod lwe_secret_key;
pub mod plaintext;
pub mod plaintext_list;
pub mod polynomial;
pub mod polynomial_list;
pub use cleartext::*;
pub use ggsw_ciphertext::*;
pub use ggsw_ciphertext_list::*;
pub use glwe_ciphertext::*;
pub use glwe_ciphertext_list::*;
pub use glwe_secret_key::*;
pub use lwe_ciphertext::*;
pub use lwe_ciphertext_list::*;
@@ -15,3 +25,5 @@ pub use lwe_keyswitch_key::*;
pub use lwe_secret_key::*;
pub use plaintext::*;
pub use plaintext_list::*;
pub use polynomial::*;
pub use polynomial_list::*;

View File

@@ -1,6 +1,6 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::PlaintextCount;
use crate::core_crypto::specification::parameters::*;
pub struct PlaintextListBase<C: Container> {
data: C,

View File

@@ -0,0 +1,75 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::specification::parameters::*;
use std::ops::{Deref, DerefMut};
pub struct PolynomialBase<C: Container> {
data: C,
}
impl<T, C: Container<Element = T>> AsRef<[T]> for PolynomialBase<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for PolynomialBase<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
impl<Scalar, C: Container<Element = Scalar>> PolynomialBase<C> {
pub fn from_container(container: C) -> PolynomialBase<C> {
assert!(
container.container_len() > 0,
"Got an empty container to create a Polynomial"
);
PolynomialBase { data: container }
}
pub fn polynomial_size(&self) -> PolynomialSize {
PolynomialSize(self.data.container_len())
}
pub fn degree(&self) -> usize {
self.polynomial_size().0 - 1
}
}
pub type Polynomial<Scalar> = PolynomialBase<Vec<Scalar>>;
pub type PolynomialView<'data, Scalar> = PolynomialBase<&'data [Scalar]>;
pub type PolynomialMutView<'data, Scalar> = PolynomialBase<&'data mut [Scalar]>;
impl<Scalar> Polynomial<Vec<Scalar>>
where
Scalar: Copy,
{
pub fn new(fill_with: Scalar, polynomial_size: PolynomialSize) -> Polynomial<Scalar> {
Polynomial::from_container(vec![fill_with; polynomial_size.0])
}
}
impl<C: Container> Deref for PolynomialBase<C> {
type Target = [C::Element];
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<C: ContainerMut> DerefMut for PolynomialBase<C> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
}
#[derive(Clone, Copy)]
pub struct PolynomialCreationMetadata();
impl<C: Container> CreateFrom<C> for PolynomialBase<C> {
type Metadata = PolynomialCreationMetadata;
fn create_from(from: C, _: Self::Metadata) -> PolynomialBase<C> {
PolynomialBase::from_container(from)
}
}

View File

@@ -0,0 +1,111 @@
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::specification::parameters::*;
pub struct PolynomialListBase<C: Container> {
data: C,
polynomial_size: PolynomialSize,
}
impl<T, C: Container<Element = T>> AsRef<[T]> for PolynomialListBase<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for PolynomialListBase<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
impl<Scalar, C: Container<Element = Scalar>> PolynomialListBase<C> {
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> PolynomialListBase<C> {
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()
);
PolynomialListBase {
data: container,
polynomial_size,
}
}
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
pub fn polynomial_count(&self) -> PolynomialCount {
PolynomialCount(self.data.container_len())
}
}
pub type PolynomialList<Scalar> = PolynomialListBase<Vec<Scalar>>;
pub type PolynomialListView<'data, Scalar> = PolynomialListBase<&'data [Scalar]>;
pub type PolynomialListMutView<'data, Scalar> = PolynomialListBase<&'data mut [Scalar]>;
impl<Scalar: Copy> PolynomialList<Scalar> {
pub fn new(
fill_with: Scalar,
polynomial_size: PolynomialSize,
polynomial_count: PolynomialCount,
) -> PolynomialList<Scalar> {
PolynomialList::from_container(
vec![fill_with; polynomial_size.0 * polynomial_count.0],
polynomial_size,
)
}
}
#[derive(Clone, Copy)]
pub struct PolynomialListCreationMetadata(pub PolynomialSize);
impl<C: Container> CreateFrom<C> for PolynomialListBase<C> {
type Metadata = PolynomialListCreationMetadata;
fn create_from(from: C, meta: Self::Metadata) -> PolynomialListBase<C> {
let PolynomialListCreationMetadata(polynomial_size) = meta;
PolynomialListBase::from_container(from, polynomial_size)
}
}
impl<C: Container> ContiguousEntityContainer for PolynomialListBase<C> {
type PODElement = C::Element;
type ElementViewMetadata = PolynomialCreationMetadata;
type ElementView<'this> = PolynomialView<'this, Self::PODElement>
where
Self: 'this;
type SelfViewMetadata = PolynomialListCreationMetadata;
type SelfView<'this> = PolynomialListView<'this, Self::PODElement>
where
Self: 'this;
fn get_element_view_creation_metadata(&self) -> Self::ElementViewMetadata {
PolynomialCreationMetadata()
}
fn get_element_view_pod_size(&self) -> usize {
self.polynomial_size().0
}
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
PolynomialListCreationMetadata(self.polynomial_size())
}
}
impl<C: ContainerMut> ContiguousEntityContainerMut for PolynomialListBase<C> {
type ElementMutView<'this> = PolynomialMutView<'this, Self::PODElement>
where
Self: 'this;
type SelfMutView<'this> = PolynomialListMutView<'this, Self::PODElement>
where
Self: 'this;
}