tfhe/core_crypto/algorithms/
lwe_compact_public_key_generation.rs

1//! Module containing primitives pertaining to [`LWE compact public key
2//! generation`](`LweCompactPublicKey`).
3
4use crate::core_crypto::algorithms::*;
5use crate::core_crypto::commons::ciphertext_modulus::CiphertextModulus;
6use crate::core_crypto::commons::generators::EncryptionRandomGenerator;
7use crate::core_crypto::commons::math::random::{Distribution, Uniform};
8use crate::core_crypto::commons::traits::*;
9use crate::core_crypto::entities::*;
10use crate::core_crypto::prelude::DefaultRandomGenerator;
11use slice_algorithms::*;
12
13/// Fill an [`LWE compact public key`](`LweCompactPublicKey`) with an actual public key constructed
14/// from a private [`LWE secret key`](`LweSecretKey`).
15pub fn generate_lwe_compact_public_key<
16    Scalar,
17    NoiseDistribution,
18    InputKeyCont,
19    OutputKeyCont,
20    Gen,
21>(
22    lwe_secret_key: &LweSecretKey<InputKeyCont>,
23    output: &mut LweCompactPublicKey<OutputKeyCont>,
24    noise_distribution: NoiseDistribution,
25    generator: &mut EncryptionRandomGenerator<Gen>,
26) where
27    Scalar: Encryptable<Uniform, NoiseDistribution>,
28    NoiseDistribution: Distribution,
29    InputKeyCont: Container<Element = Scalar>,
30    OutputKeyCont: ContainerMut<Element = Scalar>,
31    Gen: ByteRandomGenerator,
32{
33    assert!(
34        output.ciphertext_modulus().is_native_modulus(),
35        "This operation only supports native moduli"
36    );
37
38    assert!(
39        lwe_secret_key.lwe_dimension() == output.lwe_dimension(),
40        "Mismatched LweDimension between input LweSecretKey {:?} \
41    and output LweCompactPublicKey {:?}",
42        lwe_secret_key.lwe_dimension(),
43        output.lwe_dimension()
44    );
45
46    let (mut mask, mut body) = output.get_mut_mask_and_body();
47    generator.fill_slice_with_random_uniform_mask(mask.as_mut());
48
49    slice_semi_reverse_negacyclic_convolution(
50        body.as_mut(),
51        mask.as_ref(),
52        lwe_secret_key.as_ref(),
53    );
54
55    generator.unsigned_integer_slice_wrapping_add_random_noise_from_distribution_assign(
56        body.as_mut(),
57        noise_distribution,
58    );
59}
60
61/// Allocate a new [`LWE compact public key`](`LweCompactPublicKey`) and fill it with an actual
62/// public key constructed from a private [`LWE secret key`](`LweSecretKey`).
63///
64/// See [`encrypt_lwe_ciphertext_with_compact_public_key`] for usage.
65pub fn allocate_and_generate_new_lwe_compact_public_key<
66    Scalar,
67    NoiseDistribution,
68    InputKeyCont,
69    Gen,
70>(
71    lwe_secret_key: &LweSecretKey<InputKeyCont>,
72    noise_distribution: NoiseDistribution,
73    ciphertext_modulus: CiphertextModulus<Scalar>,
74    generator: &mut EncryptionRandomGenerator<Gen>,
75) -> LweCompactPublicKeyOwned<Scalar>
76where
77    Scalar: Encryptable<Uniform, NoiseDistribution>,
78    NoiseDistribution: Distribution,
79    InputKeyCont: Container<Element = Scalar>,
80    Gen: ByteRandomGenerator,
81{
82    let mut pk = LweCompactPublicKeyOwned::new(
83        Scalar::ZERO,
84        lwe_secret_key.lwe_dimension(),
85        ciphertext_modulus,
86    );
87
88    generate_lwe_compact_public_key(lwe_secret_key, &mut pk, noise_distribution, generator);
89
90    pk
91}
92
93/// Fill a [`seeded LWE compact public key`](`LweCompactPublicKey`) with an actual public key
94/// constructed from a private [`LWE secret key`](`LweSecretKey`).
95pub fn generate_seeded_lwe_compact_public_key<
96    Scalar,
97    NoiseDistribution,
98    InputKeyCont,
99    OutputKeyCont,
100    NoiseSeeder,
101>(
102    lwe_secret_key: &LweSecretKey<InputKeyCont>,
103    output: &mut SeededLweCompactPublicKey<OutputKeyCont>,
104    noise_distribution: NoiseDistribution,
105    noise_seeder: &mut NoiseSeeder,
106) where
107    Scalar: Encryptable<Uniform, NoiseDistribution>,
108    NoiseDistribution: Distribution,
109    InputKeyCont: Container<Element = Scalar>,
110    OutputKeyCont: ContainerMut<Element = Scalar>,
111    // Maybe Sized allows to pass Box<dyn Seeder>.
112    NoiseSeeder: Seeder + ?Sized,
113{
114    let mut generator = EncryptionRandomGenerator::<DefaultRandomGenerator>::new(
115        output.compression_seed().seed,
116        noise_seeder,
117    );
118
119    generate_seeded_lwe_compact_public_key_with_pre_seeded_generator(
120        lwe_secret_key,
121        output,
122        noise_distribution,
123        &mut generator,
124    );
125}
126
127/// Fill a [`seeded LWE compact public key`](`LweCompactPublicKey`) with an actual public key
128/// constructed from a private [`LWE secret key`](`LweSecretKey`).
129///
130/// This uses an already seeded generator
131pub fn generate_seeded_lwe_compact_public_key_with_pre_seeded_generator<
132    Scalar,
133    NoiseDistribution,
134    InputKeyCont,
135    OutputKeyCont,
136    ByteGen,
137>(
138    lwe_secret_key: &LweSecretKey<InputKeyCont>,
139    output: &mut SeededLweCompactPublicKey<OutputKeyCont>,
140    noise_distribution: NoiseDistribution,
141    generator: &mut EncryptionRandomGenerator<ByteGen>,
142) where
143    Scalar: Encryptable<Uniform, NoiseDistribution>,
144    NoiseDistribution: Distribution,
145    InputKeyCont: Container<Element = Scalar>,
146    OutputKeyCont: ContainerMut<Element = Scalar>,
147    ByteGen: ByteRandomGenerator,
148{
149    assert!(
150        output.ciphertext_modulus().is_native_modulus(),
151        "This operation only supports native moduli"
152    );
153
154    assert!(
155        lwe_secret_key.lwe_dimension() == output.lwe_dimension(),
156        "Mismatched LweDimension between input LweSecretKey {:?} \
157    and output LweCompactPublicKey {:?}",
158        lwe_secret_key.lwe_dimension(),
159        output.lwe_dimension()
160    );
161
162    let mut tmp_mask = vec![Scalar::ZERO; output.lwe_dimension().0];
163    generator.fill_slice_with_random_uniform_mask(tmp_mask.as_mut());
164
165    let mut body = output.get_mut_body();
166
167    slice_semi_reverse_negacyclic_convolution(
168        body.as_mut(),
169        tmp_mask.as_ref(),
170        lwe_secret_key.as_ref(),
171    );
172
173    generator.unsigned_integer_slice_wrapping_add_random_noise_from_distribution_assign(
174        body.as_mut(),
175        noise_distribution,
176    );
177}
178
179/// Allocate a new [`seeded LWE compact public key`](`SeededLweCompactPublicKey`) and fill it with
180/// an actual public key constructed from a private [`LWE secret key`](`LweSecretKey`).
181pub fn allocate_and_generate_new_seeded_lwe_compact_public_key<
182    Scalar,
183    NoiseDistribution,
184    InputKeyCont,
185    NoiseSeeder,
186>(
187    lwe_secret_key: &LweSecretKey<InputKeyCont>,
188    noise_distribution: NoiseDistribution,
189    ciphertext_modulus: CiphertextModulus<Scalar>,
190    noise_seeder: &mut NoiseSeeder,
191) -> SeededLweCompactPublicKeyOwned<Scalar>
192where
193    Scalar: Encryptable<Uniform, NoiseDistribution>,
194    NoiseDistribution: Distribution,
195    InputKeyCont: Container<Element = Scalar>,
196    // Maybe Sized allows to pass Box<dyn Seeder>.
197    NoiseSeeder: Seeder + ?Sized,
198{
199    let mut pk = SeededLweCompactPublicKey::new(
200        Scalar::ZERO,
201        lwe_secret_key.lwe_dimension(),
202        noise_seeder.seed().into(),
203        ciphertext_modulus,
204    );
205
206    generate_seeded_lwe_compact_public_key(
207        lwe_secret_key,
208        &mut pk,
209        noise_distribution,
210        noise_seeder,
211    );
212
213    pk
214}