mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-09 14:47:56 -05:00
feat(integer): add CompressedSquashedNoiseCiphertextList
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
use crate::integer::ciphertext::{
|
||||
CompressedNoiseSquashingCompressionKey, CompressedSquashedNoiseCiphertextList,
|
||||
NoiseSquashingCompressionKey, NoiseSquashingCompressionPrivateKey,
|
||||
};
|
||||
use crate::integer::compression_keys::{
|
||||
CompressedCompressionKey, CompressedDecompressionKey, CompressionKey, CompressionPrivateKeys,
|
||||
DecompressionKey,
|
||||
@@ -42,3 +46,23 @@ pub enum CompressedDecompressionKeyVersions {
|
||||
pub enum CompressionPrivateKeysVersions {
|
||||
V0(CompressionPrivateKeys),
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum NoiseSquashingCompressionKeyVersions {
|
||||
V0(NoiseSquashingCompressionKey),
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum NoiseSquashingCompressionPrivateKeyVersions {
|
||||
V0(NoiseSquashingCompressionPrivateKey),
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum CompressedNoiseSquashingCompressionKeyVersions {
|
||||
V0(CompressedNoiseSquashingCompressionKey),
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum CompressedSquashedNoiseCiphertextListVersions {
|
||||
V0(CompressedSquashedNoiseCiphertextList),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,409 @@
|
||||
use super::{
|
||||
DataKind, SquashedNoiseBooleanBlock, SquashedNoiseRadixCiphertext,
|
||||
SquashedNoiseSignedRadixCiphertext,
|
||||
};
|
||||
use crate::core_crypto::commons::math::random::{Deserialize, Serialize};
|
||||
use crate::integer::backward_compatibility::list_compression::{
|
||||
CompressedNoiseSquashingCompressionKeyVersions, CompressedSquashedNoiseCiphertextListVersions,
|
||||
NoiseSquashingCompressionPrivateKeyVersions,
|
||||
};
|
||||
use crate::integer::noise_squashing::{NoiseSquashingPrivateKey, NoiseSquashingPrivateKeyView};
|
||||
use crate::named::Named;
|
||||
use crate::shortint::ciphertext::{
|
||||
CompressedSquashedNoiseCiphertextList as ShortintCompressedSquashedNoiseCiphertextList,
|
||||
SquashedNoiseCiphertext,
|
||||
};
|
||||
use crate::shortint::list_compression::{
|
||||
CompressedNoiseSquashingCompressionKey as ShortintCompressedNoiseSquashingCompressionKey,
|
||||
NoiseSquashingCompressionKey as ShortintNoiseSquashingCompressionKey,
|
||||
NoiseSquashingCompressionPrivateKey as ShortintNoiseSquashingCompressionPrivateKey,
|
||||
};
|
||||
use crate::shortint::parameters::NoiseSquashingCompressionParameters;
|
||||
use crate::Versionize;
|
||||
|
||||
use crate::integer::backward_compatibility::list_compression::NoiseSquashingCompressionKeyVersions;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Versionize)]
|
||||
#[versionize(NoiseSquashingCompressionPrivateKeyVersions)]
|
||||
pub struct NoiseSquashingCompressionPrivateKey {
|
||||
pub(crate) key: ShortintNoiseSquashingCompressionPrivateKey,
|
||||
}
|
||||
|
||||
impl Named for NoiseSquashingCompressionPrivateKey {
|
||||
const NAME: &'static str = "integer::NoiseSquashingCompressionPrivateKey";
|
||||
}
|
||||
|
||||
impl NoiseSquashingCompressionPrivateKey {
|
||||
pub fn new(params: NoiseSquashingCompressionParameters) -> Self {
|
||||
let key = ShortintNoiseSquashingCompressionPrivateKey::new(params);
|
||||
|
||||
Self { key }
|
||||
}
|
||||
|
||||
pub fn private_key_view(&self) -> NoiseSquashingPrivateKeyView {
|
||||
NoiseSquashingPrivateKeyView {
|
||||
key: (&self.key).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Versionize)]
|
||||
#[versionize(CompressedNoiseSquashingCompressionKeyVersions)]
|
||||
pub struct CompressedNoiseSquashingCompressionKey {
|
||||
pub(crate) key: ShortintCompressedNoiseSquashingCompressionKey,
|
||||
}
|
||||
|
||||
impl CompressedNoiseSquashingCompressionKey {
|
||||
pub fn decompress(&self) -> NoiseSquashingCompressionKey {
|
||||
let key = self.key.decompress();
|
||||
NoiseSquashingCompressionKey { key }
|
||||
}
|
||||
}
|
||||
|
||||
impl Named for CompressedNoiseSquashingCompressionKey {
|
||||
const NAME: &'static str = "integer::CompressedNoiseSquashingCompressionKey";
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Versionize)]
|
||||
#[versionize(NoiseSquashingCompressionKeyVersions)]
|
||||
pub struct NoiseSquashingCompressionKey {
|
||||
pub(crate) key: ShortintNoiseSquashingCompressionKey,
|
||||
}
|
||||
|
||||
impl Named for NoiseSquashingCompressionKey {
|
||||
const NAME: &'static str = "integer::NoiseSquashingCompressionKey";
|
||||
}
|
||||
|
||||
impl NoiseSquashingPrivateKey {
|
||||
pub fn new_noise_squashing_compression_key(
|
||||
&self,
|
||||
private_compression_key: &NoiseSquashingCompressionPrivateKey,
|
||||
) -> NoiseSquashingCompressionKey {
|
||||
let key = self
|
||||
.key
|
||||
.new_noise_squashing_compression_key(&private_compression_key.key);
|
||||
|
||||
NoiseSquashingCompressionKey { key }
|
||||
}
|
||||
|
||||
pub fn new_compressed_noise_squashing_compression_key(
|
||||
&self,
|
||||
private_compression_key: &NoiseSquashingCompressionPrivateKey,
|
||||
) -> CompressedNoiseSquashingCompressionKey {
|
||||
let key = self
|
||||
.key
|
||||
.new_compressed_noise_squashing_compression_key(&private_compression_key.key);
|
||||
|
||||
CompressedNoiseSquashingCompressionKey { key }
|
||||
}
|
||||
}
|
||||
|
||||
/// List that stores compressed noise squashed ciphertext
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Versionize)]
|
||||
#[versionize(CompressedSquashedNoiseCiphertextListVersions)]
|
||||
pub struct CompressedSquashedNoiseCiphertextList {
|
||||
list: ShortintCompressedSquashedNoiseCiphertextList,
|
||||
info: Vec<DataKind>,
|
||||
}
|
||||
|
||||
impl Named for CompressedSquashedNoiseCiphertextList {
|
||||
const NAME: &'static str = "integer::CompressedSquashedNoiseCiphertextList";
|
||||
}
|
||||
|
||||
impl CompressedSquashedNoiseCiphertextList {
|
||||
/// Returns a builder to create a list
|
||||
pub fn builder() -> CompressedSquashedNoiseCiphertextListBuilder {
|
||||
CompressedSquashedNoiseCiphertextListBuilder::new()
|
||||
}
|
||||
|
||||
/// Returns the number of squashed noise ciphertext that are stored
|
||||
pub fn len(&self) -> usize {
|
||||
self.info.len()
|
||||
}
|
||||
|
||||
// Returns whether the list is empty
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
fn blocks_of(&self, index: usize) -> Option<(Vec<SquashedNoiseCiphertext>, DataKind)> {
|
||||
let preceding_infos = self.info.get(..index)?;
|
||||
let current_info = self.info.get(index).copied()?;
|
||||
let message_modulus = self.list.message_modulus().unwrap();
|
||||
|
||||
let start_block_index: usize = preceding_infos
|
||||
.iter()
|
||||
.copied()
|
||||
.map(|kind| kind.num_blocks(message_modulus).div_ceil(2))
|
||||
.sum();
|
||||
|
||||
let end_block_index =
|
||||
start_block_index + current_info.num_blocks(message_modulus).div_ceil(2);
|
||||
|
||||
Some((
|
||||
(start_block_index..end_block_index)
|
||||
.map(|i| self.list.unpack(i).unwrap())
|
||||
.collect(),
|
||||
current_info,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn get_kind_of(&self, index: usize) -> Option<DataKind> {
|
||||
self.info.get(index).copied()
|
||||
}
|
||||
|
||||
/// Decompress the squashed noise ciphertext at the given index slot
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// After decompression, the resulting ciphertext is under the parameters
|
||||
/// of the [NoiseSquashingCompressionKey].
|
||||
pub fn get<T>(&self, index: usize) -> crate::Result<Option<T>>
|
||||
where
|
||||
T: SquashedNoiseExpandable,
|
||||
{
|
||||
self.blocks_of(index)
|
||||
.map(|(ns_blocks, data_kind)| T::from_expanded_blocks(ns_blocks, data_kind))
|
||||
.transpose()
|
||||
}
|
||||
}
|
||||
|
||||
mod sealed {
|
||||
use super::*;
|
||||
pub trait Sealed {}
|
||||
|
||||
impl Sealed for SquashedNoiseRadixCiphertext {}
|
||||
impl Sealed for SquashedNoiseSignedRadixCiphertext {}
|
||||
impl Sealed for SquashedNoiseBooleanBlock {}
|
||||
}
|
||||
|
||||
pub trait SquashedNoiseCompressible: sealed::Sealed {
|
||||
fn compress_into(self, messages: &mut Vec<SquashedNoiseCiphertext>) -> DataKind;
|
||||
}
|
||||
|
||||
impl SquashedNoiseCompressible for SquashedNoiseRadixCiphertext {
|
||||
fn compress_into(mut self, messages: &mut Vec<SquashedNoiseCiphertext>) -> DataKind {
|
||||
messages.append(&mut self.packed_blocks);
|
||||
DataKind::Unsigned(self.original_block_count)
|
||||
}
|
||||
}
|
||||
|
||||
impl SquashedNoiseCompressible for SquashedNoiseSignedRadixCiphertext {
|
||||
fn compress_into(mut self, messages: &mut Vec<SquashedNoiseCiphertext>) -> DataKind {
|
||||
messages.append(&mut self.packed_blocks);
|
||||
DataKind::Signed(self.original_block_count)
|
||||
}
|
||||
}
|
||||
|
||||
impl SquashedNoiseCompressible for SquashedNoiseBooleanBlock {
|
||||
fn compress_into(self, messages: &mut Vec<SquashedNoiseCiphertext>) -> DataKind {
|
||||
messages.push(self.ciphertext);
|
||||
DataKind::Boolean
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SquashedNoiseExpandable: Sized + sealed::Sealed {
|
||||
fn from_expanded_blocks(
|
||||
blocks: Vec<SquashedNoiseCiphertext>,
|
||||
kind: DataKind,
|
||||
) -> crate::Result<Self>;
|
||||
}
|
||||
|
||||
fn create_error_message(tried: DataKind, actual: DataKind) -> crate::Error {
|
||||
fn name(kind: DataKind) -> &'static str {
|
||||
match kind {
|
||||
DataKind::Unsigned(_) => "SquashedNoiseRadixCiphertext",
|
||||
DataKind::Signed(_) => "SquashedNoiseSignedRadixCiphertext",
|
||||
DataKind::Boolean => "SquashedNoiseBooleanBlock",
|
||||
DataKind::String { .. } => "SquashedNoiseFheString",
|
||||
}
|
||||
}
|
||||
crate::error!(
|
||||
"Tried to expand a {}, but a {} is stored in this slot",
|
||||
name(tried),
|
||||
name(actual)
|
||||
)
|
||||
}
|
||||
|
||||
impl SquashedNoiseExpandable for SquashedNoiseRadixCiphertext {
|
||||
fn from_expanded_blocks(
|
||||
blocks: Vec<SquashedNoiseCiphertext>,
|
||||
kind: DataKind,
|
||||
) -> crate::Result<Self> {
|
||||
if let DataKind::Unsigned(block_count) = kind {
|
||||
Ok(Self {
|
||||
packed_blocks: blocks,
|
||||
original_block_count: block_count,
|
||||
})
|
||||
} else {
|
||||
Err(create_error_message(DataKind::Unsigned(0), kind))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SquashedNoiseExpandable for SquashedNoiseSignedRadixCiphertext {
|
||||
fn from_expanded_blocks(
|
||||
blocks: Vec<SquashedNoiseCiphertext>,
|
||||
kind: DataKind,
|
||||
) -> crate::Result<Self> {
|
||||
if let DataKind::Signed(block_count) = kind {
|
||||
Ok(Self {
|
||||
packed_blocks: blocks,
|
||||
original_block_count: block_count,
|
||||
})
|
||||
} else {
|
||||
Err(create_error_message(DataKind::Signed(0), kind))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SquashedNoiseExpandable for SquashedNoiseBooleanBlock {
|
||||
fn from_expanded_blocks(
|
||||
mut blocks: Vec<SquashedNoiseCiphertext>,
|
||||
kind: DataKind,
|
||||
) -> crate::Result<Self> {
|
||||
if DataKind::Boolean == kind {
|
||||
assert_eq!(blocks.len(), 1);
|
||||
Ok(Self {
|
||||
ciphertext: blocks.pop().unwrap(),
|
||||
})
|
||||
} else {
|
||||
Err(create_error_message(DataKind::Boolean, kind))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CompressedSquashedNoiseCiphertextListBuilder {
|
||||
list: Vec<SquashedNoiseCiphertext>,
|
||||
info: Vec<DataKind>,
|
||||
}
|
||||
|
||||
impl Default for CompressedSquashedNoiseCiphertextListBuilder {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl CompressedSquashedNoiseCiphertextListBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
list: vec![],
|
||||
info: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, value: impl SquashedNoiseCompressible) -> &mut Self {
|
||||
let n = self.list.len();
|
||||
let kind = value.compress_into(&mut self.list);
|
||||
|
||||
// Check that the number of blocks that were added matches the
|
||||
// number of blocks advertised by the DataKind
|
||||
let num_blocks = self
|
||||
.list
|
||||
.last()
|
||||
.map_or(0, |ct| kind.num_blocks(ct.message_modulus()))
|
||||
.div_ceil(2); // Because blocks are packed when noise squashed
|
||||
assert_eq!(n + num_blocks, self.list.len());
|
||||
|
||||
self.info.push(kind);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(
|
||||
&self,
|
||||
comp_key: &NoiseSquashingCompressionKey,
|
||||
) -> CompressedSquashedNoiseCiphertextList {
|
||||
let list = comp_key
|
||||
.key
|
||||
.compress_noise_squashed_ciphertexts_into_list(&self.list);
|
||||
|
||||
CompressedSquashedNoiseCiphertextList {
|
||||
list,
|
||||
info: self.info.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::integer::noise_squashing::NoiseSquashingKey;
|
||||
use crate::shortint::parameters::test_params::{
|
||||
TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
TEST_PARAM_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
};
|
||||
use rand::Rng;
|
||||
|
||||
#[test]
|
||||
fn test_compressed_noise_squashed_ciphertext_list() {
|
||||
let param = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let noise_squashing_parameters =
|
||||
TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
// The goal is to test that encrypting a value stored in a type
|
||||
// for which the bit count does not match the target block count of the encrypted
|
||||
// radix properly applies upcasting/downcasting
|
||||
let (cks, sks) = crate::integer::keycache::KEY_CACHE
|
||||
.get_from_params(param, crate::integer::IntegerKeyKind::Radix);
|
||||
let noise_squashing_private_key = NoiseSquashingPrivateKey::new(noise_squashing_parameters);
|
||||
let noise_squashing_key = NoiseSquashingKey::new(&cks, &noise_squashing_private_key);
|
||||
|
||||
let noise_squashing_compression_private_key = NoiseSquashingCompressionPrivateKey::new(
|
||||
TEST_PARAM_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
);
|
||||
let compression_key = noise_squashing_private_key
|
||||
.new_noise_squashing_compression_key(&noise_squashing_compression_private_key);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
const NUM_BLOCKS: usize = 16;
|
||||
|
||||
let clear_a = rng.gen_range(0..=i32::MAX);
|
||||
let clear_b = rng.gen_range(i32::MIN..=-1);
|
||||
let clear_c = rng.gen::<u32>();
|
||||
let clear_d = rng.gen::<bool>();
|
||||
|
||||
let ct_a = cks.encrypt_signed_radix(clear_a, NUM_BLOCKS);
|
||||
let ct_b = cks.encrypt_signed_radix(clear_b, NUM_BLOCKS);
|
||||
let ct_c = cks.encrypt_radix(clear_c, NUM_BLOCKS);
|
||||
let ct_d = cks.encrypt_bool(clear_d);
|
||||
|
||||
let ns_ct_a = noise_squashing_key
|
||||
.squash_signed_radix_ciphertext_noise(&sks, &ct_a)
|
||||
.unwrap();
|
||||
let ns_ct_b = noise_squashing_key
|
||||
.squash_signed_radix_ciphertext_noise(&sks, &ct_b)
|
||||
.unwrap();
|
||||
let ns_ct_c = noise_squashing_key
|
||||
.squash_radix_ciphertext_noise(&sks, &ct_c)
|
||||
.unwrap();
|
||||
let ns_ct_d = noise_squashing_key
|
||||
.squash_boolean_block_noise(&sks, &ct_d)
|
||||
.unwrap();
|
||||
|
||||
let list = CompressedSquashedNoiseCiphertextList::builder()
|
||||
.push(ns_ct_a)
|
||||
.push(ns_ct_b)
|
||||
.push(ns_ct_c)
|
||||
.push(ns_ct_d)
|
||||
.build(&compression_key);
|
||||
|
||||
let ns_ct_a: SquashedNoiseSignedRadixCiphertext = list.get(0).unwrap().unwrap();
|
||||
let ns_ct_b: SquashedNoiseSignedRadixCiphertext = list.get(1).unwrap().unwrap();
|
||||
let ns_ct_c: SquashedNoiseRadixCiphertext = list.get(2).unwrap().unwrap();
|
||||
let ns_ct_d: SquashedNoiseBooleanBlock = list.get(3).unwrap().unwrap();
|
||||
|
||||
let decryption_key = noise_squashing_compression_private_key.private_key_view();
|
||||
|
||||
let d_clear_a: i32 = decryption_key.decrypt_signed_radix(&ns_ct_a).unwrap();
|
||||
let d_clear_b: i32 = decryption_key.decrypt_signed_radix(&ns_ct_b).unwrap();
|
||||
let d_clear_c: u32 = decryption_key.decrypt_radix(&ns_ct_c).unwrap();
|
||||
let d_clear_d = decryption_key.decrypt_bool(&ns_ct_d).unwrap();
|
||||
|
||||
assert_eq!(clear_a, d_clear_a);
|
||||
assert_eq!(clear_b, d_clear_b);
|
||||
assert_eq!(clear_c, d_clear_c);
|
||||
assert_eq!(clear_d, d_clear_d);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ mod compact_list;
|
||||
mod compressed;
|
||||
mod compressed_ciphertext_list;
|
||||
mod compressed_modulus_switched_ciphertext;
|
||||
mod compressed_noise_squashed_ciphertext_list;
|
||||
mod integer_ciphertext;
|
||||
mod squashed_noise;
|
||||
mod utils;
|
||||
@@ -14,6 +15,7 @@ pub use compact_list::*;
|
||||
pub use compressed::*;
|
||||
pub use compressed_ciphertext_list::*;
|
||||
pub use compressed_modulus_switched_ciphertext::*;
|
||||
pub use compressed_noise_squashed_ciphertext_list::*;
|
||||
pub use integer_ciphertext::*;
|
||||
pub use squashed_noise::*;
|
||||
pub use utils::*;
|
||||
|
||||
@@ -21,6 +21,10 @@ pub struct NoiseSquashingPrivateKey {
|
||||
pub(crate) key: crate::shortint::noise_squashing::NoiseSquashingPrivateKey,
|
||||
}
|
||||
|
||||
pub struct NoiseSquashingPrivateKeyView<'a> {
|
||||
pub(crate) key: crate::shortint::noise_squashing::NoiseSquashingPrivateKeyView<'a>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Versionize)]
|
||||
#[versionize(NoiseSquashingKeyVersions)]
|
||||
pub struct NoiseSquashingKey {
|
||||
@@ -33,10 +37,6 @@ pub struct CompressedNoiseSquashingKey {
|
||||
pub(crate) key: crate::shortint::noise_squashing::CompressedNoiseSquashingKey,
|
||||
}
|
||||
|
||||
impl Named for NoiseSquashingPrivateKey {
|
||||
const NAME: &'static str = "integer::NoiseSquashingPrivateKey";
|
||||
}
|
||||
|
||||
impl Named for NoiseSquashingKey {
|
||||
const NAME: &'static str = "integer::NoiseSquashingKey";
|
||||
}
|
||||
@@ -45,6 +45,10 @@ impl Named for CompressedNoiseSquashingKey {
|
||||
const NAME: &'static str = "integer::CompressedNoiseSquashingKey";
|
||||
}
|
||||
|
||||
impl Named for NoiseSquashingPrivateKey {
|
||||
const NAME: &'static str = "integer::NoiseSquashingPrivateKey";
|
||||
}
|
||||
|
||||
impl CompressedNoiseSquashingKey {
|
||||
pub fn decompress(&self) -> NoiseSquashingKey {
|
||||
NoiseSquashingKey {
|
||||
@@ -64,28 +68,7 @@ impl CompressedNoiseSquashingKey {
|
||||
}
|
||||
}
|
||||
|
||||
impl NoiseSquashingPrivateKey {
|
||||
pub fn new_compressed_noise_squashing_key(
|
||||
&self,
|
||||
client_key: &ClientKey,
|
||||
) -> CompressedNoiseSquashingKey {
|
||||
client_key.new_compressed_noise_squashing_key(self)
|
||||
}
|
||||
|
||||
pub fn new(params: NoiseSquashingParameters) -> Self {
|
||||
assert!(
|
||||
params.carry_modulus.0 >= params.message_modulus.0,
|
||||
"NoiseSquashingPrivateKey requires its CarryModulus {:?} to be greater \
|
||||
or equal to its MessageModulus {:?}",
|
||||
params.carry_modulus.0,
|
||||
params.message_modulus.0,
|
||||
);
|
||||
|
||||
Self {
|
||||
key: crate::shortint::noise_squashing::NoiseSquashingPrivateKey::new(params),
|
||||
}
|
||||
}
|
||||
|
||||
impl NoiseSquashingPrivateKeyView<'_> {
|
||||
pub fn decrypt_radix<T>(&self, ct: &SquashedNoiseRadixCiphertext) -> crate::Result<T>
|
||||
where
|
||||
T: RecomposableFrom<u128> + UnsignedNumeric,
|
||||
@@ -241,6 +224,56 @@ impl NoiseSquashingPrivateKey {
|
||||
|
||||
Ok(decrypted != 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl NoiseSquashingPrivateKey {
|
||||
pub fn new_compressed_noise_squashing_key(
|
||||
&self,
|
||||
client_key: &ClientKey,
|
||||
) -> CompressedNoiseSquashingKey {
|
||||
client_key.new_compressed_noise_squashing_key(self)
|
||||
}
|
||||
|
||||
pub fn new(params: NoiseSquashingParameters) -> Self {
|
||||
assert!(
|
||||
params.carry_modulus.0 >= params.message_modulus.0,
|
||||
"NoiseSquashingPrivateKey requires its CarryModulus {:?} to be greater \
|
||||
or equal to its MessageModulus {:?}",
|
||||
params.carry_modulus.0,
|
||||
params.message_modulus.0,
|
||||
);
|
||||
|
||||
Self {
|
||||
key: crate::shortint::noise_squashing::NoiseSquashingPrivateKey::new(params),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn as_view(&self) -> NoiseSquashingPrivateKeyView {
|
||||
NoiseSquashingPrivateKeyView {
|
||||
key: self.key.as_view(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrypt_radix<T>(&self, ct: &SquashedNoiseRadixCiphertext) -> crate::Result<T>
|
||||
where
|
||||
T: RecomposableFrom<u128> + UnsignedNumeric,
|
||||
{
|
||||
self.as_view().decrypt_radix(ct)
|
||||
}
|
||||
|
||||
pub fn decrypt_signed_radix<T>(
|
||||
&self,
|
||||
ct: &SquashedNoiseSignedRadixCiphertext,
|
||||
) -> crate::Result<T>
|
||||
where
|
||||
T: RecomposableFrom<u128> + SignExtendable,
|
||||
{
|
||||
self.as_view().decrypt_signed_radix(ct)
|
||||
}
|
||||
|
||||
pub fn decrypt_bool(&self, ct: &SquashedNoiseBooleanBlock) -> crate::Result<bool> {
|
||||
self.as_view().decrypt_bool(ct)
|
||||
}
|
||||
|
||||
pub fn into_raw_parts(self) -> crate::shortint::noise_squashing::NoiseSquashingPrivateKey {
|
||||
let Self { key } = self;
|
||||
|
||||
@@ -232,4 +232,8 @@ impl CompressedSquashedNoiseCiphertextList {
|
||||
|
||||
Ok(extracted_lwe)
|
||||
}
|
||||
|
||||
pub fn message_modulus(&self) -> Option<MessageModulus> {
|
||||
self.meta.as_ref().map(|meta| meta.message_modulus)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::shortint::backward_compatibility::list_compression::{
|
||||
use crate::shortint::client_key::atomic_pattern::AtomicPatternClientKey;
|
||||
use crate::shortint::client_key::ClientKey;
|
||||
use crate::shortint::engine::ShortintEngine;
|
||||
use crate::shortint::list_compression::CompressedNoiseSquashingCompressionKey;
|
||||
use crate::shortint::noise_squashing::NoiseSquashingPrivateKey;
|
||||
use crate::shortint::parameters::{
|
||||
CompressionParameters, ModulusSwitchType, NoiseSquashingCompressionParameters,
|
||||
@@ -269,6 +270,31 @@ impl NoiseSquashingPrivateKey {
|
||||
lwe_per_glwe: params.lwe_per_glwe,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_compressed_noise_squashing_compression_key(
|
||||
&self,
|
||||
private_compression_key: &NoiseSquashingCompressionPrivateKey,
|
||||
) -> CompressedNoiseSquashingCompressionKey {
|
||||
let params = &private_compression_key.params;
|
||||
|
||||
let packing_key_switching_key =
|
||||
crate::shortint::engine::ShortintEngine::with_thread_local_mut(|engine| {
|
||||
allocate_and_generate_new_seeded_lwe_packing_keyswitch_key(
|
||||
&self.post_noise_squashing_secret_key().as_lwe_secret_key(),
|
||||
&private_compression_key.post_packing_ks_key,
|
||||
params.packing_ks_base_log,
|
||||
params.packing_ks_level,
|
||||
params.packing_ks_key_noise_distribution,
|
||||
params.ciphertext_modulus,
|
||||
&mut engine.seeder,
|
||||
)
|
||||
});
|
||||
|
||||
CompressedNoiseSquashingCompressionKey {
|
||||
packing_key_switching_key,
|
||||
lwe_per_glwe: params.lwe_per_glwe,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NoiseSquashingCompressionKeyConformanceParams {
|
||||
|
||||
@@ -78,6 +78,13 @@ pub(crate) struct NoiseSquashingPrivateKeyView<'a> {
|
||||
params: NoiseSquashingParameters,
|
||||
}
|
||||
|
||||
impl NoiseSquashingPrivateKeyView<'_> {
|
||||
#[allow(unused, reason = "It's only used in integer module")]
|
||||
pub fn noise_squashing_parameters(&self) -> NoiseSquashingParameters {
|
||||
self.params
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a NoiseSquashingPrivateKey> for NoiseSquashingPrivateKeyView<'a> {
|
||||
fn from(value: &'a NoiseSquashingPrivateKey) -> Self {
|
||||
Self {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use super::current_params::*;
|
||||
use super::{AtomicPatternParameters, KeySwitch32PBSParameters};
|
||||
use super::{
|
||||
AtomicPatternParameters, KeySwitch32PBSParameters, NoiseSquashingCompressionParameters,
|
||||
NoiseSquashingParameters,
|
||||
};
|
||||
|
||||
use super::{
|
||||
ClassicPBSParameters, CompactPublicKeyEncryptionParameters, CompressionParameters,
|
||||
@@ -221,3 +224,10 @@ pub const TEST_COMP_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFOR
|
||||
// KS32 PBS AP
|
||||
pub const TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128: KeySwitch32PBSParameters =
|
||||
V1_3_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
|
||||
|
||||
pub const TEST_PARAM_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
|
||||
NoiseSquashingCompressionParameters =
|
||||
V1_3_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
pub const TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
|
||||
NoiseSquashingParameters = V1_3_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
Reference in New Issue
Block a user