mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-10 07:08:03 -05:00
feat(tfhe): add SeededGlweCiphertext
This commit is contained in:
@@ -1,10 +1,40 @@
|
||||
use crate::core_crypto::algorithms::polynomial_algorithms::*;
|
||||
use crate::core_crypto::commons::dispersion::DispersionParameter;
|
||||
use crate::core_crypto::commons::generators::EncryptionRandomGenerator;
|
||||
use crate::core_crypto::commons::math::random::ActivatedRandomGenerator;
|
||||
use crate::core_crypto::commons::parameters::*;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
|
||||
/// Convenience function to share the core logic of the GLWE assign encryption between all functions
|
||||
/// needing it.
|
||||
pub fn fill_glwe_mask_and_body_for_encryption_assign<KeyCont, BodyCont, MaskCont, Scalar, Gen>(
|
||||
glwe_secret_key: &GlweSecretKey<KeyCont>,
|
||||
output_mask: &mut GlweMask<MaskCont>,
|
||||
output_body: &mut GlweBody<BodyCont>,
|
||||
noise_parameters: impl DispersionParameter,
|
||||
generator: &mut EncryptionRandomGenerator<Gen>,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
KeyCont: Container<Element = Scalar>,
|
||||
BodyCont: ContainerMut<Element = Scalar>,
|
||||
MaskCont: ContainerMut<Element = Scalar>,
|
||||
Gen: ByteRandomGenerator,
|
||||
{
|
||||
generator.unsigned_torus_slice_wrapping_add_random_noise_assign(
|
||||
output_body.as_mut(),
|
||||
noise_parameters,
|
||||
);
|
||||
|
||||
generator.fill_slice_with_random_mask(output_mask.as_mut());
|
||||
|
||||
polynomial_wrapping_add_multisum_assign(
|
||||
&mut output_body.as_mut_polynomial(),
|
||||
&output_mask.as_polynomial_list(),
|
||||
&glwe_secret_key.as_polynomial_list(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Variant of [`encrypt_glwe_ciphertext`] which assumes that the plaintexts to encrypt are already
|
||||
/// loaded in the body of the output [`GLWE ciphertext`](`GlweCiphertext`), this is sometimes useful
|
||||
/// to avoid allocating a [`PlaintextList`] in situ.
|
||||
@@ -112,14 +142,44 @@ pub fn encrypt_glwe_ciphertext_assign<Scalar, KeyCont, OutputCont, Gen>(
|
||||
|
||||
let (mut mask, mut body) = output.get_mut_mask_and_body();
|
||||
|
||||
generator.fill_slice_with_random_mask(mask.as_mut());
|
||||
fill_glwe_mask_and_body_for_encryption_assign(
|
||||
glwe_secret_key,
|
||||
&mut mask,
|
||||
&mut body,
|
||||
noise_parameters,
|
||||
generator,
|
||||
);
|
||||
}
|
||||
|
||||
generator
|
||||
.unsigned_torus_slice_wrapping_add_random_noise_assign(body.as_mut(), noise_parameters);
|
||||
/// Convenience function to share the core logic of the GLWE encryption between all functions
|
||||
/// needing it.
|
||||
pub fn fill_glwe_mask_and_body_for_encryption<KeyCont, InputCont, BodyCont, MaskCont, Scalar, Gen>(
|
||||
glwe_secret_key: &GlweSecretKey<KeyCont>,
|
||||
output_mask: &mut GlweMask<MaskCont>,
|
||||
output_body: &mut GlweBody<BodyCont>,
|
||||
encoded: &PlaintextList<InputCont>,
|
||||
noise_parameters: impl DispersionParameter,
|
||||
generator: &mut EncryptionRandomGenerator<Gen>,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
KeyCont: Container<Element = Scalar>,
|
||||
InputCont: Container<Element = Scalar>,
|
||||
BodyCont: ContainerMut<Element = Scalar>,
|
||||
MaskCont: ContainerMut<Element = Scalar>,
|
||||
Gen: ByteRandomGenerator,
|
||||
{
|
||||
generator.fill_slice_with_random_noise(output_body.as_mut(), noise_parameters);
|
||||
|
||||
generator.fill_slice_with_random_mask(output_mask.as_mut());
|
||||
|
||||
polynomial_wrapping_add_assign(
|
||||
&mut output_body.as_mut_polynomial(),
|
||||
&encoded.as_polynomial(),
|
||||
);
|
||||
|
||||
polynomial_wrapping_add_multisum_assign(
|
||||
&mut body.as_mut_polynomial(),
|
||||
&mask.as_polynomial_list(),
|
||||
&mut output_body.as_mut_polynomial(),
|
||||
&output_mask.as_polynomial_list(),
|
||||
&glwe_secret_key.as_polynomial_list(),
|
||||
);
|
||||
}
|
||||
@@ -252,19 +312,13 @@ pub fn encrypt_glwe_ciphertext<Scalar, KeyCont, InputCont, OutputCont, Gen>(
|
||||
|
||||
let (mut mask, mut body) = output_glwe_ciphertext.get_mut_mask_and_body();
|
||||
|
||||
generator.fill_slice_with_random_mask(mask.as_mut());
|
||||
|
||||
generator.fill_slice_with_random_noise(body.as_mut(), noise_parameters);
|
||||
|
||||
polynomial_wrapping_add_assign(
|
||||
&mut body.as_mut_polynomial(),
|
||||
&input_plaintext_list.as_polynomial(),
|
||||
);
|
||||
|
||||
polynomial_wrapping_add_multisum_assign(
|
||||
&mut body.as_mut_polynomial(),
|
||||
&mask.as_polynomial_list(),
|
||||
&glwe_secret_key.as_polynomial_list(),
|
||||
fill_glwe_mask_and_body_for_encryption(
|
||||
glwe_secret_key,
|
||||
&mut mask,
|
||||
&mut body,
|
||||
input_plaintext_list,
|
||||
noise_parameters,
|
||||
generator,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -679,3 +733,139 @@ where
|
||||
|
||||
new_ct
|
||||
}
|
||||
|
||||
/// Encrypt a [`PlaintextList`] in a
|
||||
/// [`compressed/seeded GLWE ciphertext`](`SeededGlweCiphertext`).
|
||||
///
|
||||
/// ```
|
||||
/// use tfhe::core_crypto::commons::generators::{
|
||||
/// EncryptionRandomGenerator, SecretRandomGenerator,
|
||||
/// };
|
||||
/// use tfhe::core_crypto::commons::math::decomposition::SignedDecomposer;
|
||||
/// use tfhe::core_crypto::commons::math::random::ActivatedRandomGenerator;
|
||||
/// use tfhe::core_crypto::prelude::*;
|
||||
/// use tfhe::seeders::new_seeder;
|
||||
///
|
||||
/// // DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct
|
||||
/// // computations
|
||||
/// // Define parameters for GlweCiphertext creation
|
||||
/// let glwe_size = GlweSize(2);
|
||||
/// let polynomial_size = PolynomialSize(1024);
|
||||
/// let glwe_modular_std_dev = StandardDev(0.00000000000000029403601535432533);
|
||||
///
|
||||
/// // Create the PRNG
|
||||
/// let mut seeder = new_seeder();
|
||||
/// let seeder = seeder.as_mut();
|
||||
/// let mut encryption_generator =
|
||||
/// EncryptionRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed(), seeder);
|
||||
/// let mut secret_generator =
|
||||
/// SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());
|
||||
///
|
||||
/// // Create the GlweSecretKey
|
||||
/// let glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
|
||||
/// glwe_size.to_glwe_dimension(),
|
||||
/// polynomial_size,
|
||||
/// &mut secret_generator,
|
||||
/// );
|
||||
///
|
||||
/// // Create the plaintext
|
||||
/// let msg = 3u64;
|
||||
/// let encoded_msg = msg << 60;
|
||||
/// let plaintext_list = PlaintextList::new(encoded_msg, PlaintextCount(polynomial_size.0));
|
||||
///
|
||||
/// // Create a new GlweCiphertext
|
||||
/// let mut glwe =
|
||||
/// SeededGlweCiphertext::new(0u64, glwe_size, polynomial_size, seeder.seed().into());
|
||||
///
|
||||
/// encrypt_seeded_glwe_ciphertext(
|
||||
/// &glwe_secret_key,
|
||||
/// &mut glwe,
|
||||
/// &plaintext_list,
|
||||
/// glwe_modular_std_dev,
|
||||
/// seeder,
|
||||
/// );
|
||||
///
|
||||
/// let glwe = glwe.decompress_into_glwe_ciphertext();
|
||||
///
|
||||
/// let mut output_plaintext_list = PlaintextList::new(0u64, plaintext_list.plaintext_count());
|
||||
///
|
||||
/// decrypt_glwe_ciphertext(&glwe_secret_key, &glwe, &mut output_plaintext_list);
|
||||
///
|
||||
/// // Round and remove encoding
|
||||
/// // First create a decomposer working on the high 4 bits corresponding to our encoding.
|
||||
/// let decomposer = SignedDecomposer::new(DecompositionBaseLog(4), DecompositionLevelCount(1));
|
||||
///
|
||||
/// output_plaintext_list
|
||||
/// .iter_mut()
|
||||
/// .for_each(|elt| *elt.0 = decomposer.closest_representable(*elt.0));
|
||||
///
|
||||
/// // Get the raw vector
|
||||
/// let mut cleartext_list = output_plaintext_list.into_container();
|
||||
/// // Remove the encoding
|
||||
/// cleartext_list.iter_mut().for_each(|elt| *elt = *elt >> 60);
|
||||
/// // Get the list immutably
|
||||
/// let cleartext_list = cleartext_list;
|
||||
///
|
||||
/// // Check we recovered the original message for each plaintext we encrypted
|
||||
/// cleartext_list.iter().for_each(|&elt| assert_eq!(elt, msg));
|
||||
/// ```
|
||||
pub fn encrypt_seeded_glwe_ciphertext<Scalar, KeyCont, InputCont, OutputCont, NoiseSeeder>(
|
||||
glwe_secret_key: &GlweSecretKey<KeyCont>,
|
||||
output_glwe_ciphertext: &mut SeededGlweCiphertext<OutputCont>,
|
||||
input_plaintext_list: &PlaintextList<InputCont>,
|
||||
noise_parameters: impl DispersionParameter,
|
||||
noise_seeder: &mut NoiseSeeder,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
KeyCont: Container<Element = Scalar>,
|
||||
InputCont: Container<Element = Scalar>,
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
// Maybe Sized allows to pass Box<dyn Seeder>.
|
||||
NoiseSeeder: Seeder + ?Sized,
|
||||
{
|
||||
assert!(
|
||||
output_glwe_ciphertext.polynomial_size().0 == input_plaintext_list.plaintext_count().0,
|
||||
"Mismatch between PolynomialSize of output cipertext PlaintextCount of input. \
|
||||
Got {:?} in output, and {:?} in input.",
|
||||
output_glwe_ciphertext.polynomial_size(),
|
||||
input_plaintext_list.plaintext_count()
|
||||
);
|
||||
assert!(
|
||||
output_glwe_ciphertext.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_ciphertext.glwe_size().to_glwe_dimension(),
|
||||
glwe_secret_key.glwe_dimension()
|
||||
);
|
||||
assert!(
|
||||
output_glwe_ciphertext.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_glwe_ciphertext.polynomial_size(),
|
||||
glwe_secret_key.polynomial_size()
|
||||
);
|
||||
|
||||
let mut generator = EncryptionRandomGenerator::<ActivatedRandomGenerator>::new(
|
||||
output_glwe_ciphertext.compression_seed().seed,
|
||||
noise_seeder,
|
||||
);
|
||||
|
||||
let glwe_dimension = output_glwe_ciphertext.glwe_size().to_glwe_dimension();
|
||||
let polynomial_size = output_glwe_ciphertext.polynomial_size();
|
||||
|
||||
let mut body = output_glwe_ciphertext.get_mut_body();
|
||||
|
||||
let mut tmp_mask = GlweMask::from_container(
|
||||
vec![Scalar::ZERO; glwe_ciphertext_mask_size(glwe_dimension, polynomial_size)],
|
||||
polynomial_size,
|
||||
);
|
||||
|
||||
fill_glwe_mask_and_body_for_encryption(
|
||||
glwe_secret_key,
|
||||
&mut tmp_mask,
|
||||
&mut body,
|
||||
input_plaintext_list,
|
||||
noise_parameters,
|
||||
&mut generator,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ pub mod lwe_secret_key_generation;
|
||||
pub mod lwe_wopbs;
|
||||
pub mod misc;
|
||||
pub mod polynomial_algorithms;
|
||||
pub mod seeded_glwe_ciphertext_decompression;
|
||||
pub mod seeded_lwe_ciphertext_list_decompression;
|
||||
pub mod seeded_lwe_public_key_decompression;
|
||||
pub mod seeded_lwe_public_key_generation;
|
||||
@@ -40,6 +41,7 @@ pub use lwe_public_key_generation::*;
|
||||
pub use lwe_secret_key_generation::*;
|
||||
pub use lwe_wopbs::*;
|
||||
pub use misc::*;
|
||||
pub use seeded_glwe_ciphertext_decompression::*;
|
||||
pub use seeded_lwe_ciphertext_list_decompression::*;
|
||||
pub use seeded_lwe_public_key_decompression::*;
|
||||
pub use seeded_lwe_public_key_generation::*;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
use crate::core_crypto::commons::math::random::RandomGenerator;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
|
||||
/// Convenience function to share the core logic of the decompression algorithm for
|
||||
/// [`SeededGlweCiphertext`] between all functions needing it.
|
||||
pub fn decompress_seeded_glwe_ciphertext_with_existing_generator<
|
||||
Scalar,
|
||||
InputCont,
|
||||
OutputCont,
|
||||
Gen,
|
||||
>(
|
||||
output_glwe: &mut GlweCiphertext<OutputCont>,
|
||||
input_seeded_glwe: &SeededGlweCiphertext<InputCont>,
|
||||
generator: &mut RandomGenerator<Gen>,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
InputCont: Container<Element = Scalar>,
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
Gen: ByteRandomGenerator,
|
||||
{
|
||||
let (mut output_mask, mut output_body) = output_glwe.get_mut_mask_and_body();
|
||||
|
||||
// generate a uniformly random mask
|
||||
generator.fill_slice_with_random_uniform(output_mask.as_mut());
|
||||
output_body
|
||||
.as_mut()
|
||||
.copy_from_slice(input_seeded_glwe.get_body().as_ref());
|
||||
}
|
||||
|
||||
/// Decompress a [`SeededGlweCiphertext`], without consuming it, into a standard
|
||||
/// [`GlweCiphertext`].
|
||||
pub fn decompress_seeded_glwe_ciphertext<Scalar, InputCont, OutputCont, Gen>(
|
||||
output_glwe: &mut GlweCiphertext<OutputCont>,
|
||||
input_seeded_glwe: &SeededGlweCiphertext<InputCont>,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
InputCont: Container<Element = Scalar>,
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
Gen: ByteRandomGenerator,
|
||||
{
|
||||
let mut generator = RandomGenerator::<Gen>::new(input_seeded_glwe.compression_seed().seed);
|
||||
decompress_seeded_glwe_ciphertext_with_existing_generator::<_, _, _, Gen>(
|
||||
output_glwe,
|
||||
input_seeded_glwe,
|
||||
&mut generator,
|
||||
)
|
||||
}
|
||||
@@ -17,6 +17,7 @@ pub mod plaintext;
|
||||
pub mod plaintext_list;
|
||||
pub mod polynomial;
|
||||
pub mod polynomial_list;
|
||||
pub mod seeded_glwe_ciphertext;
|
||||
pub mod seeded_lwe_ciphertext_list;
|
||||
pub mod seeded_lwe_public_key;
|
||||
|
||||
@@ -42,5 +43,6 @@ pub use plaintext::*;
|
||||
pub use plaintext_list::*;
|
||||
pub use polynomial::*;
|
||||
pub use polynomial_list::*;
|
||||
pub use seeded_glwe_ciphertext::*;
|
||||
pub use seeded_lwe_ciphertext_list::*;
|
||||
pub use seeded_lwe_public_key::*;
|
||||
|
||||
221
tfhe/src/core_crypto/entities/seeded_glwe_ciphertext.rs
Normal file
221
tfhe/src/core_crypto/entities/seeded_glwe_ciphertext.rs
Normal file
@@ -0,0 +1,221 @@
|
||||
use crate::core_crypto::algorithms::*;
|
||||
use crate::core_crypto::commons::math::random::{ActivatedRandomGenerator, CompressionSeed};
|
||||
use crate::core_crypto::commons::parameters::*;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
|
||||
/// A [`seeded GLWE ciphertext`](`SeededGlweCiphertext`).
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SeededGlweCiphertext<C: Container> {
|
||||
data: C,
|
||||
glwe_size: GlweSize,
|
||||
compression_seed: CompressionSeed,
|
||||
}
|
||||
|
||||
impl<T, C: Container<Element = T>> AsRef<[T]> for SeededGlweCiphertext<C> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for SeededGlweCiphertext<C> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self.data.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar, C: Container<Element = Scalar>> SeededGlweCiphertext<C> {
|
||||
/// Create a [`SeededGlweCiphertext`] from an existing container.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This function only wraps a container in the appropriate type. If you want to encrypt data
|
||||
/// you need to use [`crate::core_crypto::algorithms::encrypt_seeded_glwe_ciphertext`] using
|
||||
/// this ciphertext as output.
|
||||
///
|
||||
/// This docstring exhibits [`SeededGlweCiphertext`] primitives usage.
|
||||
///
|
||||
/// ```
|
||||
/// use tfhe::core_crypto::prelude::*;
|
||||
/// use tfhe::seeders::new_seeder;
|
||||
///
|
||||
/// // DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct
|
||||
/// // computations
|
||||
/// // Define parameters for SeededGlweCiphertext creation
|
||||
/// let glwe_size = GlweSize(2);
|
||||
/// let polynomial_size = PolynomialSize(1024);
|
||||
///
|
||||
/// // Get a seeder
|
||||
/// let mut seeder = new_seeder();
|
||||
/// let seeder = seeder.as_mut();
|
||||
///
|
||||
/// // Create a new SeededGlweCiphertext
|
||||
/// let mut glwe =
|
||||
/// SeededGlweCiphertext::new(0u64, glwe_size, polynomial_size, seeder.seed().into());
|
||||
///
|
||||
/// assert_eq!(glwe.glwe_size(), glwe_size);
|
||||
/// assert_eq!(glwe.polynomial_size(), polynomial_size);
|
||||
/// assert_eq!(glwe.get_body().polynomial_size(), polynomial_size);
|
||||
/// assert_eq!(glwe.get_mut_body().polynomial_size(), polynomial_size);
|
||||
///
|
||||
/// let compression_seed = glwe.compression_seed();
|
||||
///
|
||||
/// // Demonstrate how to recover the allocated container
|
||||
/// let underlying_container: Vec<u64> = glwe.into_container();
|
||||
///
|
||||
/// // Recreate a ciphertext using from_container
|
||||
/// let mut glwe =
|
||||
/// SeededGlweCiphertext::from_container(underlying_container, glwe_size, compression_seed);
|
||||
///
|
||||
/// assert_eq!(glwe.glwe_size(), glwe_size);
|
||||
/// assert_eq!(glwe.polynomial_size(), polynomial_size);
|
||||
/// assert_eq!(glwe.get_body().polynomial_size(), polynomial_size);
|
||||
/// assert_eq!(glwe.get_mut_body().polynomial_size(), polynomial_size);
|
||||
///
|
||||
/// // Decompress the ciphertext
|
||||
/// let mut glwe = glwe.decompress_into_glwe_ciphertext();
|
||||
///
|
||||
/// assert_eq!(glwe.glwe_size(), glwe_size);
|
||||
/// assert_eq!(glwe.polynomial_size(), polynomial_size);
|
||||
/// assert_eq!(glwe.get_body().polynomial_size(), polynomial_size);
|
||||
/// assert_eq!(glwe.get_mut_body().polynomial_size(), polynomial_size);
|
||||
/// assert_eq!(
|
||||
/// glwe.get_mask().glwe_dimension(),
|
||||
/// glwe_size.to_glwe_dimension()
|
||||
/// );
|
||||
/// assert_eq!(
|
||||
/// glwe.get_mut_mask().glwe_dimension(),
|
||||
/// glwe_size.to_glwe_dimension()
|
||||
/// );
|
||||
/// assert_eq!(glwe.get_mask().polynomial_size(), polynomial_size);
|
||||
/// assert_eq!(glwe.get_mut_mask().polynomial_size(), polynomial_size);
|
||||
/// ```
|
||||
pub fn from_container(
|
||||
container: C,
|
||||
glwe_size: GlweSize,
|
||||
compression_seed: CompressionSeed,
|
||||
) -> SeededGlweCiphertext<C> {
|
||||
assert!(
|
||||
container.container_len() > 0,
|
||||
"Got an empty container to create a SeededGlweCiphertext"
|
||||
);
|
||||
SeededGlweCiphertext {
|
||||
data: container,
|
||||
glwe_size,
|
||||
compression_seed,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the [`GlweSize`] of the [`SeededGlweCiphertext`].
|
||||
///
|
||||
/// See [`SeededGlweCiphertext::from_container`] for usage.
|
||||
pub fn glwe_size(&self) -> GlweSize {
|
||||
self.glwe_size
|
||||
}
|
||||
|
||||
/// Return the [`PolynomialSize`] of the [`SeededGlweCiphertext`].
|
||||
///
|
||||
/// See [`SeededGlweCiphertext::from_container`] for usage.
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
PolynomialSize(self.data.container_len())
|
||||
}
|
||||
|
||||
/// Return the [`CompressionSeed`] of the [`SeededGlweCiphertext`].
|
||||
///
|
||||
/// See [`SeededGlweCiphertext::from_container`] for usage.
|
||||
pub fn compression_seed(&self) -> CompressionSeed {
|
||||
self.compression_seed
|
||||
}
|
||||
|
||||
/// Return an immutable view to the [`GlweBody`] of a [`SeededGlweCiphertext`].
|
||||
///
|
||||
/// See [`SeededGlweCiphertext::from_container`] for usage.
|
||||
pub fn get_body(&self) -> GlweBody<&[Scalar]> {
|
||||
GlweBody::from_container(self.as_ref())
|
||||
}
|
||||
|
||||
/// Consume the entity and return its underlying container.
|
||||
///
|
||||
/// See [`SeededGlweCiphertext::from_container`] for usage.
|
||||
pub fn into_container(self) -> C {
|
||||
self.data
|
||||
}
|
||||
|
||||
/// Consume the [`SeededGlweCiphertext`] and decompress it into a standard
|
||||
/// [`GlweCiphertext`].
|
||||
///
|
||||
/// See [`SeededGlweCiphertext::from_container`] for usage.
|
||||
pub fn decompress_into_glwe_ciphertext(self) -> GlweCiphertextOwned<Scalar>
|
||||
where
|
||||
Scalar: UnsignedTorus,
|
||||
{
|
||||
let mut decompressed_ct =
|
||||
GlweCiphertext::new(Scalar::ZERO, self.glwe_size(), self.polynomial_size());
|
||||
decompress_seeded_glwe_ciphertext::<_, _, _, ActivatedRandomGenerator>(
|
||||
&mut decompressed_ct,
|
||||
&self,
|
||||
);
|
||||
decompressed_ct
|
||||
}
|
||||
|
||||
/// Return a view of the [`SeededGlweCiphertext`]. This is useful if an algorithm takes a view
|
||||
/// by value.
|
||||
pub fn as_view(&self) -> SeededGlweCiphertext<&'_ [Scalar]> {
|
||||
SeededGlweCiphertext {
|
||||
data: self.data.as_ref(),
|
||||
glwe_size: self.glwe_size,
|
||||
compression_seed: self.compression_seed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar, C: ContainerMut<Element = Scalar>> SeededGlweCiphertext<C> {
|
||||
/// Mutable variant of [`SeededGlweCiphertext::get_body`].
|
||||
///
|
||||
/// See [`SeededGlweCiphertext::from_container`] for usage.
|
||||
pub fn get_mut_body(&mut self) -> GlweBody<&mut [Scalar]> {
|
||||
GlweBody::from_container(self.as_mut())
|
||||
}
|
||||
|
||||
/// Mutable variant of [`SeededGlweCiphertext::as_view`].
|
||||
pub fn as_mut_view(&mut self) -> SeededGlweCiphertext<&'_ mut [Scalar]> {
|
||||
SeededGlweCiphertext {
|
||||
data: self.data.as_mut(),
|
||||
glwe_size: self.glwe_size,
|
||||
compression_seed: self.compression_seed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`SeededGlweCiphertext`] owning the memory for its own storage.
|
||||
pub type SeededGlweCiphertextOwned<Scalar> = SeededGlweCiphertext<Vec<Scalar>>;
|
||||
/// A [`SeededGlweCiphertext`] immutably borrowing memory for its own storage.
|
||||
pub type SeededGlweCiphertextView<'data, Scalar> = SeededGlweCiphertext<&'data [Scalar]>;
|
||||
/// A [`SeededGlweCiphertext`] mutably borrowing memory for its own storage.
|
||||
pub type SeededGlweCiphertextMutView<'data, Scalar> = SeededGlweCiphertext<&'data mut [Scalar]>;
|
||||
|
||||
impl<Scalar: Copy> SeededGlweCiphertextOwned<Scalar> {
|
||||
/// Allocate memory and create a new owned [`SeededGlweCiphertext`].
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This function allocates a vector of the appropriate size and wraps it in the appropriate
|
||||
/// type. If you want to encrypt data you need to use
|
||||
/// [`crate::core_crypto::algorithms::encrypt_glwe_ciphertext`] using this ciphertext as
|
||||
/// output.
|
||||
///
|
||||
///
|
||||
/// See [`SeededGlweCiphertext::from_container`] for usage.
|
||||
pub fn new(
|
||||
fill_with: Scalar,
|
||||
glwe_size: GlweSize,
|
||||
polynomial_size: PolynomialSize,
|
||||
compression_seed: CompressionSeed,
|
||||
) -> SeededGlweCiphertextOwned<Scalar> {
|
||||
SeededGlweCiphertextOwned::from_container(
|
||||
vec![fill_with; polynomial_size.0],
|
||||
glwe_size,
|
||||
compression_seed,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ impl ShortintEngine {
|
||||
|
||||
pub(crate) fn unchecked_neg_assign_with_z(
|
||||
&mut self,
|
||||
_server_key: &ServerKey,
|
||||
server_key: &ServerKey,
|
||||
ct: &mut Ciphertext,
|
||||
) -> EngineResult<u64> {
|
||||
// z = ceil( degree / 2^p ) * 2^p
|
||||
@@ -46,7 +46,7 @@ impl ShortintEngine {
|
||||
|
||||
// Value of the shift we multiply our messages by
|
||||
let delta =
|
||||
(1_u64 << 63) / (_server_key.message_modulus.0 * _server_key.carry_modulus.0) as u64;
|
||||
(1_u64 << 63) / (server_key.message_modulus.0 * server_key.carry_modulus.0) as u64;
|
||||
|
||||
//Scaling + 1 on the padding bit
|
||||
let w = Plaintext(z * delta);
|
||||
|
||||
Reference in New Issue
Block a user