From 93ff6992e2c5409fb41568fb91fbea9560805358 Mon Sep 17 00:00:00 2001 From: "Mayeul@Zama" <69792125+mayeul-zama@users.noreply.github.com> Date: Thu, 1 Aug 2024 18:19:44 +0200 Subject: [PATCH] refactor(all): refactor oprf integer and hl APIs --- tfhe/benches/integer/oprf.rs | 12 +- tfhe/c_api_tests/test_high_level_integers.c | 6 +- tfhe/docs/fundamentals/encrypted-prf.md | 36 +++- tfhe/src/c_api/high_level_api/integers.rs | 32 ++- tfhe/src/high_level_api/integers/oprf.rs | 112 +++++++++-- tfhe/src/high_level_api/mod.rs | 1 - tfhe/src/integer/oprf.rs | 211 ++++++++++++++------ 7 files changed, 299 insertions(+), 111 deletions(-) diff --git a/tfhe/benches/integer/oprf.rs b/tfhe/benches/integer/oprf.rs index 43dc84663f..163fb45efb 100644 --- a/tfhe/benches/integer/oprf.rs +++ b/tfhe/benches/integer/oprf.rs @@ -19,11 +19,13 @@ pub fn unsigned_oprf(c: &mut Criterion) { let bench_id = format!("{}::{}::{}_bits", bench_name, param.name(), bit_size); bench_group.bench_function(&bench_id, |b| { b.iter(|| { - _ = black_box(sk.par_generate_oblivious_pseudo_random_unsigned_integer( - Seed(0), - bit_size as u64, - num_block as u64, - )); + _ = black_box( + sk.par_generate_oblivious_pseudo_random_unsigned_integer_bounded( + Seed(0), + bit_size as u64, + num_block as u64, + ), + ); }) }); diff --git a/tfhe/c_api_tests/test_high_level_integers.c b/tfhe/c_api_tests/test_high_level_integers.c index f3fcbb020d..80183b2a85 100644 --- a/tfhe/c_api_tests/test_high_level_integers.c +++ b/tfhe/c_api_tests/test_high_level_integers.c @@ -599,7 +599,7 @@ void test_oprf(const ClientKey *client_key) { fhe_uint8_destroy(ct); - status = generate_oblivious_pseudo_random_bits_fhe_uint8(&ct, 0, 0, 2); + status = generate_oblivious_pseudo_random_bounded_fhe_uint8(&ct, 0, 0, 2); assert(status == 0); status = fhe_uint8_decrypt(ct, client_key, &decrypted); @@ -613,7 +613,7 @@ void test_oprf(const ClientKey *client_key) { { FheInt8 *ct = NULL; - int status = generate_oblivious_pseudo_random_full_signed_range_fhe_int8(&ct, 0, 0); + int status = generate_oblivious_pseudo_random_fhe_int8(&ct, 0, 0); assert(status == 0); int8_t decrypted; @@ -623,7 +623,7 @@ void test_oprf(const ClientKey *client_key) { fhe_int8_destroy(ct); - status = generate_oblivious_pseudo_random_unsigned_fhe_int8(&ct, 0, 0, 2); + status = generate_oblivious_pseudo_random_bounded_fhe_int8(&ct, 0, 0, 2); assert(status == 0); status = fhe_int8_decrypt(ct, client_key, &decrypted); diff --git a/tfhe/docs/fundamentals/encrypted-prf.md b/tfhe/docs/fundamentals/encrypted-prf.md index 0567e3e5af..1e4abd43c4 100644 --- a/tfhe/docs/fundamentals/encrypted-prf.md +++ b/tfhe/docs/fundamentals/encrypted-prf.md @@ -1,10 +1,24 @@ # Generate encrypted pseudo random values -This document gives an example of generating pseudo random values in FHE that are not known by the server. +This document explains the mechanism and steps to generate an oblivious encrypted random value using only server keys. + +The goal is to give to the server the possibility to generate a random value, which will be obtained in an encrypted format and will remain unknown to the server. The implementation is based on [this article](https://eprint.iacr.org/2024/665). + +This is possible through two methods on `FheUint` and `FheInt`: +- `generate_oblivious_pseudo_random` which return an integer taken uniformly in the full integer range (`[0; 2^N[` for a `FheUintN` and `[-2^(N-1); 2^(N-1)[` for a `FheIntN`). +- `generate_oblivious_pseudo_random_bounded` which return an integer taken uniformly in `[0; 2^random_bits_count[`. For a `FheUintN`, we must have `random_bits_count <= N`. For a `FheIntN`, we must have `random_bits_count <= N - 1`. + +Both methods functions take a seed `Seed` as input, which could be any `u128` value. +They both rely on the use of the usual server key. +The output is reproducible, i.e., the function is deterministic from the inputs: assuming the same hardware, seed and server key, this function outputs the same random encrypted value. + + +Here is an example of the usage: + ```rust use tfhe::prelude::FheDecrypt; -use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheUint8, Seed}; +use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheUint8, FheInt8, Seed}; pub fn main() { let config = ConfigBuilder::default().build(); @@ -14,12 +28,22 @@ pub fn main() { let random_bits_count = 3; - // You can pass a 128 bits Seed here - // The generated values will always be the same for a given server key - // The server cannot know what value was generated - let ct_res = FheUint8::generate_oblivious_pseudo_random(Seed(0), random_bits_count); + let ct_res = FheUint8::generate_oblivious_pseudo_random(Seed(0)); let dec_result: u8 = ct_res.decrypt(&client_key); + + let ct_res = FheUint8::generate_oblivious_pseudo_random_bounded(Seed(0), random_bits_count); + + let dec_result: u8 = ct_res.decrypt(&client_key); + assert!(dec_result < (1 << random_bits_count)); + + let ct_res = FheInt8::generate_oblivious_pseudo_random(Seed(0)); + + let dec_result: i8 = ct_res.decrypt(&client_key); + + let ct_res = FheInt8::generate_oblivious_pseudo_random_bounded(Seed(0), random_bits_count); + + let dec_result: i8 = ct_res.decrypt(&client_key); assert!(dec_result < (1 << random_bits_count)); } ``` diff --git a/tfhe/src/c_api/high_level_api/integers.rs b/tfhe/src/c_api/high_level_api/integers.rs index b038cf5b6e..a6d73ce144 100644 --- a/tfhe/src/c_api/high_level_api/integers.rs +++ b/tfhe/src/c_api/high_level_api/integers.rs @@ -491,7 +491,6 @@ macro_rules! impl_oprf_for_uint { seed_low_bytes: u64, seed_high_bytes: u64, ) -> c_int { - use crate::high_level_api::IntegerId; $crate::c_api::utils::catch_panic(|| { let seed_low_bytes: u128 = seed_low_bytes.into(); let seed_high_bytes: u128 = seed_high_bytes.into(); @@ -499,7 +498,6 @@ macro_rules! impl_oprf_for_uint { let result = crate::FheUint::generate_oblivious_pseudo_random( seed, - ] as IntegerId>::num_bits() as u64 ); *out_result = Box::into_raw(Box::new($name(result))); }) @@ -508,7 +506,7 @@ macro_rules! impl_oprf_for_uint { ::paste::paste! { #[no_mangle] - pub unsafe extern "C" fn []( + pub unsafe extern "C" fn []( out_result: *mut *mut $name, seed_low_bytes: u64, seed_high_bytes: u64, @@ -520,7 +518,7 @@ macro_rules! impl_oprf_for_uint { let seed_high_bytes: u128 = seed_high_bytes.into(); let seed = crate::Seed((seed_high_bytes << 64) | seed_low_bytes); - let result = crate::FheUint::generate_oblivious_pseudo_random(seed, random_bits_count); + let result = crate::FheUint::generate_oblivious_pseudo_random_bounded(seed, random_bits_count); *out_result = Box::into_raw(Box::new($name(result))); }) } @@ -532,27 +530,21 @@ macro_rules! impl_oprf_for_int { ( name: $name:ident ) => { - ::paste::paste! { #[no_mangle] - pub unsafe extern "C" fn []( + pub unsafe extern "C" fn []( out_result: *mut *mut $name, seed_low_bytes: u64, seed_high_bytes: u64, - random_bits_count: u64, ) -> c_int { $crate::c_api::utils::catch_panic(|| { let seed_low_bytes: u128 = seed_low_bytes.into(); let seed_high_bytes: u128 = seed_high_bytes.into(); let seed = crate::Seed((seed_high_bytes << 64) | seed_low_bytes); - let result = - crate::FheInt::generate_oblivious_pseudo_random( - seed, - crate::high_level_api::SignedRandomizationSpec::Unsigned { - random_bits_count - }, - ); + let result = crate::FheInt::generate_oblivious_pseudo_random( + seed, + ); *out_result = Box::into_raw(Box::new($name(result))); }) } @@ -560,20 +552,22 @@ macro_rules! impl_oprf_for_int { ::paste::paste! { #[no_mangle] - pub unsafe extern "C" fn []( + pub unsafe extern "C" fn []( out_result: *mut *mut $name, seed_low_bytes: u64, seed_high_bytes: u64, + random_bits_count: u64, ) -> c_int { $crate::c_api::utils::catch_panic(|| { let seed_low_bytes: u128 = seed_low_bytes.into(); let seed_high_bytes: u128 = seed_high_bytes.into(); let seed = crate::Seed((seed_high_bytes << 64) | seed_low_bytes); - let result = crate::FheInt::generate_oblivious_pseudo_random( - seed, - crate::high_level_api::SignedRandomizationSpec::FullSigned, - ); + let result = + crate::FheInt::generate_oblivious_pseudo_random_bounded( + seed, + random_bits_count, + ); *out_result = Box::into_raw(Box::new($name(result))); }) } diff --git a/tfhe/src/high_level_api/integers/oprf.rs b/tfhe/src/high_level_api/integers/oprf.rs index 360b390dfa..4ee3ec1049 100644 --- a/tfhe/src/high_level_api/integers/oprf.rs +++ b/tfhe/src/high_level_api/integers/oprf.rs @@ -1,14 +1,49 @@ use super::{FheIntId, FheUintId}; use crate::high_level_api::global_state; use crate::high_level_api::keys::InternalServerKey; -use crate::integer::oprf::SignedRandomizationSpec; use crate::{FheInt, FheUint, Seed}; impl FheUint { + /// Generates an encrypted unsigned integer + /// taken uniformly in its full range using the given seed. + /// The encryted value is oblivious to the server. + /// It can be useful to make server random generation deterministic. + /// + /// ```rust + /// use tfhe::prelude::FheDecrypt; + /// use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheUint8, Seed}; + /// + /// let config = ConfigBuilder::default().build(); + /// let (client_key, server_key) = generate_keys(config); + /// + /// set_server_key(server_key); + /// + /// let ct_res = FheUint8::generate_oblivious_pseudo_random(Seed(0)); + /// + /// let dec_result: u16 = ct_res.decrypt(&client_key); + /// ``` + pub fn generate_oblivious_pseudo_random(seed: Seed) -> Self { + global_state::with_internal_keys(|key| match key { + InternalServerKey::Cpu(key) => { + let ct = key + .pbs_key() + .par_generate_oblivious_pseudo_random_unsigned_integer( + seed, + Id::num_blocks(key.message_modulus()) as u64, + ); + + Self::new(ct, key.tag.clone()) + } + #[cfg(feature = "gpu")] + InternalServerKey::Cuda(_) => { + todo!("Cuda devices do not yet support oblivious pseudo random generation") + } + }) + } /// Generates an encrypted `num_block` blocks unsigned integer - /// taken uniformly in `[0, 2^random_bits_count[` using the given seed - /// The encryted value is oblivious to the server - /// It can be useful to make server random generation deterministic + /// taken uniformly in `[0, 2^random_bits_count[` using the given seed. + /// The encryted value is oblivious to the server. + /// It can be useful to make server random generation deterministic. /// /// ```rust /// use tfhe::prelude::FheDecrypt; @@ -21,17 +56,17 @@ impl FheUint { /// /// let random_bits_count = 3; /// - /// let ct_res = FheUint8::generate_oblivious_pseudo_random(Seed(0), random_bits_count); + /// let ct_res = FheUint8::generate_oblivious_pseudo_random_bounded(Seed(0), random_bits_count); /// /// let dec_result: u16 = ct_res.decrypt(&client_key); /// assert!(dec_result < (1 << random_bits_count)); /// ``` - pub fn generate_oblivious_pseudo_random(seed: Seed, random_bits_count: u64) -> Self { + pub fn generate_oblivious_pseudo_random_bounded(seed: Seed, random_bits_count: u64) -> Self { global_state::with_internal_keys(|key| match key { InternalServerKey::Cpu(key) => { let ct = key .pbs_key() - .par_generate_oblivious_pseudo_random_unsigned_integer( + .par_generate_oblivious_pseudo_random_unsigned_integer_bounded( seed, random_bits_count, Id::num_blocks(key.message_modulus()) as u64, @@ -48,40 +83,33 @@ impl FheUint { } impl FheInt { - /// Generates an encrypted `num_block` blocks signed integer - /// using the given seed following the randomizer spec - /// The encryted value is oblivious to the server - /// It can be useful to make server random generation deterministic + /// Generates an encrypted signed integer + /// taken uniformly in its full range using the given seed. + /// The encryted value is oblivious to the server. + /// It can be useful to make server random generation deterministic. /// /// ```rust /// use tfhe::prelude::FheDecrypt; - /// use tfhe::{ - /// generate_keys, set_server_key, ConfigBuilder, FheInt8, Seed, SignedRandomizationSpec, - /// }; + /// use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheInt8, Seed}; /// /// let config = ConfigBuilder::default().build(); /// let (client_key, server_key) = generate_keys(config); /// /// set_server_key(server_key); /// - /// let ct_res = - /// FheInt8::generate_oblivious_pseudo_random(Seed(0), SignedRandomizationSpec::FullSigned); + /// let ct_res = FheInt8::generate_oblivious_pseudo_random(Seed(0)); /// /// let dec_result: i16 = ct_res.decrypt(&client_key); /// assert!(dec_result < 1 << 7); /// assert!(dec_result >= -(1 << 7)); /// ``` - pub fn generate_oblivious_pseudo_random( - seed: Seed, - randomizer: SignedRandomizationSpec, - ) -> Self { + pub fn generate_oblivious_pseudo_random(seed: Seed) -> Self { global_state::with_internal_keys(|key| match key { InternalServerKey::Cpu(key) => { let ct = key .pbs_key() .par_generate_oblivious_pseudo_random_signed_integer( seed, - randomizer, Id::num_blocks(key.message_modulus()) as u64, ); Self::new(ct, key.tag.clone()) @@ -92,4 +120,46 @@ impl FheInt { } }) } + + /// Generates an encrypted `num_block` blocks signed integer + /// taken uniformly in `[0, 2^random_bits_count[` using the given seed. + /// The encryted value is oblivious to the server. + /// It can be useful to make server random generation deterministic. + /// + /// ```rust + /// use tfhe::prelude::FheDecrypt; + /// use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheInt8, Seed}; + /// + /// let config = ConfigBuilder::default().build(); + /// let (client_key, server_key) = generate_keys(config); + /// + /// set_server_key(server_key); + /// + /// let random_bits_count = 3; + /// + /// let ct_res = FheInt8::generate_oblivious_pseudo_random_bounded(Seed(0), random_bits_count); + /// + /// let dec_result: i16 = ct_res.decrypt(&client_key); + /// assert!(dec_result >= 0); + /// assert!(dec_result < 1 << random_bits_count); + /// ``` + pub fn generate_oblivious_pseudo_random_bounded(seed: Seed, random_bits_count: u64) -> Self { + global_state::with_internal_keys(|key| match key { + InternalServerKey::Cpu(key) => { + let ct = key + .pbs_key() + .par_generate_oblivious_pseudo_random_signed_integer_bounded( + seed, + random_bits_count, + Id::num_blocks(key.message_modulus()) as u64, + ); + + Self::new(ct, key.tag.clone()) + } + #[cfg(feature = "gpu")] + InternalServerKey::Cuda(_) => { + todo!("Cuda devices do not yet support oblivious pseudo random generation") + } + }) + } } diff --git a/tfhe/src/high_level_api/mod.rs b/tfhe/src/high_level_api/mod.rs index 3b61ba1fb2..c4178d51a2 100644 --- a/tfhe/src/high_level_api/mod.rs +++ b/tfhe/src/high_level_api/mod.rs @@ -24,7 +24,6 @@ macro_rules! expand_pub_use_fhe_type( ); pub use crate::core_crypto::commons::math::random::Seed; -pub use crate::integer::oprf::SignedRandomizationSpec; pub use crate::integer::server_key::MatchValues; pub use config::{Config, ConfigBuilder}; pub use global_state::{set_server_key, unset_server_key, with_server_key_as_context}; diff --git a/tfhe/src/integer/oprf.rs b/tfhe/src/integer/oprf.rs index a60f34a278..addf7b707e 100644 --- a/tfhe/src/integer/oprf.rs +++ b/tfhe/src/integer/oprf.rs @@ -7,9 +7,79 @@ pub use concrete_csprng::seeders::{Seed, Seeder}; impl ServerKey { /// Generates an encrypted `num_block` blocks unsigned integer - /// taken uniformly in `[0, 2^random_bits_count[` using the given seed - /// The encryted value is oblivious to the server - /// It can be useful to make server random generation deterministic + /// taken uniformly in its full range using the given seed. + /// The encryted value is oblivious to the server. + /// It can be useful to make server random generation deterministic. + /// + /// ```rust + /// use tfhe::integer::gen_keys_radix; + /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS; + /// use tfhe::Seed; + /// + /// let size = 4; + /// + /// // Generate the client key and the server key: + /// let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS, size); + /// + /// let ct_res = sks.par_generate_oblivious_pseudo_random_unsigned_integer(Seed(0), size as u64); + /// + /// // Decrypt: + /// let dec_result: u64 = cks.decrypt(&ct_res); + /// + /// assert!(dec_result < 1 << (2 * size)); + /// ``` + pub fn par_generate_oblivious_pseudo_random_unsigned_integer( + &self, + seed: Seed, + num_blocks: u64, + ) -> RadixCiphertext { + assert!(self.message_modulus().0.is_power_of_two()); + let range_log_size = self.message_modulus().0.ilog2() as u64 * num_blocks; + + let random_bits_count = range_log_size; + + assert!(self.message_modulus().0.is_power_of_two()); + let message_bits_count = self.message_modulus().0.ilog2() as u64; + + let mut deterministic_seeder = DeterministicSeeder::::new(seed); + + let seeds: Vec = (0..num_blocks) + .map(|_| deterministic_seeder.seed()) + .collect(); + + let blocks = seeds + .into_par_iter() + .enumerate() + .map(|(i, seed)| { + let i = i as u64; + + if i * message_bits_count < random_bits_count { + // if we generate 5 bits of noise in n blocks of 2 bits, the third (i=2) block + // must have only one bit of random + if random_bits_count < (i + 1) * message_bits_count { + let top_message_bits_count = random_bits_count - i * message_bits_count; + + assert!(top_message_bits_count <= message_bits_count); + + self.key + .generate_oblivious_pseudo_random(seed, top_message_bits_count) + } else { + self.key + .generate_oblivious_pseudo_random(seed, message_bits_count) + } + } else { + self.key.create_trivial(0) + } + }) + .collect::>(); + + RadixCiphertext::from(blocks) + } + + /// Generates an encrypted `num_block` blocks unsigned integer + /// taken uniformly in `[0, 2^random_bits_count[` using the given seed. + /// The encryted value is oblivious to the server. + /// It can be useful to make server random generation deterministic. /// /// ```rust /// use tfhe::integer::gen_keys_radix; @@ -23,7 +93,7 @@ impl ServerKey { /// /// let random_bits_count = 3; /// - /// let ct_res = sks.par_generate_oblivious_pseudo_random_unsigned_integer( + /// let ct_res = sks.par_generate_oblivious_pseudo_random_unsigned_integer_bounded( /// Seed(0), /// random_bits_count, /// size as u64, @@ -33,7 +103,7 @@ impl ServerKey { /// let dec_result: u64 = cks.decrypt(&ct_res); /// assert!(dec_result < (1 << random_bits_count)); /// ``` - pub fn par_generate_oblivious_pseudo_random_unsigned_integer( + pub fn par_generate_oblivious_pseudo_random_unsigned_integer_bounded( &self, seed: Seed, random_bits_count: u64, @@ -86,24 +156,14 @@ impl ServerKey { } } -// Describes in which range a random signed integer should be generated -#[derive(Copy, Clone)] -pub enum SignedRandomizationSpec { - // taken uniformly in `[0, 2^random_bits_count[` - Unsigned { random_bits_count: u64 }, - // taken uniformly in the full range [-2^(p-1), 2^(p-1)[ - FullSigned, -} - impl ServerKey { /// Generates an encrypted `num_block` blocks signed integer - /// using the given seed following the randomizer spec - /// The encryted value is oblivious to the server - /// It can be useful to make server random generation deterministic + /// taken uniformly in its full range using the given seed. + /// The encryted value is oblivious to the server. + /// It can be useful to make server random generation deterministic. /// /// ```rust /// use tfhe::integer::gen_keys_radix; - /// use tfhe::integer::oprf::SignedRandomizationSpec; /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS; /// use tfhe::Seed; /// @@ -112,11 +172,7 @@ impl ServerKey { /// // Generate the client key and the server key: /// let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS, size); /// - /// let ct_res = sks.par_generate_oblivious_pseudo_random_signed_integer( - /// Seed(0), - /// SignedRandomizationSpec::FullSigned, - /// size as u64, - /// ); + /// let ct_res = sks.par_generate_oblivious_pseudo_random_signed_integer(Seed(0), size as u64); /// /// // Decrypt: /// let dec_result: i64 = cks.decrypt_signed(&ct_res); @@ -126,14 +182,67 @@ impl ServerKey { pub fn par_generate_oblivious_pseudo_random_signed_integer( &self, seed: Seed, - randomizer: SignedRandomizationSpec, num_blocks: u64, ) -> SignedRadixCiphertext { - #[allow(clippy::int_plus_one)] - if let SignedRandomizationSpec::Unsigned { random_bits_count } = randomizer { - assert!(self.message_modulus().0.is_power_of_two()); - let range_log_size = self.message_modulus().0.ilog2() as u64 * num_blocks; + assert!(self.message_modulus().0.is_power_of_two()); + let message_bits_count = self.message_modulus().0.ilog2() as u64; + + let mut deterministic_seeder = DeterministicSeeder::::new(seed); + + let seeds: Vec = (0..num_blocks) + .map(|_| deterministic_seeder.seed()) + .collect(); + + let blocks = seeds + .into_par_iter() + .map(|seed| { + self.key + .generate_oblivious_pseudo_random(seed, message_bits_count) + }) + .collect::>(); + SignedRadixCiphertext::from(blocks) + } + + /// Generates an encrypted `num_block` blocks signed integer + /// taken uniformly in `[0, 2^random_bits_count[` using the given seed. + /// The encryted value is oblivious to the server. + /// It can be useful to make server random generation deterministic. + /// + /// ```rust + /// use tfhe::integer::gen_keys_radix; + /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS; + /// use tfhe::Seed; + /// + /// let size = 4; + /// + /// let random_bits_count = 3; + /// + /// // Generate the client key and the server key: + /// let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS, size); + /// + /// let ct_res = sks.par_generate_oblivious_pseudo_random_signed_integer_bounded( + /// Seed(0), + /// random_bits_count, + /// size as u64, + /// ); + /// + /// // Decrypt: + /// let dec_result: i64 = cks.decrypt_signed(&ct_res); + /// assert!(dec_result >= 0); + /// assert!(dec_result < (1 << random_bits_count)); + /// ``` + pub fn par_generate_oblivious_pseudo_random_signed_integer_bounded( + &self, + seed: Seed, + random_bits_count: u64, + num_blocks: u64, + ) -> SignedRadixCiphertext { + assert!(self.message_modulus().0.is_power_of_two()); + let range_log_size = self.message_modulus().0.ilog2() as u64 * num_blocks; + + #[allow(clippy::int_plus_one)] + { assert!( random_bits_count + 1 <= range_log_size, "The range asked for a random value (=[0, 2^{}[) does not fit in the available range [-2^{}, 2^{}[", @@ -156,30 +265,22 @@ impl ServerKey { .map(|(i, seed)| { let i = i as u64; - match randomizer { - SignedRandomizationSpec::Unsigned { random_bits_count } => { - if i * message_bits_count < random_bits_count { - // if we generate 5 bits of noise in n blocks of 2 bits, the third (i=2) - // block must have only one bit of random - if random_bits_count < (i + 1) * message_bits_count { - let top_message_bits_count = - random_bits_count - i * message_bits_count; - - assert!(top_message_bits_count <= message_bits_count); - - self.key - .generate_oblivious_pseudo_random(seed, top_message_bits_count) - } else { - self.key - .generate_oblivious_pseudo_random(seed, message_bits_count) - } - } else { - self.key.create_trivial(0) - } + if i * message_bits_count < random_bits_count { + // if we generate 5 bits of noise in n blocks of 2 bits, the third (i=2) + // block must have only one bit of random + if random_bits_count < (i + 1) * message_bits_count { + let top_message_bits_count = random_bits_count - i * message_bits_count; + + assert!(top_message_bits_count <= message_bits_count); + + self.key + .generate_oblivious_pseudo_random(seed, top_message_bits_count) + } else { + self.key + .generate_oblivious_pseudo_random(seed, message_bits_count) } - SignedRandomizationSpec::FullSigned => self - .key - .generate_oblivious_pseudo_random(seed, message_bits_count), + } else { + self.key.create_trivial(0) } }) .collect::>(); @@ -191,7 +292,6 @@ impl ServerKey { #[cfg(test)] pub(crate) mod test { - use crate::integer::oprf::SignedRandomizationSpec; use crate::shortint::oprf::test::test_uniformity; use concrete_csprng::seeders::Seed; @@ -214,7 +314,7 @@ pub(crate) mod test { }; test_uniformity(1 << random_bits_count, &|seed| { - let img = sk.par_generate_oblivious_pseudo_random_unsigned_integer( + let img = sk.par_generate_oblivious_pseudo_random_unsigned_integer_bounded( Seed(seed as u128), random_bits_count, num_blocks as u64, @@ -223,9 +323,9 @@ pub(crate) mod test { }); test_uniformity(1 << random_bits_count, &|seed| { - let img = sk.par_generate_oblivious_pseudo_random_signed_integer( + let img = sk.par_generate_oblivious_pseudo_random_signed_integer_bounded( Seed(seed as u128), - SignedRandomizationSpec::Unsigned { random_bits_count }, + random_bits_count, num_blocks as u64, ); let result = ck.decrypt_signed::(&img); @@ -238,7 +338,6 @@ pub(crate) mod test { test_uniformity(1 << (2 * num_blocks), &|seed| { let img = sk.par_generate_oblivious_pseudo_random_signed_integer( Seed(seed as u128), - SignedRandomizationSpec::FullSigned, num_blocks as u64, );