mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-10 15:18:33 -05:00
feat(hlapi): add XofKeySet
This adds a specialized struct that is able to generate keys for the high_level_api in a way that is compatible with the NIST/MPC protocol There are still things to be done in later commits: - Backward compatibility - NIST compliant ClientKey generation
This commit is contained in:
committed by
tmontaigu
parent
7e1c8f7db5
commit
d1c190fac6
@@ -11,6 +11,7 @@ use crate::core_crypto::commons::parameters::*;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use rayon::prelude::*;
|
||||
use tfhe_csprng::seeders::Seed;
|
||||
|
||||
/// Fill an [`LWE bootstrap key`](`LweBootstrapKey`) with an actual bootstrapping key constructed
|
||||
/// from an input key [`LWE secret key`](`LweSecretKey`) and an output key
|
||||
@@ -390,6 +391,41 @@ pub fn generate_seeded_lwe_bootstrap_key<
|
||||
OutputCont: ContainerMut<Element = OutputScalar>,
|
||||
// Maybe Sized allows to pass Box<dyn Seeder>.
|
||||
NoiseSeeder: Seeder + ?Sized,
|
||||
{
|
||||
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
|
||||
output.compression_seed().seed,
|
||||
noise_seeder,
|
||||
);
|
||||
|
||||
generate_seeded_lwe_bootstrap_key_with_pre_seeded_generator(
|
||||
input_lwe_secret_key,
|
||||
output_glwe_secret_key,
|
||||
output,
|
||||
noise_distribution,
|
||||
&mut generator,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn generate_seeded_lwe_bootstrap_key_with_pre_seeded_generator<
|
||||
NoiseDistribution,
|
||||
InputKeyCont,
|
||||
OutputKeyCont,
|
||||
OutputCont,
|
||||
ByteGen,
|
||||
>(
|
||||
input_lwe_secret_key: &LweSecretKey<InputKeyCont>,
|
||||
output_glwe_secret_key: &GlweSecretKey<OutputKeyCont>,
|
||||
output: &mut SeededLweBootstrapKey<OutputCont>,
|
||||
noise_distribution: NoiseDistribution,
|
||||
generator: &mut EncryptionRandomGenerator<ByteGen>,
|
||||
) where
|
||||
NoiseDistribution: Distribution,
|
||||
InputKeyCont: Container,
|
||||
OutputKeyCont: Container,
|
||||
OutputCont: ContainerMut<Element = OutputKeyCont::Element>,
|
||||
InputKeyCont::Element: Copy + CastInto<OutputKeyCont::Element>,
|
||||
OutputKeyCont::Element: Encryptable<Uniform, NoiseDistribution>,
|
||||
ByteGen: ByteRandomGenerator,
|
||||
{
|
||||
assert!(
|
||||
output.input_lwe_dimension() == input_lwe_secret_key.lwe_dimension(),
|
||||
@@ -415,11 +451,6 @@ pub fn generate_seeded_lwe_bootstrap_key<
|
||||
output.polynomial_size()
|
||||
);
|
||||
|
||||
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
|
||||
output.compression_seed().seed,
|
||||
noise_seeder,
|
||||
);
|
||||
|
||||
let gen_iter = generator
|
||||
.try_fork_from_config(output.encryption_fork_config(Uniform, noise_distribution))
|
||||
.unwrap();
|
||||
@@ -492,6 +523,49 @@ where
|
||||
bsk
|
||||
}
|
||||
|
||||
pub fn allocate_and_generate_lwe_bootstrapping_key_with_pre_seeded_generator<
|
||||
LweCont,
|
||||
GlweCont,
|
||||
ByteGen,
|
||||
>(
|
||||
input_lwe_secret_key: &LweSecretKey<LweCont>,
|
||||
output_glwe_secret_key: &GlweSecretKey<GlweCont>,
|
||||
decomp_base_log: DecompositionBaseLog,
|
||||
decomp_level_count: DecompositionLevelCount,
|
||||
noise_distribution: DynamicDistribution<GlweCont::Element>,
|
||||
ciphertext_modulus: CiphertextModulus<GlweCont::Element>,
|
||||
noise_generator: &mut EncryptionRandomGenerator<ByteGen>,
|
||||
) -> SeededLweBootstrapKeyOwned<GlweCont::Element>
|
||||
where
|
||||
LweCont: Container,
|
||||
GlweCont: Container,
|
||||
LweCont::Element: Copy + CastInto<GlweCont::Element>,
|
||||
GlweCont::Element:
|
||||
UnsignedInteger + Encryptable<Uniform, DynamicDistribution<GlweCont::Element>>,
|
||||
ByteGen: ByteRandomGenerator,
|
||||
{
|
||||
let mut lwe_bootstrapping_key = SeededLweBootstrapKeyOwned::new(
|
||||
GlweCont::Element::ZERO,
|
||||
output_glwe_secret_key.glwe_dimension().to_glwe_size(),
|
||||
output_glwe_secret_key.polynomial_size(),
|
||||
decomp_base_log,
|
||||
decomp_level_count,
|
||||
input_lwe_secret_key.lwe_dimension(),
|
||||
CompressionSeed::from(Seed(0)),
|
||||
ciphertext_modulus,
|
||||
);
|
||||
|
||||
generate_seeded_lwe_bootstrap_key_with_pre_seeded_generator(
|
||||
input_lwe_secret_key,
|
||||
output_glwe_secret_key,
|
||||
&mut lwe_bootstrapping_key,
|
||||
noise_distribution,
|
||||
noise_generator,
|
||||
);
|
||||
|
||||
lwe_bootstrapping_key
|
||||
}
|
||||
|
||||
/// Parallel variant of [`generate_seeded_lwe_bootstrap_key`], it is recommended to use this
|
||||
/// function for better key generation times as LWE bootstrapping keys can be quite large.
|
||||
pub fn par_generate_seeded_lwe_bootstrap_key<
|
||||
|
||||
@@ -110,6 +110,41 @@ pub fn generate_seeded_lwe_compact_public_key<
|
||||
OutputKeyCont: ContainerMut<Element = Scalar>,
|
||||
// Maybe Sized allows to pass Box<dyn Seeder>.
|
||||
NoiseSeeder: Seeder + ?Sized,
|
||||
{
|
||||
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
|
||||
output.compression_seed().seed,
|
||||
noise_seeder,
|
||||
);
|
||||
|
||||
generate_seeded_lwe_compact_public_key_with_pre_seeded_generator(
|
||||
lwe_secret_key,
|
||||
output,
|
||||
noise_distribution,
|
||||
&mut generator,
|
||||
);
|
||||
}
|
||||
|
||||
/// Fill a [`seeded LWE compact public key`](`LweCompactPublicKey`) with an actual public key
|
||||
/// constructed from a private [`LWE secret key`](`LweSecretKey`).
|
||||
///
|
||||
/// This uses an already seeded generator
|
||||
pub fn generate_seeded_lwe_compact_public_key_with_pre_seeded_generator<
|
||||
Scalar,
|
||||
NoiseDistribution,
|
||||
InputKeyCont,
|
||||
OutputKeyCont,
|
||||
ByteGen,
|
||||
>(
|
||||
lwe_secret_key: &LweSecretKey<InputKeyCont>,
|
||||
output: &mut SeededLweCompactPublicKey<OutputKeyCont>,
|
||||
noise_distribution: NoiseDistribution,
|
||||
generator: &mut EncryptionRandomGenerator<ByteGen>,
|
||||
) where
|
||||
Scalar: Encryptable<Uniform, NoiseDistribution>,
|
||||
NoiseDistribution: Distribution,
|
||||
InputKeyCont: Container<Element = Scalar>,
|
||||
OutputKeyCont: ContainerMut<Element = Scalar>,
|
||||
ByteGen: ByteRandomGenerator,
|
||||
{
|
||||
assert!(
|
||||
output.ciphertext_modulus().is_native_modulus(),
|
||||
@@ -124,11 +159,6 @@ pub fn generate_seeded_lwe_compact_public_key<
|
||||
output.lwe_dimension()
|
||||
);
|
||||
|
||||
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
|
||||
output.compression_seed().seed,
|
||||
noise_seeder,
|
||||
);
|
||||
|
||||
let mut tmp_mask = vec![Scalar::ZERO; output.lwe_dimension().0];
|
||||
generator.fill_slice_with_random_uniform_mask(tmp_mask.as_mut());
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ use crate::core_crypto::commons::math::random::{
|
||||
use crate::core_crypto::commons::parameters::*;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use tfhe_csprng::seeders::Seed;
|
||||
|
||||
/// Fill an [`LWE keyswitch key`](`LweKeyswitchKey`) with an actual keyswitching key constructed
|
||||
/// from an input and an output key [`LWE secret key`](`LweSecretKey`).
|
||||
@@ -407,6 +408,43 @@ pub fn generate_seeded_lwe_keyswitch_key<
|
||||
KSKeyCont: ContainerMut<Element = OutputScalar>,
|
||||
// Maybe Sized allows to pass Box<dyn Seeder>.
|
||||
NoiseSeeder: Seeder + ?Sized,
|
||||
{
|
||||
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
|
||||
lwe_keyswitch_key.compression_seed().seed,
|
||||
noise_seeder,
|
||||
);
|
||||
|
||||
generate_seeded_lwe_keyswitch_key_with_pre_seeded_generator(
|
||||
input_lwe_sk,
|
||||
output_lwe_sk,
|
||||
lwe_keyswitch_key,
|
||||
noise_distribution,
|
||||
&mut generator,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn generate_seeded_lwe_keyswitch_key_with_pre_seeded_generator<
|
||||
InputScalar,
|
||||
OutputScalar,
|
||||
NoiseDistribution,
|
||||
InputKeyCont,
|
||||
OutputKeyCont,
|
||||
KSKeyCont,
|
||||
ByteGen,
|
||||
>(
|
||||
input_lwe_sk: &LweSecretKey<InputKeyCont>,
|
||||
output_lwe_sk: &LweSecretKey<OutputKeyCont>,
|
||||
lwe_keyswitch_key: &mut SeededLweKeyswitchKey<KSKeyCont>,
|
||||
noise_distribution: NoiseDistribution,
|
||||
generator: &mut EncryptionRandomGenerator<ByteGen>,
|
||||
) where
|
||||
InputScalar: UnsignedInteger + CastInto<OutputScalar>,
|
||||
OutputScalar: Encryptable<Uniform, NoiseDistribution>,
|
||||
NoiseDistribution: Distribution,
|
||||
InputKeyCont: Container<Element = InputScalar>,
|
||||
OutputKeyCont: Container<Element = OutputScalar>,
|
||||
KSKeyCont: ContainerMut<Element = OutputScalar>,
|
||||
ByteGen: ByteRandomGenerator,
|
||||
{
|
||||
assert!(
|
||||
lwe_keyswitch_key.input_key_lwe_dimension() == input_lwe_sk.lwe_dimension(),
|
||||
@@ -439,11 +477,6 @@ pub fn generate_seeded_lwe_keyswitch_key<
|
||||
let mut decomposition_plaintexts_buffer =
|
||||
PlaintextListOwned::new(OutputScalar::ZERO, PlaintextCount(decomp_level_count.0));
|
||||
|
||||
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
|
||||
lwe_keyswitch_key.compression_seed().seed,
|
||||
noise_seeder,
|
||||
);
|
||||
|
||||
// Iterate over the input key elements and the destination lwe_keyswitch_key memory
|
||||
for (input_key_element, mut keyswitch_key_block) in input_lwe_sk
|
||||
.as_ref()
|
||||
@@ -473,7 +506,7 @@ pub fn generate_seeded_lwe_keyswitch_key<
|
||||
&mut keyswitch_key_block,
|
||||
&decomposition_plaintexts_buffer,
|
||||
noise_distribution,
|
||||
&mut generator,
|
||||
generator,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -527,6 +560,44 @@ where
|
||||
new_lwe_keyswitch_key
|
||||
}
|
||||
|
||||
pub fn allocate_and_generate_lwe_key_switching_key_with_pre_seeded_generator<
|
||||
InputLweCont,
|
||||
OutputLweCont,
|
||||
>(
|
||||
input_lwe_secret_key: &LweSecretKey<InputLweCont>,
|
||||
output_lwe_secret_key: &LweSecretKey<OutputLweCont>,
|
||||
decomp_base_log: DecompositionBaseLog,
|
||||
decomp_level_count: DecompositionLevelCount,
|
||||
noise_distribution: DynamicDistribution<InputLweCont::Element>,
|
||||
ciphertext_modulus: CiphertextModulus<InputLweCont::Element>,
|
||||
noise_generator: &mut EncryptionRandomGenerator<DefaultRandomGenerator>,
|
||||
) -> SeededLweKeyswitchKeyOwned<InputLweCont::Element>
|
||||
where
|
||||
InputLweCont: Container,
|
||||
InputLweCont::Element:
|
||||
UnsignedInteger + Encryptable<Uniform, DynamicDistribution<InputLweCont::Element>>,
|
||||
OutputLweCont: Container<Element = InputLweCont::Element>,
|
||||
{
|
||||
let mut key_switching_key = SeededLweKeyswitchKeyOwned::new(
|
||||
InputLweCont::Element::ZERO,
|
||||
decomp_base_log,
|
||||
decomp_level_count,
|
||||
input_lwe_secret_key.lwe_dimension(),
|
||||
output_lwe_secret_key.lwe_dimension(),
|
||||
CompressionSeed::from(Seed(0)),
|
||||
ciphertext_modulus,
|
||||
);
|
||||
generate_seeded_lwe_keyswitch_key_with_pre_seeded_generator(
|
||||
input_lwe_secret_key,
|
||||
output_lwe_secret_key,
|
||||
&mut key_switching_key,
|
||||
noise_distribution,
|
||||
noise_generator,
|
||||
);
|
||||
|
||||
key_switching_key
|
||||
}
|
||||
|
||||
/// A generator for producing chunks of an LWE keyswitch key.
|
||||
///
|
||||
/// This struct allows for the generation of LWE keyswitch key chunks, which can be used to
|
||||
|
||||
@@ -496,6 +496,47 @@ pub fn generate_seeded_lwe_multi_bit_bootstrap_key<
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
// Maybe Sized allows to pass Box<dyn Seeder>.
|
||||
NoiseSeeder: Seeder + ?Sized,
|
||||
{
|
||||
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
|
||||
output.compression_seed().seed,
|
||||
noise_seeder,
|
||||
);
|
||||
|
||||
generate_seeded_lwe_multi_bit_bootstrap_key_with_pre_seeded_generator(
|
||||
input_lwe_secret_key,
|
||||
output_glwe_secret_key,
|
||||
output,
|
||||
noise_distribution,
|
||||
&mut generator,
|
||||
);
|
||||
}
|
||||
|
||||
/// Fill a [`seeded LWE bootstrap key`](`SeededLweMultiBitBootstrapKey`) with an actual seeded
|
||||
/// bootstrapping key constructed from an input key [`LWE secret key`](`LweSecretKey`) and an output
|
||||
/// key [`GLWE secret key`](`GlweSecretKey`)
|
||||
///
|
||||
///
|
||||
/// This uses an already seeded generator
|
||||
pub fn generate_seeded_lwe_multi_bit_bootstrap_key_with_pre_seeded_generator<
|
||||
Scalar,
|
||||
NoiseDistribution,
|
||||
InputKeyCont,
|
||||
OutputKeyCont,
|
||||
OutputCont,
|
||||
ByteGen,
|
||||
>(
|
||||
input_lwe_secret_key: &LweSecretKey<InputKeyCont>,
|
||||
output_glwe_secret_key: &GlweSecretKey<OutputKeyCont>,
|
||||
output: &mut SeededLweMultiBitBootstrapKey<OutputCont>,
|
||||
noise_distribution: NoiseDistribution,
|
||||
generator: &mut EncryptionRandomGenerator<ByteGen>,
|
||||
) where
|
||||
Scalar: Encryptable<Uniform, NoiseDistribution> + CastFrom<usize>,
|
||||
NoiseDistribution: Distribution,
|
||||
InputKeyCont: Container<Element = Scalar>,
|
||||
OutputKeyCont: Container<Element = Scalar>,
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
ByteGen: ByteRandomGenerator,
|
||||
{
|
||||
assert!(
|
||||
output.input_lwe_dimension() == input_lwe_secret_key.lwe_dimension(),
|
||||
@@ -521,11 +562,6 @@ pub fn generate_seeded_lwe_multi_bit_bootstrap_key<
|
||||
output.polynomial_size()
|
||||
);
|
||||
|
||||
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
|
||||
output.compression_seed().seed,
|
||||
noise_seeder,
|
||||
);
|
||||
|
||||
assert!(
|
||||
output.input_lwe_dimension() == input_lwe_secret_key.lwe_dimension(),
|
||||
"Mismatched LweDimension between input LWE secret key and LWE bootstrap key. \
|
||||
|
||||
@@ -205,6 +205,92 @@ where
|
||||
new_lwe_packing_keyswitch_key
|
||||
}
|
||||
|
||||
pub fn generate_seeded_lwe_packing_keyswitch_key_with_pre_seeded_generator<
|
||||
Scalar,
|
||||
NoiseDistribution,
|
||||
InputKeyCont,
|
||||
OutputKeyCont,
|
||||
KSKeyCont,
|
||||
Gen,
|
||||
>(
|
||||
input_lwe_sk: &LweSecretKey<InputKeyCont>,
|
||||
output_glwe_sk: &GlweSecretKey<OutputKeyCont>,
|
||||
lwe_packing_keyswitch_key: &mut SeededLwePackingKeyswitchKey<KSKeyCont>,
|
||||
noise_distribution: NoiseDistribution,
|
||||
generator: &mut EncryptionRandomGenerator<Gen>,
|
||||
) where
|
||||
Scalar: Encryptable<Uniform, NoiseDistribution>,
|
||||
NoiseDistribution: Distribution,
|
||||
InputKeyCont: Container<Element = Scalar>,
|
||||
OutputKeyCont: Container<Element = Scalar>,
|
||||
KSKeyCont: ContainerMut<Element = Scalar>,
|
||||
Gen: ByteRandomGenerator,
|
||||
{
|
||||
assert!(
|
||||
lwe_packing_keyswitch_key.input_key_lwe_dimension() == input_lwe_sk.lwe_dimension(),
|
||||
"The destination LwePackingKeyswitchKey input LweDimension is not equal \
|
||||
to the input LweSecretKey LweDimension. Destination: {:?}, input: {:?}",
|
||||
lwe_packing_keyswitch_key.input_key_lwe_dimension(),
|
||||
input_lwe_sk.lwe_dimension()
|
||||
);
|
||||
assert!(
|
||||
lwe_packing_keyswitch_key.output_key_glwe_dimension() == output_glwe_sk.glwe_dimension(),
|
||||
"The destination LwePackingKeyswitchKey output LweDimension is not equal \
|
||||
to the output GlweSecretKey GlweDimension. Destination: {:?}, output: {:?}",
|
||||
lwe_packing_keyswitch_key.output_key_glwe_dimension(),
|
||||
output_glwe_sk.glwe_dimension()
|
||||
);
|
||||
assert!(
|
||||
lwe_packing_keyswitch_key.output_key_polynomial_size() == output_glwe_sk.polynomial_size(),
|
||||
"The destination LwePackingKeyswitchKey output PolynomialSize is not equal \
|
||||
to the output GlweSecretKey PolynomialSize. Destination: {:?}, output: {:?}",
|
||||
lwe_packing_keyswitch_key.output_key_polynomial_size(),
|
||||
output_glwe_sk.polynomial_size()
|
||||
);
|
||||
|
||||
let decomp_base_log = lwe_packing_keyswitch_key.decomposition_base_log();
|
||||
let decomp_level_count = lwe_packing_keyswitch_key.decomposition_level_count();
|
||||
let polynomial_size = lwe_packing_keyswitch_key.output_polynomial_size();
|
||||
let ciphertext_modulus = lwe_packing_keyswitch_key.ciphertext_modulus();
|
||||
assert!(ciphertext_modulus.is_compatible_with_native_modulus());
|
||||
|
||||
// The plaintexts used to encrypt a key element will be stored in this buffer
|
||||
let mut decomposition_plaintexts_buffer = PlaintextListOwned::new(
|
||||
Scalar::ZERO,
|
||||
PlaintextCount(decomp_level_count.0 * polynomial_size.0),
|
||||
);
|
||||
|
||||
// Iterate over the input key elements and the destination lwe_packing_keyswitch_key memory
|
||||
for (input_key_element, mut packing_keyswitch_key_block) in input_lwe_sk
|
||||
.as_ref()
|
||||
.iter()
|
||||
.zip(lwe_packing_keyswitch_key.iter_mut())
|
||||
{
|
||||
// We fill the buffer with the powers of the key elements
|
||||
for (level, mut messages) in (1..=decomp_level_count.0)
|
||||
.map(DecompositionLevel)
|
||||
.rev()
|
||||
.zip(decomposition_plaintexts_buffer.chunks_exact_mut(polynomial_size.0))
|
||||
{
|
||||
// Here we take the decomposition term from the native torus, bring it to the torus we
|
||||
// are working with by dividing by the scaling factor and the encryption will take care
|
||||
// of mapping that back to the native torus
|
||||
*messages.get_mut(0).0 =
|
||||
DecompositionTerm::new(level, decomp_base_log, *input_key_element)
|
||||
.to_recomposition_summand()
|
||||
.wrapping_div(ciphertext_modulus.get_power_of_two_scaling_to_native_torus());
|
||||
}
|
||||
|
||||
encrypt_seeded_glwe_ciphertext_list_with_pre_seeded_generator(
|
||||
output_glwe_sk,
|
||||
&mut packing_keyswitch_key_block,
|
||||
&decomposition_plaintexts_buffer,
|
||||
noise_distribution,
|
||||
generator,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill an [`LWE keyswitch key`](`SeededLwePackingKeyswitchKey`) with an actual keyswitching key
|
||||
/// constructed from an input [`LWE secret key`](`LweSecretKey`) and an output
|
||||
/// [`GLWE secret key`](`GlweSecretKey`).
|
||||
@@ -281,74 +367,18 @@ pub fn generate_seeded_lwe_packing_keyswitch_key<
|
||||
// Maybe Sized allows to pass Box<dyn Seeder>.
|
||||
NoiseSeeder: Seeder + ?Sized,
|
||||
{
|
||||
assert!(
|
||||
lwe_packing_keyswitch_key.input_key_lwe_dimension() == input_lwe_sk.lwe_dimension(),
|
||||
"The destination LwePackingKeyswitchKey input LweDimension is not equal \
|
||||
to the input LweSecretKey LweDimension. Destination: {:?}, input: {:?}",
|
||||
lwe_packing_keyswitch_key.input_key_lwe_dimension(),
|
||||
input_lwe_sk.lwe_dimension()
|
||||
);
|
||||
assert!(
|
||||
lwe_packing_keyswitch_key.output_key_glwe_dimension() == output_glwe_sk.glwe_dimension(),
|
||||
"The destination LwePackingKeyswitchKey output LweDimension is not equal \
|
||||
to the output GlweSecretKey GlweDimension. Destination: {:?}, output: {:?}",
|
||||
lwe_packing_keyswitch_key.output_key_glwe_dimension(),
|
||||
output_glwe_sk.glwe_dimension()
|
||||
);
|
||||
assert!(
|
||||
lwe_packing_keyswitch_key.output_key_polynomial_size() == output_glwe_sk.polynomial_size(),
|
||||
"The destination LwePackingKeyswitchKey output PolynomialSize is not equal \
|
||||
to the output GlweSecretKey PolynomialSize. Destination: {:?}, output: {:?}",
|
||||
lwe_packing_keyswitch_key.output_key_polynomial_size(),
|
||||
output_glwe_sk.polynomial_size()
|
||||
);
|
||||
|
||||
let decomp_base_log = lwe_packing_keyswitch_key.decomposition_base_log();
|
||||
let decomp_level_count = lwe_packing_keyswitch_key.decomposition_level_count();
|
||||
let polynomial_size = lwe_packing_keyswitch_key.output_polynomial_size();
|
||||
let ciphertext_modulus = lwe_packing_keyswitch_key.ciphertext_modulus();
|
||||
assert!(ciphertext_modulus.is_compatible_with_native_modulus());
|
||||
|
||||
// The plaintexts used to encrypt a key element will be stored in this buffer
|
||||
let mut decomposition_plaintexts_buffer = PlaintextListOwned::new(
|
||||
Scalar::ZERO,
|
||||
PlaintextCount(decomp_level_count.0 * polynomial_size.0),
|
||||
);
|
||||
|
||||
let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
|
||||
lwe_packing_keyswitch_key.compression_seed().seed,
|
||||
noise_seeder,
|
||||
);
|
||||
|
||||
// Iterate over the input key elements and the destination lwe_packing_keyswitch_key memory
|
||||
for (input_key_element, mut packing_keyswitch_key_block) in input_lwe_sk
|
||||
.as_ref()
|
||||
.iter()
|
||||
.zip(lwe_packing_keyswitch_key.iter_mut())
|
||||
{
|
||||
// We fill the buffer with the powers of the key elements
|
||||
for (level, mut messages) in (1..=decomp_level_count.0)
|
||||
.map(DecompositionLevel)
|
||||
.rev()
|
||||
.zip(decomposition_plaintexts_buffer.chunks_exact_mut(polynomial_size.0))
|
||||
{
|
||||
// Here we take the decomposition term from the native torus, bring it to the torus we
|
||||
// are working with by dividing by the scaling factor and the encryption will take care
|
||||
// of mapping that back to the native torus
|
||||
*messages.get_mut(0).0 =
|
||||
DecompositionTerm::new(level, decomp_base_log, *input_key_element)
|
||||
.to_recomposition_summand()
|
||||
.wrapping_div(ciphertext_modulus.get_power_of_two_scaling_to_native_torus());
|
||||
}
|
||||
|
||||
encrypt_seeded_glwe_ciphertext_list_with_pre_seeded_generator(
|
||||
output_glwe_sk,
|
||||
&mut packing_keyswitch_key_block,
|
||||
&decomposition_plaintexts_buffer,
|
||||
noise_distribution,
|
||||
&mut generator,
|
||||
);
|
||||
}
|
||||
generate_seeded_lwe_packing_keyswitch_key_with_pre_seeded_generator(
|
||||
input_lwe_sk,
|
||||
output_glwe_sk,
|
||||
lwe_packing_keyswitch_key,
|
||||
noise_distribution,
|
||||
&mut generator,
|
||||
)
|
||||
}
|
||||
|
||||
/// Allocate a new [`seeded LWE keyswitch key`](`SeededLwePackingKeyswitchKey`) and fill it with an
|
||||
|
||||
@@ -110,6 +110,14 @@ impl<G: ByteRandomGenerator> EncryptionRandomGenerator<G> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "integer", test))]
|
||||
pub(crate) fn from_raw_parts(
|
||||
mask: MaskRandomGenerator<G>,
|
||||
noise: NoiseRandomGenerator<G>,
|
||||
) -> Self {
|
||||
Self { mask, noise }
|
||||
}
|
||||
|
||||
/// Return the number of remaining bytes for the mask generator, if the generator is bounded.
|
||||
pub fn remaining_bytes(&self) -> Option<usize> {
|
||||
self.mask.remaining_bytes()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use crate::conformance::ParameterSetConformant;
|
||||
use crate::core_crypto::algorithms::*;
|
||||
use crate::core_crypto::backward_compatibility::entities::seeded_lwe_packing_keyswitch_key::SeededLwePackingKeyswitchKeyVersions;
|
||||
use crate::core_crypto::commons::generators::MaskRandomGenerator;
|
||||
use crate::core_crypto::commons::math::random::{CompressionSeed, DefaultRandomGenerator};
|
||||
use crate::core_crypto::commons::parameters::*;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
@@ -303,6 +304,35 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> SeededLwePackingKe
|
||||
decompressed_pksk
|
||||
}
|
||||
|
||||
/// Decompress the [`SeededLwePackingKeyswitchKey`] into [`LwePackingKeyswitchKey`]
|
||||
/// without consuming `self`
|
||||
pub fn decompress_to_lwe_packing_keyswitch_key_with_pre_seeded_generator<Gen>(
|
||||
&self,
|
||||
generator: &mut MaskRandomGenerator<Gen>,
|
||||
) -> LwePackingKeyswitchKeyOwned<Scalar>
|
||||
where
|
||||
Scalar: UnsignedTorus,
|
||||
Gen: ByteRandomGenerator,
|
||||
{
|
||||
let mut decompressed_pksk = LwePackingKeyswitchKeyOwned::new(
|
||||
Scalar::ZERO,
|
||||
self.decomposition_base_log(),
|
||||
self.decomposition_level_count(),
|
||||
self.input_key_lwe_dimension(),
|
||||
self.output_key_glwe_dimension(),
|
||||
self.output_key_polynomial_size(),
|
||||
self.ciphertext_modulus(),
|
||||
);
|
||||
|
||||
decompress_seeded_lwe_packing_keyswitch_key_with_pre_seeded_generator(
|
||||
&mut decompressed_pksk,
|
||||
self,
|
||||
generator,
|
||||
);
|
||||
|
||||
decompressed_pksk
|
||||
}
|
||||
|
||||
pub fn as_seeded_glwe_ciphertext_list(&self) -> SeededGlweCiphertextListView<'_, Scalar> {
|
||||
SeededGlweCiphertextListView::from_container(
|
||||
self.as_ref(),
|
||||
|
||||
@@ -46,7 +46,7 @@ macro_rules! export_concrete_array_types {
|
||||
};
|
||||
}
|
||||
|
||||
pub use crate::core_crypto::commons::math::random::Seed;
|
||||
pub use crate::core_crypto::commons::math::random::{Seed, XofSeed};
|
||||
pub use crate::integer::server_key::MatchValues;
|
||||
use crate::{error, Error, Versionize};
|
||||
use backward_compatibility::compressed_ciphertext_list::SquashedNoiseCiphertextStateVersions;
|
||||
@@ -137,6 +137,7 @@ pub use re_randomization::{
|
||||
pub use strings::ascii::{EncryptableString, FheAsciiString, FheStringIsEmpty, FheStringLen};
|
||||
pub use tag::Tag;
|
||||
pub use traits::FheId;
|
||||
pub mod xof_key_set;
|
||||
|
||||
mod booleans;
|
||||
mod compressed_ciphertext_list;
|
||||
|
||||
1193
tfhe/src/high_level_api/xof_key_set.rs
Normal file
1193
tfhe/src/high_level_api/xof_key_set.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -49,6 +49,12 @@ impl Named for NoiseSquashingPrivateKey {
|
||||
const NAME: &'static str = "integer::NoiseSquashingPrivateKey";
|
||||
}
|
||||
|
||||
impl NoiseSquashingPrivateKey {
|
||||
pub fn noise_squashing_parameters(&self) -> NoiseSquashingParameters {
|
||||
self.key.noise_squashing_parameters()
|
||||
}
|
||||
}
|
||||
|
||||
impl CompressedNoiseSquashingKey {
|
||||
pub fn decompress(&self) -> NoiseSquashingKey {
|
||||
NoiseSquashingKey {
|
||||
|
||||
@@ -120,6 +120,11 @@ impl CompressedStandardAtomicPatternServerKey {
|
||||
&self.bootstrapping_key
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "integer", test))]
|
||||
pub(crate) fn bootstrapping_key_mut(&mut self) -> &mut ShortintCompressedBootstrappingKey<u64> {
|
||||
&mut self.bootstrapping_key
|
||||
}
|
||||
|
||||
pub fn pbs_order(&self) -> PBSOrder {
|
||||
self.pbs_order
|
||||
}
|
||||
|
||||
@@ -109,12 +109,6 @@ pub struct CompressedNoiseSquashingKey {
|
||||
output_ciphertext_modulus: CoreCiphertextModulus<u128>,
|
||||
}
|
||||
|
||||
impl CompressedNoiseSquashingKey {
|
||||
pub fn bootstrapping_key(&self) -> &CompressedShortint128BootstrappingKey {
|
||||
&self.bootstrapping_key
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientKey {
|
||||
pub fn new_compressed_noise_squashing_key(
|
||||
&self,
|
||||
@@ -243,6 +237,10 @@ impl CompressedNoiseSquashingKey {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn bootstrapping_key(&self) -> &CompressedShortint128BootstrappingKey {
|
||||
&self.bootstrapping_key
|
||||
}
|
||||
|
||||
pub fn message_modulus(&self) -> MessageModulus {
|
||||
self.message_modulus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user