trace packing for native modulus

This commit is contained in:
Carl-Zama
2024-07-11 04:04:34 +01:00
parent e817c9dcab
commit 88b84ddb90

View File

@@ -15,11 +15,11 @@ use crate::core_crypto::entities::*;
/// // DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct
/// // computations
/// // Define parameters for LweTracePackingKeyswitchKey creation
/// let lwe_dimension = LweDimension(60);
/// let lwe_count = LweCiphertextCount(25);
/// let polynomial_size = PolynomialSize(32);
/// let glwe_dimension = GlweDimension(2);
/// let lwe_modular_std_dev = StandardDev(0.00000000000000000000001);
/// let lwe_dimension = LweDimension(800);
/// let lwe_count = LweCiphertextCount(100);
/// let polynomial_size = PolynomialSize(256);
/// let glwe_dimension = GlweDimension(4);
/// let lwe_modular_std_dev = StandardDev(0.000003925799891201197);
/// let ciphertext_modulus = CiphertextModulus::new_native();
///
/// let mut seeder = new_seeder();
@@ -32,9 +32,9 @@ use crate::core_crypto::entities::*;
///
/// generate_tpksk_output_glwe_secret_key(&lwe_secret_key, &mut glwe_secret_key);
///
/// let decomp_base_log = DecompositionBaseLog(2);
/// let decomp_level_count = DecompositionLevelCount(8);
/// let var_small = Variance::from_variance(2f64.powf(-90.0));
/// let decomp_base_log = DecompositionBaseLog(3);
/// let decomp_level_count = DecompositionLevelCount(10);
/// let var_small = Variance::from_variance(0.000000000000000000000070406309659297588492321926110929);
/// let mut seeder = new_seeder();
/// let seeder = seeder.as_mut();
/// let mut encryption_generator =
@@ -64,8 +64,8 @@ use crate::core_crypto::entities::*;
/// ciphertext_modulus,
/// );
///
/// let msg = 1u64;
/// let plaintext_list = PlaintextList::new(msg << 56, PlaintextCount(lwe_count.0));
/// let msg = 7u64;
/// let plaintext_list = PlaintextList::new(msg << 59, PlaintextCount(lwe_count.0));
///
/// encrypt_lwe_ciphertext_list(
/// &lwe_secret_key,
@@ -103,8 +103,8 @@ use crate::core_crypto::entities::*;
/// );
///
/// // Round and remove encoding
/// // First create a decomposer working on the high 8 bits corresponding to our encoding.
/// let decomposer = SignedDecomposer::new(DecompositionBaseLog(8), DecompositionLevelCount(1));
/// // First create a decomposer working on the high 5 bits corresponding to our encoding.
/// let decomposer = SignedDecomposer::new(DecompositionBaseLog(5), DecompositionLevelCount(1));
///
/// output_plaintext_list
/// .iter_mut()
@@ -113,11 +113,9 @@ use crate::core_crypto::entities::*;
/// // Get the raw vector
/// let mut cleartext_list = output_plaintext_list.into_container();
/// // Remove the encoding
/// // Due to not having an inverse of 2 the packing multiplies each value by polynomial_size
/// // Hence the encoding delta is multiplied by polynomial_size
/// cleartext_list
/// .iter_mut()
/// .for_each(|elt| *elt = *elt >> 56 + polynomial_size.log2().0);
/// .for_each(|elt| *elt = *elt >> 59);
/// // Get the list immutably
/// let cleartext_list = cleartext_list;
///
@@ -232,6 +230,34 @@ pub fn trace_packing_keyswitch_lwe_ciphertext_list_into_glwe_ciphertext<
if ct_0.as_ref().iter().any(|&x| x != Scalar::ZERO)
|| ct_1.as_ref().iter().any(|&x| x != Scalar::ZERO)
{
// Diving ct_0 and ct_1 by 2
for mut pol in glwe_list.get_mut(i).as_mut_polynomial_list().iter_mut() {
pol.iter_mut().for_each(|coef| {
if *coef % Scalar::TWO != Scalar::ZERO {
// We should really divide by two and round up or down randomly
// i.e. sample a random bit b and do *coef = (coef + (-1)**b) >> 1
// Here, as it is just a POC, we always round down for simplicity
*coef = *coef >> 1
} else {
*coef = *coef >> 1
}
}
)
}
for mut pol in glwe_list.get_mut(j).as_mut_polynomial_list().iter_mut() {
pol.iter_mut().for_each(|coef| {
if *coef % Scalar::TWO != Scalar::ZERO {
// We should really divide by two and round up or down randomly
// i.e. sample a random bit b and do *coef = (coef + (-1)**b) >> 1
// Here, as it is just a POC, we always round down for simplicity
*coef = *coef >> 1
} else {
*coef = *coef >> 1
}
}
)
}
// Rotate ct_1 by N/2^(l+1)
for mut pol in glwe_list.get_mut(j).as_mut_polynomial_list().iter_mut() {
polynomial_wrapping_monic_monomial_mul_assign(
@@ -265,19 +291,6 @@ pub fn trace_packing_keyswitch_lwe_ciphertext_list_into_glwe_ciphertext<
polynomial_wrapping_sub_assign(&mut pol_minus, &pol_1);
}
// Now we should scale both ct_plus and ct_minus by 2^-1 mod q = (q+1) / 2 for odd q
let scalar = Scalar::ONE; // change to (q + 1)/2 for odd q
if !ciphertext_modulus.is_power_of_two() {
// Set scalar to (q + 1)/2
}
for mut pol in ct_plus.as_mut_polynomial_list().iter_mut() {
polynomial_wrapping_scalar_mul_assign(&mut pol, scalar);
}
for mut pol in ct_minus.as_mut_polynomial_list().iter_mut() {
polynomial_wrapping_scalar_mul_assign(&mut pol, scalar);
}
// Apply the automorphism sending X to X^(2^(l+1) + 1) to ct_minus
for mut pol in ct_minus.as_mut_polynomial_list().iter_mut() {
apply_automorphism_assign(&mut pol, 2_usize.pow(l as u32 + 1) + 1)
@@ -319,7 +332,6 @@ pub fn trace_packing_keyswitch_lwe_ciphertext_list_into_glwe_ciphertext<
}
}
let res = glwe_list.get(0);
output_glwe_ciphertext.as_mut().fill(Scalar::ZERO);
for (mut pol_out, pol_res) in output_glwe_ciphertext
.as_mut_polynomial_list()
.iter_mut()