use crate::core_crypto::algorithms::polynomial_algorithms::*;
use crate::core_crypto::algorithms::slice_algorithms::{
slice_wrapping_scalar_div_assign, slice_wrapping_scalar_mul_assign,
};
use crate::core_crypto::commons::ciphertext_modulus::CiphertextModulusKind;
use crate::core_crypto::commons::generators::EncryptionRandomGenerator;
use crate::core_crypto::commons::math::random::{DefaultRandomGenerator, Distribution, Uniform};
use crate::core_crypto::commons::parameters::*;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
pub fn fill_glwe_mask_and_body_for_encryption_assign<
Scalar,
NoiseDistribution,
KeyCont,
BodyCont,
MaskCont,
Gen,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output_mask: &mut GlweMask<MaskCont>,
output_body: &mut GlweBody<BodyCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
BodyCont: ContainerMut<Element = Scalar>,
MaskCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
let ciphertext_modulus = output_body.ciphertext_modulus();
if ciphertext_modulus.is_compatible_with_native_modulus() {
fill_glwe_mask_and_body_for_encryption_assign_native_mod_compatible(
glwe_secret_key,
output_mask,
output_body,
noise_distribution,
generator,
)
} else {
fill_glwe_mask_and_body_for_encryption_assign_non_native_mod(
glwe_secret_key,
output_mask,
output_body,
noise_distribution,
generator,
)
}
}
pub fn fill_glwe_mask_and_body_for_encryption_assign_native_mod_compatible<
Scalar,
NoiseDistribution,
KeyCont,
BodyCont,
MaskCont,
Gen,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output_mask: &mut GlweMask<MaskCont>,
output_body: &mut GlweBody<BodyCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
BodyCont: ContainerMut<Element = Scalar>,
MaskCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
assert_eq!(
output_mask.ciphertext_modulus(),
output_body.ciphertext_modulus(),
"Mismatched moduli between output_mask ({:?}) and output_body ({:?})",
output_mask.ciphertext_modulus(),
output_body.ciphertext_modulus()
);
assert_eq!(
output_mask.glwe_dimension(),
glwe_secret_key.glwe_dimension(),
"Mismatched GlweDimension between output_mask ({:?}) and glwe_secret_key ({:?})",
output_mask.glwe_dimension(),
glwe_secret_key.glwe_dimension(),
);
let ciphertext_modulus = output_body.ciphertext_modulus();
assert!(ciphertext_modulus.is_compatible_with_native_modulus());
generator
.fill_slice_with_random_uniform_mask_custom_mod(output_mask.as_mut(), ciphertext_modulus);
generator.unsigned_integer_slice_wrapping_add_random_noise_from_distribution_custom_mod_assign(
output_body.as_mut(),
noise_distribution,
ciphertext_modulus,
);
if !ciphertext_modulus.is_native_modulus() {
let torus_scaling = ciphertext_modulus.get_power_of_two_scaling_to_native_torus();
slice_wrapping_scalar_mul_assign(output_mask.as_mut(), torus_scaling);
slice_wrapping_scalar_mul_assign(output_body.as_mut(), torus_scaling);
}
polynomial_wrapping_add_multisum_assign(
&mut output_body.as_mut_polynomial(),
&output_mask.as_polynomial_list(),
&glwe_secret_key.as_polynomial_list(),
);
}
pub fn fill_glwe_mask_and_body_for_encryption_assign_non_native_mod<
Scalar,
NoiseDistribution,
KeyCont,
BodyCont,
MaskCont,
Gen,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output_mask: &mut GlweMask<MaskCont>,
output_body: &mut GlweBody<BodyCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
BodyCont: ContainerMut<Element = Scalar>,
MaskCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
assert_eq!(
output_mask.ciphertext_modulus(),
output_body.ciphertext_modulus(),
"Mismatched moduli between output_mask ({:?}) and output_body ({:?})",
output_mask.ciphertext_modulus(),
output_body.ciphertext_modulus()
);
let ciphertext_modulus = output_body.ciphertext_modulus();
assert!(!ciphertext_modulus.is_compatible_with_native_modulus());
generator
.fill_slice_with_random_uniform_mask_custom_mod(output_mask.as_mut(), ciphertext_modulus);
generator.unsigned_integer_slice_wrapping_add_random_noise_from_distribution_custom_mod_assign(
output_body.as_mut(),
noise_distribution,
ciphertext_modulus,
);
polynomial_wrapping_add_multisum_assign_custom_mod(
&mut output_body.as_mut_polynomial(),
&output_mask.as_polynomial_list(),
&glwe_secret_key.as_polynomial_list(),
ciphertext_modulus.get_custom_modulus().cast_into(),
);
}
pub fn encrypt_glwe_ciphertext_assign<Scalar, NoiseDistribution, KeyCont, OutputCont, Gen>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output: &mut GlweCiphertext<OutputCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
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 ciphertext 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 ciphertext 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();
fill_glwe_mask_and_body_for_encryption_assign(
glwe_secret_key,
&mut mask,
&mut body,
noise_distribution,
generator,
);
}
pub fn encrypt_seeded_glwe_ciphertext_assign_with_pre_seeded_generator<
Scalar,
NoiseDistribution,
KeyCont,
OutputCont,
Gen,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output: &mut SeededGlweCiphertext<OutputCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
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 ciphertext 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 ciphertext and input secret key. \
Got {:?} in output, and {:?} in secret key.",
output.polynomial_size(),
glwe_secret_key.polynomial_size()
);
let mut mask = GlweMask::from_container(
vec![
Scalar::ZERO;
glwe_ciphertext_mask_size(
output.glwe_size().to_glwe_dimension(),
output.polynomial_size()
)
],
output.polynomial_size(),
output.ciphertext_modulus(),
);
let mut body = output.get_mut_body();
fill_glwe_mask_and_body_for_encryption_assign(
glwe_secret_key,
&mut mask,
&mut body,
noise_distribution,
generator,
);
}
pub fn fill_glwe_mask_and_body_for_encryption<
Scalar,
NoiseDistribution,
KeyCont,
InputCont,
BodyCont,
MaskCont,
Gen,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output_mask: &mut GlweMask<MaskCont>,
output_body: &mut GlweBody<BodyCont>,
encoded: &PlaintextList<InputCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
BodyCont: ContainerMut<Element = Scalar>,
MaskCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
let ciphertext_modulus = output_body.ciphertext_modulus();
if ciphertext_modulus.is_compatible_with_native_modulus() {
fill_glwe_mask_and_body_for_encryption_native_mod_compatible(
glwe_secret_key,
output_mask,
output_body,
encoded,
noise_distribution,
generator,
)
} else {
fill_glwe_mask_and_body_for_encryption_other_mod(
glwe_secret_key,
output_mask,
output_body,
encoded,
noise_distribution,
generator,
)
}
}
pub fn fill_glwe_mask_and_body_for_encryption_native_mod_compatible<
Scalar,
NoiseDistribution,
KeyCont,
InputCont,
BodyCont,
MaskCont,
Gen,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output_mask: &mut GlweMask<MaskCont>,
output_body: &mut GlweBody<BodyCont>,
encoded: &PlaintextList<InputCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
BodyCont: ContainerMut<Element = Scalar>,
MaskCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
assert_eq!(
output_mask.ciphertext_modulus(),
output_body.ciphertext_modulus()
);
let ciphertext_modulus = output_body.ciphertext_modulus();
assert!(ciphertext_modulus.is_compatible_with_native_modulus());
generator
.fill_slice_with_random_uniform_mask_custom_mod(output_mask.as_mut(), ciphertext_modulus);
generator.fill_slice_with_random_noise_from_distribution_custom_mod(
output_body.as_mut(),
noise_distribution,
ciphertext_modulus,
);
polynomial_wrapping_add_assign(
&mut output_body.as_mut_polynomial(),
&encoded.as_polynomial(),
);
if !ciphertext_modulus.is_native_modulus() {
let torus_scaling = ciphertext_modulus.get_power_of_two_scaling_to_native_torus();
slice_wrapping_scalar_mul_assign(output_mask.as_mut(), torus_scaling);
slice_wrapping_scalar_mul_assign(output_body.as_mut(), torus_scaling);
}
polynomial_wrapping_add_multisum_assign(
&mut output_body.as_mut_polynomial(),
&output_mask.as_polynomial_list(),
&glwe_secret_key.as_polynomial_list(),
);
}
pub fn fill_glwe_mask_and_body_for_encryption_other_mod<
Scalar,
NoiseDistribution,
KeyCont,
InputCont,
BodyCont,
MaskCont,
Gen,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output_mask: &mut GlweMask<MaskCont>,
output_body: &mut GlweBody<BodyCont>,
encoded: &PlaintextList<InputCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
BodyCont: ContainerMut<Element = Scalar>,
MaskCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
assert_eq!(
output_mask.ciphertext_modulus(),
output_body.ciphertext_modulus()
);
let ciphertext_modulus = output_body.ciphertext_modulus();
assert!(!ciphertext_modulus.is_compatible_with_native_modulus());
generator
.fill_slice_with_random_uniform_mask_custom_mod(output_mask.as_mut(), ciphertext_modulus);
generator.fill_slice_with_random_noise_from_distribution_custom_mod(
output_body.as_mut(),
noise_distribution,
ciphertext_modulus,
);
let ciphertext_modulus = ciphertext_modulus.get_custom_modulus().cast_into();
polynomial_wrapping_add_assign_custom_mod(
&mut output_body.as_mut_polynomial(),
&encoded.as_polynomial(),
ciphertext_modulus,
);
polynomial_wrapping_add_multisum_assign_custom_mod(
&mut output_body.as_mut_polynomial(),
&output_mask.as_polynomial_list(),
&glwe_secret_key.as_polynomial_list(),
ciphertext_modulus,
);
}
pub fn encrypt_glwe_ciphertext<Scalar, NoiseDistribution, KeyCont, InputCont, OutputCont, Gen>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output_glwe_ciphertext: &mut GlweCiphertext<OutputCont>,
input_plaintext_list: &PlaintextList<InputCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
assert!(
output_glwe_ciphertext.polynomial_size().0 == input_plaintext_list.plaintext_count().0,
"Mismatch between PolynomialSize of output ciphertext 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 ciphertext 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 ciphertext and input secret key. \
Got {:?} in output, and {:?} in secret key.",
output_glwe_ciphertext.polynomial_size(),
glwe_secret_key.polynomial_size()
);
let (mut mask, mut body) = output_glwe_ciphertext.get_mut_mask_and_body();
fill_glwe_mask_and_body_for_encryption(
glwe_secret_key,
&mut mask,
&mut body,
input_plaintext_list,
noise_distribution,
generator,
);
}
pub fn encrypt_glwe_ciphertext_list<
Scalar,
NoiseDistribution,
KeyCont,
InputCont,
OutputCont,
Gen,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output_glwe_ciphertext_list: &mut GlweCiphertextList<OutputCont>,
input_plaintext_list: &PlaintextList<InputCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
Gen: ByteRandomGenerator,
{
assert!(
output_glwe_ciphertext_list
.polynomial_size()
.0
.checked_mul(output_glwe_ciphertext_list.glwe_ciphertext_count().0)
.unwrap()
== input_plaintext_list.plaintext_count().0,
"Mismatch between required number of plaintexts: {} ({:?} * {:?}) and input \
PlaintextCount: {:?}",
output_glwe_ciphertext_list.polynomial_size().0
* output_glwe_ciphertext_list.glwe_ciphertext_count().0,
output_glwe_ciphertext_list.polynomial_size(),
output_glwe_ciphertext_list.glwe_ciphertext_count(),
input_plaintext_list.plaintext_count()
);
assert!(
output_glwe_ciphertext_list.glwe_size().to_glwe_dimension()
== glwe_secret_key.glwe_dimension(),
"Mismatch between GlweDimension of output ciphertext and input secret key. \
Got {:?} in output, and {:?} in secret key.",
output_glwe_ciphertext_list.glwe_size().to_glwe_dimension(),
glwe_secret_key.glwe_dimension()
);
assert!(
output_glwe_ciphertext_list.polynomial_size() == glwe_secret_key.polynomial_size(),
"Mismatch between PolynomialSize of output ciphertext and input secret key. \
Got {:?} in output, and {:?} in secret key.",
output_glwe_ciphertext_list.polynomial_size(),
glwe_secret_key.polynomial_size()
);
let polynomial_size = output_glwe_ciphertext_list.polynomial_size();
for (mut ciphertext, encoded) in output_glwe_ciphertext_list
.iter_mut()
.zip(input_plaintext_list.chunks_exact(polynomial_size.0))
{
encrypt_glwe_ciphertext(
glwe_secret_key,
&mut ciphertext,
&encoded,
noise_distribution,
generator,
);
}
}
pub fn decrypt_glwe_ciphertext<Scalar, KeyCont, InputCont, OutputCont>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
input_glwe_ciphertext: &GlweCiphertext<InputCont>,
output_plaintext_list: &mut PlaintextList<OutputCont>,
) where
Scalar: UnsignedInteger,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
{
let ciphertext_modulus = input_glwe_ciphertext.ciphertext_modulus();
if ciphertext_modulus.is_compatible_with_native_modulus() {
decrypt_glwe_ciphertext_native_mod_compatible(
glwe_secret_key,
input_glwe_ciphertext,
output_plaintext_list,
);
} else {
decrypt_glwe_ciphertext_other_mod(
glwe_secret_key,
input_glwe_ciphertext,
output_plaintext_list,
);
}
}
pub fn decrypt_glwe_ciphertext_native_mod_compatible<Scalar, KeyCont, InputCont, OutputCont>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
input_glwe_ciphertext: &GlweCiphertext<InputCont>,
output_plaintext_list: &mut PlaintextList<OutputCont>,
) where
Scalar: UnsignedInteger,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
{
assert!(
output_plaintext_list.plaintext_count().0 == input_glwe_ciphertext.polynomial_size().0,
"Mismatched output PlaintextCount {:?} and input PolynomialSize {:?}",
output_plaintext_list.plaintext_count(),
input_glwe_ciphertext.polynomial_size()
);
assert!(
glwe_secret_key.glwe_dimension() == input_glwe_ciphertext.glwe_size().to_glwe_dimension(),
"Mismatched GlweDimension between glwe_secret_key {:?} and input_glwe_ciphertext {:?}",
glwe_secret_key.glwe_dimension(),
input_glwe_ciphertext.glwe_size().to_glwe_dimension()
);
assert!(
glwe_secret_key.polynomial_size() == input_glwe_ciphertext.polynomial_size(),
"Mismatched PolynomialSize between glwe_secret_key {:?} and input_glwe_ciphertext {:?}",
glwe_secret_key.polynomial_size(),
input_glwe_ciphertext.polynomial_size()
);
let ciphertext_modulus = input_glwe_ciphertext.ciphertext_modulus();
assert!(ciphertext_modulus.is_compatible_with_native_modulus());
let (mask, body) = input_glwe_ciphertext.get_mask_and_body();
output_plaintext_list
.as_mut()
.copy_from_slice(body.as_ref());
polynomial_wrapping_sub_multisum_assign(
&mut output_plaintext_list.as_mut_polynomial(),
&mask.as_polynomial_list(),
&glwe_secret_key.as_polynomial_list(),
);
if !ciphertext_modulus.is_native_modulus() {
slice_wrapping_scalar_div_assign(
output_plaintext_list.as_mut(),
ciphertext_modulus.get_power_of_two_scaling_to_native_torus(),
);
}
}
pub fn decrypt_glwe_ciphertext_other_mod<Scalar, KeyCont, InputCont, OutputCont>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
input_glwe_ciphertext: &GlweCiphertext<InputCont>,
output_plaintext_list: &mut PlaintextList<OutputCont>,
) where
Scalar: UnsignedInteger,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
{
assert!(
output_plaintext_list.plaintext_count().0 == input_glwe_ciphertext.polynomial_size().0,
"Mismatched output PlaintextCount {:?} and input PolynomialSize {:?}",
output_plaintext_list.plaintext_count(),
input_glwe_ciphertext.polynomial_size()
);
assert!(
glwe_secret_key.glwe_dimension() == input_glwe_ciphertext.glwe_size().to_glwe_dimension(),
"Mismatched GlweDimension between glwe_secret_key {:?} and input_glwe_ciphertext {:?}",
glwe_secret_key.glwe_dimension(),
input_glwe_ciphertext.glwe_size().to_glwe_dimension()
);
assert!(
glwe_secret_key.polynomial_size() == input_glwe_ciphertext.polynomial_size(),
"Mismatched PolynomialSize between glwe_secret_key {:?} and input_glwe_ciphertext {:?}",
glwe_secret_key.polynomial_size(),
input_glwe_ciphertext.polynomial_size()
);
let ciphertext_modulus = input_glwe_ciphertext.ciphertext_modulus();
assert!(!ciphertext_modulus.is_compatible_with_native_modulus());
let ciphertext_modulus_as_scalar: Scalar = ciphertext_modulus.get_custom_modulus().cast_into();
let (mask, body) = input_glwe_ciphertext.get_mask_and_body();
output_plaintext_list
.as_mut()
.copy_from_slice(body.as_ref());
polynomial_wrapping_sub_multisum_assign_custom_mod(
&mut output_plaintext_list.as_mut_polynomial(),
&mask.as_polynomial_list(),
&glwe_secret_key.as_polynomial_list(),
ciphertext_modulus_as_scalar,
);
}
pub fn decrypt_glwe_ciphertext_list<Scalar, KeyCont, InputCont, OutputCont>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
input_glwe_ciphertext_list: &GlweCiphertextList<InputCont>,
output_plaintext_list: &mut PlaintextList<OutputCont>,
) where
Scalar: UnsignedTorus,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
{
assert!(
output_plaintext_list.plaintext_count().0
== input_glwe_ciphertext_list.polynomial_size().0
* input_glwe_ciphertext_list.glwe_ciphertext_count().0,
"Mismatched output PlaintextCount {:?} and input PolynomialSize ({:?}) * \
GlweCiphertextCount ({:?}) = {:?}",
output_plaintext_list.plaintext_count(),
input_glwe_ciphertext_list.polynomial_size(),
input_glwe_ciphertext_list.glwe_ciphertext_count(),
input_glwe_ciphertext_list.polynomial_size().0
* input_glwe_ciphertext_list.glwe_ciphertext_count().0
);
assert!(
glwe_secret_key.glwe_dimension()
== input_glwe_ciphertext_list.glwe_size().to_glwe_dimension(),
"Mismatched GlweDimension between glwe_secret_key {:?} and input_glwe_ciphertext_list {:?}",
glwe_secret_key.glwe_dimension(),
input_glwe_ciphertext_list.glwe_size().to_glwe_dimension()
);
assert!(
glwe_secret_key.polynomial_size() == input_glwe_ciphertext_list.polynomial_size(),
"Mismatched PolynomialSize between glwe_secret_key {:?} and input_glwe_ciphertext_list {:?}",
glwe_secret_key.polynomial_size(),
input_glwe_ciphertext_list.polynomial_size()
);
for (ciphertext, mut output_sublist) in input_glwe_ciphertext_list
.iter()
.zip(output_plaintext_list.chunks_exact_mut(input_glwe_ciphertext_list.polynomial_size().0))
{
decrypt_glwe_ciphertext(glwe_secret_key, &ciphertext, &mut output_sublist);
}
}
pub fn trivially_encrypt_glwe_ciphertext<Scalar, InputCont, OutputCont>(
output: &mut GlweCiphertext<OutputCont>,
encoded: &PlaintextList<InputCont>,
) where
Scalar: UnsignedTorus,
OutputCont: ContainerMut<Element = Scalar>,
InputCont: Container<Element = Scalar>,
{
assert!(
encoded.plaintext_count().0 == output.polynomial_size().0,
"Mismatched input PlaintextCount {:?} and output PolynomialSize {:?}",
encoded.plaintext_count(),
output.polynomial_size()
);
let (mut mask, mut body) = output.get_mut_mask_and_body();
mask.as_mut().fill(Scalar::ZERO);
body.as_mut().copy_from_slice(encoded.as_ref());
let ciphertext_modulus = body.ciphertext_modulus();
match ciphertext_modulus.kind() {
CiphertextModulusKind::Native | CiphertextModulusKind::Other => (),
CiphertextModulusKind::NonNativePowerOfTwo => {
slice_wrapping_scalar_mul_assign(
body.as_mut(),
ciphertext_modulus.get_power_of_two_scaling_to_native_torus(),
);
}
}
}
pub fn allocate_and_trivially_encrypt_new_glwe_ciphertext<Scalar, InputCont>(
glwe_size: GlweSize,
encoded: &PlaintextList<InputCont>,
ciphertext_modulus: CiphertextModulus<Scalar>,
) -> GlweCiphertextOwned<Scalar>
where
Scalar: UnsignedTorus,
InputCont: Container<Element = Scalar>,
{
let polynomial_size = PolynomialSize(encoded.plaintext_count().0);
let mut new_ct =
GlweCiphertextOwned::new(Scalar::ZERO, glwe_size, polynomial_size, ciphertext_modulus);
let mut body = new_ct.get_mut_body();
body.as_mut().copy_from_slice(encoded.as_ref());
if ciphertext_modulus.kind() == CiphertextModulusKind::NonNativePowerOfTwo {
slice_wrapping_scalar_mul_assign(
body.as_mut(),
ciphertext_modulus.get_power_of_two_scaling_to_native_torus(),
);
}
new_ct
}
pub fn encrypt_seeded_glwe_ciphertext_with_pre_seeded_generator<
Scalar,
NoiseDistribution,
KeyCont,
OutputCont,
InputCont,
Gen,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output_glwe_ciphertext: &mut SeededGlweCiphertext<OutputCont>,
input_plaintext_list: &PlaintextList<InputCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
InputCont: Container<Element = Scalar>,
Gen: ByteRandomGenerator,
{
assert!(
output_glwe_ciphertext.polynomial_size().0 == input_plaintext_list.plaintext_count().0,
"Mismatch between PolynomialSize of output ciphertext 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 ciphertext 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 ciphertext and input secret key. \
Got {:?} in output, and {:?} in secret key.",
output_glwe_ciphertext.polynomial_size(),
glwe_secret_key.polynomial_size()
);
let glwe_dimension = output_glwe_ciphertext.glwe_size().to_glwe_dimension();
let polynomial_size = output_glwe_ciphertext.polynomial_size();
let ciphertext_modulus = output_glwe_ciphertext.ciphertext_modulus();
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,
ciphertext_modulus,
);
fill_glwe_mask_and_body_for_encryption(
glwe_secret_key,
&mut tmp_mask,
&mut body,
input_plaintext_list,
noise_distribution,
generator,
);
}
pub fn encrypt_seeded_glwe_ciphertext<
Scalar,
NoiseDistribution,
KeyCont,
InputCont,
OutputCont,
NoiseSeeder,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output_glwe_ciphertext: &mut SeededGlweCiphertext<OutputCont>,
input_plaintext_list: &PlaintextList<InputCont>,
noise_distribution: NoiseDistribution,
noise_seeder: &mut NoiseSeeder,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
InputCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
NoiseSeeder: Seeder + ?Sized,
{
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
output_glwe_ciphertext.compression_seed(),
noise_seeder,
);
encrypt_seeded_glwe_ciphertext_with_pre_seeded_generator(
glwe_secret_key,
output_glwe_ciphertext,
input_plaintext_list,
noise_distribution,
&mut generator,
);
}
pub fn encrypt_seeded_glwe_ciphertext_list_with_pre_seeded_generator<
Scalar,
NoiseDistribution,
KeyCont,
OutputCont,
InputCont,
Gen,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output: &mut SeededGlweCiphertextList<OutputCont>,
encoded: &PlaintextList<InputCont>,
noise_distribution: NoiseDistribution,
generator: &mut EncryptionRandomGenerator<Gen>,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
InputCont: Container<Element = Scalar>,
Gen: ByteRandomGenerator,
{
assert!(
output.glwe_size().to_glwe_dimension() == glwe_secret_key.glwe_dimension(),
"Mismatched GlweDimension between input GlweSecretKey {:?} and output \
SeededGlweCiphertextList {:?}.",
glwe_secret_key.glwe_dimension(),
output.glwe_size().to_glwe_dimension(),
);
assert!(
output
.glwe_ciphertext_count()
.0
.checked_mul(output.polynomial_size().0)
.unwrap()
== encoded.plaintext_count().0,
"Mismatch between number of output ciphertexts and input plaintexts. \
Got {:?} plaintexts while {:?} plaintexts are required to encrypt {:?} ciphertexts.",
encoded.plaintext_count(),
output.glwe_ciphertext_count().0 * output.polynomial_size().0,
output.glwe_ciphertext_count()
);
let mut output_mask = GlweMask::from_container(
vec![
Scalar::ZERO;
glwe_ciphertext_mask_size(
output.glwe_size().to_glwe_dimension(),
output.polynomial_size(),
)
],
output.polynomial_size(),
output.ciphertext_modulus(),
);
let polynomial_size = output.polynomial_size();
for (mut output_glwe, plaintext_list) in output
.iter_mut()
.zip(encoded.chunks_exact(polynomial_size.0))
{
fill_glwe_mask_and_body_for_encryption(
glwe_secret_key,
&mut output_mask,
&mut output_glwe.get_mut_body(),
&plaintext_list,
noise_distribution,
generator,
);
}
}
pub fn encrypt_seeded_glwe_ciphertext_list<
Scalar,
NoiseDistribution,
KeyCont,
OutputCont,
InputCont,
NoiseSeeder,
>(
glwe_secret_key: &GlweSecretKey<KeyCont>,
output: &mut SeededGlweCiphertextList<OutputCont>,
encoded: &PlaintextList<InputCont>,
noise_distribution: NoiseDistribution,
noise_seeder: &mut NoiseSeeder,
) where
Scalar: Encryptable<Uniform, NoiseDistribution>,
NoiseDistribution: Distribution,
KeyCont: Container<Element = Scalar>,
OutputCont: ContainerMut<Element = Scalar>,
InputCont: Container<Element = Scalar>,
NoiseSeeder: Seeder + ?Sized,
{
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
output.compression_seed(),
noise_seeder,
);
encrypt_seeded_glwe_ciphertext_list_with_pre_seeded_generator(
glwe_secret_key,
output,
encoded,
noise_distribution,
&mut generator,
);
}