Skip to content

Commit 738f8b9

Browse files
committed
feat(CompressedXofKeySet): impl key gen of ClientKey
This adds the implemention of the ClientKey generation that respects the threshold specs, some points are: * 2 random generators are used one for everything public (masks) the other for everything private (private keys and noise). These generators are seeded once. * binary secret keys are generated using `fill_slice_with_random_uniform_binary_bits` and support pmax param
1 parent 58ae2f5 commit 738f8b9

File tree

7 files changed

+729
-304
lines changed

7 files changed

+729
-304
lines changed

tfhe/src/core_crypto/algorithms/glwe_secret_key_generation.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Module containing primitives pertaining to the generation of
22
//! [`GLWE secret keys`](`GlweSecretKey`).
33
4+
use std::ops::RangeInclusive;
5+
46
use crate::core_crypto::commons::generators::SecretRandomGenerator;
57
use crate::core_crypto::commons::math::random::{RandomGenerable, UniformBinary};
68
use crate::core_crypto::commons::parameters::*;
@@ -67,3 +69,77 @@ pub fn generate_binary_glwe_secret_key<Scalar, InCont, Gen>(
6769
{
6870
generator.fill_slice_with_random_uniform_binary(glwe_secret_key.as_mut());
6971
}
72+
73+
/// Fill a [`GLWE secret key`](`GlweSecretKey`) with uniformly random binary coefficients.
74+
///
75+
/// The hamming weight of the secret key will be in: `(1-pmax)*len..=pmax*len`
76+
/// where pmax is in ]0.5, 1.0]
77+
///
78+
/// # Panics
79+
///
80+
/// Panics if pmax <= 0.5 or pmax > 1.0
81+
///
82+
/// # Example
83+
///
84+
/// ```rust
85+
/// use tfhe::core_crypto::prelude::*;
86+
///
87+
/// // DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct
88+
/// // computations
89+
/// // Define parameters for GlweSecretKey creation
90+
/// let glwe_size = GlweSize(2);
91+
/// let polynomial_size = PolynomialSize(1024);
92+
///
93+
/// // Create the PRNG
94+
/// let mut seeder = new_seeder();
95+
/// let seeder = seeder.as_mut();
96+
/// let mut secret_generator = SecretRandomGenerator::<DefaultRandomGenerator>::new(seeder.seed());
97+
/// let pmax = 0.7;
98+
///
99+
/// let mut glwe_secret_key =
100+
/// GlweSecretKey::new_empty_key(0u64, glwe_size.to_glwe_dimension(), polynomial_size);
101+
///
102+
/// generate_binary_glwe_secret_key_with_bounded_hamming_weight(
103+
/// &mut glwe_secret_key,
104+
/// &mut secret_generator,
105+
/// pmax,
106+
/// );
107+
///
108+
/// // Check all coefficients are not zero as we just generated a new key
109+
/// assert!(!glwe_secret_key.as_ref().iter().all(|&elt| elt == 0));
110+
/// ```
111+
pub fn generate_binary_glwe_secret_key_with_bounded_hamming_weight<Scalar, InCont, Gen>(
112+
glwe_secret_key: &mut GlweSecretKey<InCont>,
113+
generator: &mut SecretRandomGenerator<Gen>,
114+
pmax: f64,
115+
) where
116+
Scalar: UnsignedInteger + RandomGenerable<UniformBinary>,
117+
InCont: ContainerMut<Element = Scalar>,
118+
Gen: ByteRandomGenerator,
119+
{
120+
assert!(
121+
0.5 < pmax && pmax <= 1.0,
122+
"pmax parameter must be in ]0.5, 1.0]"
123+
);
124+
125+
let bounds = RangeInclusive::new(
126+
((1.0 - pmax) * glwe_secret_key.polynomial_size().0 as f64) as u128,
127+
(pmax * glwe_secret_key.polynomial_size().0 as f64) as u128,
128+
);
129+
130+
for mut secret_poly in glwe_secret_key.as_mut_polynomial_list().iter_mut() {
131+
loop {
132+
generator.fill_slice_with_random_uniform_binary_bits(secret_poly.as_mut());
133+
let hamming_weight = secret_poly
134+
.as_ref()
135+
.iter()
136+
.copied()
137+
.map(|bit| -> u128 { bit.cast_into() })
138+
.sum::<u128>();
139+
140+
if bounds.contains(&hamming_weight) {
141+
break;
142+
}
143+
}
144+
}
145+
}

tfhe/src/core_crypto/algorithms/lwe_secret_key_generation.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Module containing primitives pertaining to the generation of
22
//! [`LWE secret keys`](`LweSecretKey`).
33
4+
use std::ops::RangeInclusive;
5+
46
use crate::core_crypto::commons::generators::SecretRandomGenerator;
57
use crate::core_crypto::commons::math::random::{RandomGenerable, UniformBinary};
68
use crate::core_crypto::commons::parameters::*;
@@ -62,3 +64,72 @@ pub fn generate_binary_lwe_secret_key<Scalar, InCont, Gen>(
6264
{
6365
generator.fill_slice_with_random_uniform_binary(lwe_secret_key.as_mut());
6466
}
67+
68+
/// Fill an [`LWE secret key`](`LweSecretKey`) with uniformly random binary coefficients.
69+
///
70+
/// The hamming weight of the secret key will be in: `(1-pmax)*len..=pmax*len`
71+
/// where pmax is in ]0.5, 1.0]
72+
///
73+
/// # Panics
74+
///
75+
/// Panics if pmax <= 0.5 or pmax > 1.0
76+
///
77+
/// # Example
78+
///
79+
/// ```rust
80+
/// use tfhe::core_crypto::prelude::*;
81+
///
82+
/// // DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct
83+
/// // computations
84+
/// // Define parameters for LweCiphertext creation
85+
/// let lwe_dimension = LweDimension(742);
86+
///
87+
/// // Create the PRNG
88+
/// let mut seeder = new_seeder();
89+
/// let seeder = seeder.as_mut();
90+
/// let mut secret_generator = SecretRandomGenerator::<DefaultRandomGenerator>::new(seeder.seed());
91+
/// let pmax = 0.7;
92+
/// let mut lwe_secret_key = LweSecretKey::new_empty_key(0u64, lwe_dimension);
93+
///
94+
/// generate_binary_lwe_secret_key_with_bounded_hamming_weight(
95+
/// &mut lwe_secret_key,
96+
/// &mut secret_generator,
97+
/// pmax,
98+
/// );
99+
///
100+
/// // Check all coefficients are not zero as we just generated a new key
101+
/// assert!(!lwe_secret_key.as_ref().iter().all(|&elt| elt == 0));
102+
/// ```
103+
pub fn generate_binary_lwe_secret_key_with_bounded_hamming_weight<Scalar, InCont, Gen>(
104+
lwe_secret_key: &mut LweSecretKey<InCont>,
105+
generator: &mut SecretRandomGenerator<Gen>,
106+
pmax: f64,
107+
) where
108+
Scalar: RandomGenerable<UniformBinary> + UnsignedInteger,
109+
InCont: ContainerMut<Element = Scalar>,
110+
Gen: ByteRandomGenerator,
111+
{
112+
assert!(
113+
0.5 < pmax && pmax <= 1.0,
114+
"pmax parameter must be in ]0.5, 1.0]"
115+
);
116+
117+
let bounds = RangeInclusive::new(
118+
((1.0 - pmax) * lwe_secret_key.lwe_dimension().0 as f64) as u128,
119+
(pmax * lwe_secret_key.lwe_dimension().0 as f64) as u128,
120+
);
121+
122+
loop {
123+
generator.fill_slice_with_random_uniform_binary_bits(lwe_secret_key.as_mut());
124+
let hamming_weight = lwe_secret_key
125+
.as_ref()
126+
.iter()
127+
.copied()
128+
.map(|bit| -> u128 { bit.cast_into() })
129+
.sum::<u128>();
130+
131+
if bounds.contains(&hamming_weight) {
132+
break;
133+
}
134+
}
135+
}

tfhe/src/core_crypto/commons/generators/encryption/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl<G: ByteRandomGenerator> EncryptionRandomGenerator<G> {
110110
}
111111
}
112112

113-
#[cfg(all(feature = "integer", test))]
113+
#[cfg(feature = "integer")]
114114
pub(crate) fn from_raw_parts(
115115
mask: MaskRandomGenerator<G>,
116116
noise: NoiseRandomGenerator<G>,

tfhe/src/core_crypto/commons/generators/encryption/noise_random_generator.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ impl<G: ByteRandomGenerator> NoiseRandomGenerator<G> {
108108
}
109109
}
110110

111+
pub fn from_raw_parts(gen: RandomGenerator<G>) -> Self {
112+
Self { gen }
113+
}
114+
111115
/// Create a new [`NoiseRandomGenerator`], using the provided seed
112116
pub fn new_from_seed(seed: impl Into<SeedKind>) -> Self {
113117
Self {

tfhe/src/core_crypto/commons/generators/secret.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,30 @@
11
//! Module containing primitives pertaining to random generation in the context of secret key
22
//! generation.
33
4+
use tfhe_csprng::seeders::SeedKind;
5+
46
use crate::core_crypto::commons::math::random::{
5-
ByteRandomGenerator, RandomGenerable, RandomGenerator, Seed, UniformBinary,
7+
ByteRandomGenerator, RandomGenerable, RandomGenerator, UniformBinary,
68
};
9+
use crate::core_crypto::prelude::UnsignedInteger;
710

811
/// A random number generator which can be used to generate secret keys.
912
pub struct SecretRandomGenerator<G: ByteRandomGenerator>(RandomGenerator<G>);
1013

1114
impl<G: ByteRandomGenerator> SecretRandomGenerator<G> {
1215
/// Create a new generator, optionally seeding it with the given value.
13-
pub fn new(seed: Seed) -> Self {
16+
pub fn new(seed: impl Into<SeedKind>) -> Self {
1417
Self(RandomGenerator::new(seed))
1518
}
1619

20+
pub fn from_raw_parts(inner: RandomGenerator<G>) -> Self {
21+
Self(inner)
22+
}
23+
24+
pub fn into_raw_parts(self) -> RandomGenerator<G> {
25+
self.0
26+
}
27+
1728
/// Return the number of remaining bytes, if the generator is bounded.
1829
pub fn remaining_bytes(&self) -> Option<usize> {
1930
self.0.remaining_bytes()
@@ -32,4 +43,11 @@ impl<G: ByteRandomGenerator> SecretRandomGenerator<G> {
3243
{
3344
self.0.random_uniform_binary()
3445
}
46+
47+
pub fn fill_slice_with_random_uniform_binary_bits<Scalar>(&mut self, output: &mut [Scalar])
48+
where
49+
Scalar: UnsignedInteger,
50+
{
51+
self.0.fill_slice_with_random_uniform_binary_bits(output);
52+
}
3553
}

tfhe/src/core_crypto/entities/glwe_secret_key.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ impl<Scalar: UnsignedInteger, C: ContainerMut<Element = Scalar>> GlweSecretKey<C
149149
let polynomial_size = self.polynomial_size;
150150
GlweSecretKey::from_container(self.as_mut(), polynomial_size)
151151
}
152+
153+
/// Interpret the [`GlweSecretKey`] as a [`PolynomialListMutView`].
154+
pub fn as_mut_polynomial_list(&mut self) -> PolynomialListMutView<'_, C::Element> {
155+
let poly_size = self.polynomial_size;
156+
PolynomialListMutView::from_container(self.as_mut(), poly_size)
157+
}
152158
}
153159

154160
/// A [`GlweSecretKey`] owning the memory for its own storage.

0 commit comments

Comments
 (0)