mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-09 14:47:56 -05:00
refactor(shortint): change the LweCiphertext type
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
use crate::core_crypto::algorithms::*;
|
||||
//! Module containing functions related to LWE ciphertext encryption and decryption
|
||||
|
||||
use crate::core_crypto::algorithms::slice_algorithms::*;
|
||||
use crate::core_crypto::commons::crypto::secret::generators::EncryptionRandomGenerator;
|
||||
use crate::core_crypto::commons::math::random::ByteRandomGenerator;
|
||||
use crate::core_crypto::commons::math::torus::UnsignedTorus;
|
||||
@@ -8,11 +10,12 @@ use crate::core_crypto::entities::encoded::Encoded;
|
||||
use crate::core_crypto::entities::lwe_ciphertext::{LweCiphertext, LweCiphertextBase};
|
||||
use crate::core_crypto::entities::lwe_secret_key::LweSecretKeyBase;
|
||||
use crate::core_crypto::specification::dispersion::DispersionParameter;
|
||||
use crate::core_crypto::specification::parameters::LweSize;
|
||||
|
||||
pub fn encrypt_lwe_ciphertext<Scalar, KeyCont, OutputCont, Gen>(
|
||||
lwe_secret_key: &LweSecretKeyBase<KeyCont>,
|
||||
output: &mut LweCiphertextBase<OutputCont>,
|
||||
encoded: &Encoded<Scalar>,
|
||||
encoded: Encoded<Scalar>,
|
||||
noise_parameters: impl DispersionParameter,
|
||||
generator: &mut EncryptionRandomGenerator<Gen>,
|
||||
) where
|
||||
@@ -36,7 +39,7 @@ pub fn encrypt_lwe_ciphertext<Scalar, KeyCont, OutputCont, Gen>(
|
||||
|
||||
pub fn allocate_and_encrypt_new_lwe_ciphertext<Scalar, KeyCont, Gen>(
|
||||
lwe_secret_key: &LweSecretKeyBase<KeyCont>,
|
||||
encoded: &Encoded<Scalar>,
|
||||
encoded: Encoded<Scalar>,
|
||||
noise_parameters: impl DispersionParameter,
|
||||
generator: &mut EncryptionRandomGenerator<Gen>,
|
||||
) -> LweCiphertext<Scalar>
|
||||
@@ -58,6 +61,35 @@ where
|
||||
new_ct
|
||||
}
|
||||
|
||||
pub fn trivially_encrypt_lwe_ciphertext<Scalar, OutputCont>(
|
||||
output: &mut LweCiphertextBase<OutputCont>,
|
||||
encoded: Encoded<Scalar>,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
{
|
||||
output
|
||||
.as_mut()
|
||||
.iter_mut()
|
||||
.for_each(|elt| *elt = Scalar::ZERO);
|
||||
|
||||
*output.get_mut_body().0 = encoded.0
|
||||
}
|
||||
|
||||
pub fn allocate_and_trivially_encrypt_new_lwe_ciphertext<Scalar>(
|
||||
lwe_size: LweSize,
|
||||
encoded: Encoded<Scalar>,
|
||||
) -> LweCiphertext<Scalar>
|
||||
where
|
||||
Scalar: UnsignedTorus,
|
||||
{
|
||||
let mut new_ct = LweCiphertext::from_container(vec![Scalar::ZERO; lwe_size.0]);
|
||||
|
||||
*new_ct.get_mut_body().0 = encoded.0;
|
||||
|
||||
new_ct
|
||||
}
|
||||
|
||||
pub fn decrypt_lwe_ciphertext<Scalar, KeyCont, InputCont>(
|
||||
lwe_secret_key: &LweSecretKeyBase<KeyCont>,
|
||||
lwe_ciphertext: &LweCiphertextBase<InputCont>,
|
||||
|
||||
61
tfhe/src/core_crypto/algorithms/lwe_linear_algebra.rs
Normal file
61
tfhe/src/core_crypto/algorithms/lwe_linear_algebra.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
//! Module containing functions related to LWE ciphertext linear algebra, like addition,
|
||||
//! multiplication, etc.
|
||||
|
||||
use crate::core_crypto::algorithms::slice_algorithms::*;
|
||||
use crate::core_crypto::commons::numeric::UnsignedInteger;
|
||||
use crate::core_crypto::commons::traits::{Container, ContainerMut};
|
||||
use crate::core_crypto::entities::cleartext::Cleartext;
|
||||
use crate::core_crypto::entities::encoded::Encoded;
|
||||
use crate::core_crypto::entities::lwe_ciphertext::LweCiphertextBase;
|
||||
|
||||
pub fn lwe_ciphertext_in_place_addition<Scalar, LhsCont, RhsCont>(
|
||||
lhs: &mut LweCiphertextBase<LhsCont>,
|
||||
rhs: &LweCiphertextBase<RhsCont>,
|
||||
) where
|
||||
Scalar: UnsignedInteger,
|
||||
LhsCont: ContainerMut<Element = Scalar>,
|
||||
RhsCont: Container<Element = Scalar>,
|
||||
{
|
||||
update_with_wrapping_add(lhs.as_mut(), rhs.as_ref());
|
||||
}
|
||||
|
||||
pub fn lwe_ciphertext_in_place_encoded_addition<Scalar, InCont>(
|
||||
lhs: &mut LweCiphertextBase<InCont>,
|
||||
rhs: Encoded<Scalar>,
|
||||
) where
|
||||
Scalar: UnsignedInteger,
|
||||
InCont: ContainerMut<Element = Scalar>,
|
||||
{
|
||||
let body = lhs.get_mut_body();
|
||||
|
||||
*body.0 = (*body.0).wrapping_add(rhs.0);
|
||||
}
|
||||
|
||||
pub fn lwe_ciphertext_in_place_opposite<Scalar, InCont>(ct: &mut LweCiphertextBase<InCont>)
|
||||
where
|
||||
Scalar: UnsignedInteger,
|
||||
InCont: ContainerMut<Element = Scalar>,
|
||||
{
|
||||
update_with_wrapping_opposite(ct.as_mut());
|
||||
}
|
||||
|
||||
pub fn lwe_ciphertext_in_place_cleartext_multiplication<Scalar, InCont>(
|
||||
lhs: &mut LweCiphertextBase<InCont>,
|
||||
rhs: Cleartext<Scalar>,
|
||||
) where
|
||||
Scalar: UnsignedInteger,
|
||||
InCont: ContainerMut<Element = Scalar>,
|
||||
{
|
||||
update_with_scalar_wrapping_mul(lhs.as_mut(), rhs.0);
|
||||
}
|
||||
|
||||
pub fn lwe_ciphertext_in_place_subtraction<Scalar, LhsCont, RhsCont>(
|
||||
lhs: &mut LweCiphertextBase<LhsCont>,
|
||||
rhs: &LweCiphertextBase<RhsCont>,
|
||||
) where
|
||||
Scalar: UnsignedInteger,
|
||||
LhsCont: ContainerMut<Element = Scalar>,
|
||||
RhsCont: Container<Element = Scalar>,
|
||||
{
|
||||
update_with_wrapping_sub(lhs.as_mut(), rhs.as_ref());
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod lwe_encryption;
|
||||
pub mod lwe_linear_algebra;
|
||||
pub mod slice_algorithms;
|
||||
|
||||
pub use slice_algorithms::*;
|
||||
|
||||
@@ -17,3 +17,52 @@ where
|
||||
acc.wrapping_add(left.wrapping_mul(right))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update_with_wrapping_add<Scalar>(lhs: &mut [Scalar], rhs: &[Scalar])
|
||||
where
|
||||
Scalar: UnsignedInteger,
|
||||
{
|
||||
assert!(
|
||||
lhs.len() == rhs.len(),
|
||||
"lhs (len: {}) and rhs (len: {}) must have the same length",
|
||||
lhs.len(),
|
||||
rhs.len()
|
||||
);
|
||||
|
||||
lhs.iter_mut()
|
||||
.zip(rhs.iter())
|
||||
.for_each(|(lhs, &rhs)| *lhs = (*lhs).wrapping_add(rhs));
|
||||
}
|
||||
|
||||
pub fn update_with_wrapping_sub<Scalar>(lhs: &mut [Scalar], rhs: &[Scalar])
|
||||
where
|
||||
Scalar: UnsignedInteger,
|
||||
{
|
||||
assert!(
|
||||
lhs.len() == rhs.len(),
|
||||
"lhs (len: {}) and rhs (len: {}) must have the same length",
|
||||
lhs.len(),
|
||||
rhs.len()
|
||||
);
|
||||
|
||||
lhs.iter_mut()
|
||||
.zip(rhs.iter())
|
||||
.for_each(|(lhs, &rhs)| *lhs = (*lhs).wrapping_sub(rhs));
|
||||
}
|
||||
|
||||
pub fn update_with_wrapping_opposite<Scalar>(slice: &mut [Scalar])
|
||||
where
|
||||
Scalar: UnsignedInteger,
|
||||
{
|
||||
slice
|
||||
.iter_mut()
|
||||
.for_each(|elt| *elt = (*elt).wrapping_neg());
|
||||
}
|
||||
|
||||
pub fn update_with_scalar_wrapping_mul<Scalar>(lhs: &mut [Scalar], rhs: Scalar)
|
||||
where
|
||||
Scalar: UnsignedInteger,
|
||||
{
|
||||
lhs.iter_mut()
|
||||
.for_each(|lhs| *lhs = (*lhs).wrapping_mul(rhs));
|
||||
}
|
||||
|
||||
4
tfhe/src/core_crypto/entities/cleartext.rs
Normal file
4
tfhe/src/core_crypto/entities/cleartext.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
use crate::core_crypto::commons::numeric::Numeric;
|
||||
|
||||
/// A cleartext, not encoded, value
|
||||
pub struct Cleartext<T: Numeric>(pub T);
|
||||
@@ -33,6 +33,18 @@ pub struct LweCiphertextBase<C: Container> {
|
||||
data: C,
|
||||
}
|
||||
|
||||
impl<T, C: Container<Element = T>> AsRef<[T]> for LweCiphertextBase<C> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for LweCiphertextBase<C> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self.data.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar, C: Container<Element = Scalar>> LweCiphertextBase<C> {
|
||||
pub fn from_container(container: C) -> Self {
|
||||
assert!(
|
||||
@@ -51,6 +63,12 @@ impl<Scalar, C: Container<Element = Scalar>> LweCiphertextBase<C> {
|
||||
|
||||
(LweMask::from_container(mask), LweBody(body))
|
||||
}
|
||||
|
||||
pub fn get_body(&self) -> LweBody<&Scalar> {
|
||||
let body = self.data.as_ref().last().unwrap();
|
||||
|
||||
LweBody(body)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar, C: ContainerMut<Element = Scalar>> LweCiphertextBase<C> {
|
||||
@@ -59,6 +77,12 @@ impl<Scalar, C: ContainerMut<Element = Scalar>> LweCiphertextBase<C> {
|
||||
|
||||
(LweMask::from_container(mask), LweBody(body))
|
||||
}
|
||||
|
||||
pub fn get_mut_body(&mut self) -> LweBody<&mut Scalar> {
|
||||
let body = self.data.as_mut().last_mut().unwrap();
|
||||
|
||||
LweBody(body)
|
||||
}
|
||||
}
|
||||
|
||||
pub type LweCiphertext<Scalar> = LweCiphertextBase<Vec<Scalar>>;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod cleartext;
|
||||
pub mod encoded;
|
||||
pub mod lwe_ciphertext;
|
||||
pub mod lwe_secret_key;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//! Module with the definition of a short-integer ciphertext.
|
||||
use crate::core_crypto::entities::lwe_ciphertext::LweCiphertext;
|
||||
use crate::core_crypto::prelude::*;
|
||||
use crate::shortint::parameters::{CarryModulus, MessageModulus};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
@@ -82,7 +83,7 @@ impl Degree {
|
||||
/// Internally, it uses a LWE ciphertext.
|
||||
#[derive(Clone)]
|
||||
pub struct Ciphertext {
|
||||
pub ct: LweCiphertext64,
|
||||
pub ct: LweCiphertext<u64>,
|
||||
pub degree: Degree,
|
||||
pub message_modulus: MessageModulus,
|
||||
pub carry_modulus: CarryModulus,
|
||||
@@ -103,8 +104,10 @@ impl Serialize for Ciphertext {
|
||||
{
|
||||
let mut ser_eng = DefaultSerializationEngine::new(()).map_err(serde::ser::Error::custom)?;
|
||||
|
||||
let old_ct: LweCiphertext64 = self.ct.clone().into();
|
||||
|
||||
let data = ser_eng
|
||||
.serialize(&self.ct)
|
||||
.serialize(&old_ct)
|
||||
.map_err(serde::ser::Error::custom)?;
|
||||
|
||||
SerializableCiphertext {
|
||||
@@ -126,12 +129,12 @@ impl<'de> Deserialize<'de> for Ciphertext {
|
||||
|
||||
let mut de_eng = DefaultSerializationEngine::new(()).map_err(serde::de::Error::custom)?;
|
||||
|
||||
let ct = de_eng
|
||||
let old_ct: LweCiphertext64 = de_eng
|
||||
.deserialize(thing.data.as_slice())
|
||||
.map_err(serde::de::Error::custom)?;
|
||||
|
||||
Ok(Self {
|
||||
ct,
|
||||
ct: old_ct.into(),
|
||||
degree: thing.degree,
|
||||
message_modulus: thing.message_modulus,
|
||||
carry_modulus: thing.carry_modulus,
|
||||
|
||||
@@ -66,15 +66,15 @@ impl ShortintEngine {
|
||||
|
||||
let encoded = Encoded(shifted_message);
|
||||
|
||||
let new_ct = allocate_and_encrypt_new_lwe_ciphertext(
|
||||
let ct = allocate_and_encrypt_new_lwe_ciphertext(
|
||||
&client_key.lwe_secret_key,
|
||||
&encoded,
|
||||
encoded,
|
||||
client_key.parameters.lwe_modular_std_dev,
|
||||
self.engine.get_encryption_generator(),
|
||||
);
|
||||
|
||||
Ok(Ciphertext {
|
||||
ct: new_ct.into(),
|
||||
ct,
|
||||
degree: Degree(message_modulus.0 - 1),
|
||||
message_modulus,
|
||||
carry_modulus: CarryModulus(carry_modulus),
|
||||
@@ -93,15 +93,15 @@ impl ShortintEngine {
|
||||
|
||||
let encoded = Encoded(shifted_message);
|
||||
|
||||
let new_ct = allocate_and_encrypt_new_lwe_ciphertext(
|
||||
let ct = allocate_and_encrypt_new_lwe_ciphertext(
|
||||
&client_key.lwe_secret_key,
|
||||
&encoded,
|
||||
encoded,
|
||||
client_key.parameters.lwe_modular_std_dev,
|
||||
self.engine.get_encryption_generator(),
|
||||
);
|
||||
|
||||
Ok(Ciphertext {
|
||||
ct: new_ct.into(),
|
||||
ct,
|
||||
degree: Degree(
|
||||
client_key.parameters.message_modulus.0 * client_key.parameters.carry_modulus.0 - 1,
|
||||
),
|
||||
@@ -116,8 +116,7 @@ impl ShortintEngine {
|
||||
ct: &Ciphertext,
|
||||
) -> EngineResult<u64> {
|
||||
// decryption
|
||||
let decrypted_encoded =
|
||||
decrypt_lwe_ciphertext(&client_key.lwe_secret_key, &ct.ct.as_refactor_ct_view());
|
||||
let decrypted_encoded = decrypt_lwe_ciphertext(&client_key.lwe_secret_key, &ct.ct);
|
||||
|
||||
let decrypted_u64: u64 = decrypted_encoded.0;
|
||||
|
||||
@@ -154,15 +153,15 @@ impl ShortintEngine {
|
||||
|
||||
let encoded = Encoded(shifted_message);
|
||||
|
||||
let new_ct = allocate_and_encrypt_new_lwe_ciphertext(
|
||||
let ct = allocate_and_encrypt_new_lwe_ciphertext(
|
||||
&client_key.lwe_secret_key,
|
||||
&encoded,
|
||||
encoded,
|
||||
client_key.parameters.lwe_modular_std_dev,
|
||||
self.engine.get_encryption_generator(),
|
||||
);
|
||||
|
||||
Ok(Ciphertext {
|
||||
ct: new_ct.into(),
|
||||
ct,
|
||||
degree: Degree(client_key.parameters.message_modulus.0 - 1),
|
||||
message_modulus: client_key.parameters.message_modulus,
|
||||
carry_modulus: client_key.parameters.carry_modulus,
|
||||
@@ -175,8 +174,7 @@ impl ShortintEngine {
|
||||
ct: &Ciphertext,
|
||||
) -> EngineResult<u64> {
|
||||
// decryption
|
||||
let decrypted_encoded =
|
||||
decrypt_lwe_ciphertext(&client_key.lwe_secret_key, &ct.ct.as_refactor_ct_view());
|
||||
let decrypted_encoded = decrypt_lwe_ciphertext(&client_key.lwe_secret_key, &ct.ct);
|
||||
|
||||
let decrypted_u64: u64 = decrypted_encoded.0;
|
||||
|
||||
@@ -215,15 +213,15 @@ impl ShortintEngine {
|
||||
|
||||
let encoded = Encoded(shifted_message);
|
||||
|
||||
let new_ct = allocate_and_encrypt_new_lwe_ciphertext(
|
||||
let ct = allocate_and_encrypt_new_lwe_ciphertext(
|
||||
&client_key.lwe_secret_key,
|
||||
&encoded,
|
||||
encoded,
|
||||
client_key.parameters.lwe_modular_std_dev,
|
||||
self.engine.get_encryption_generator(),
|
||||
);
|
||||
|
||||
Ok(Ciphertext {
|
||||
ct: new_ct.into(),
|
||||
ct,
|
||||
degree: Degree(message_modulus as usize - 1),
|
||||
message_modulus: MessageModulus(message_modulus as usize),
|
||||
carry_modulus: CarryModulus(carry_modulus),
|
||||
@@ -237,8 +235,7 @@ impl ShortintEngine {
|
||||
basis: u64,
|
||||
) -> EngineResult<u64> {
|
||||
// decryption
|
||||
let decrypted_encoded =
|
||||
decrypt_lwe_ciphertext(&client_key.lwe_secret_key, &ct.ct.as_refactor_ct_view());
|
||||
let decrypted_encoded = decrypt_lwe_ciphertext(&client_key.lwe_secret_key, &ct.ct);
|
||||
|
||||
let decrypted_u64: u64 = decrypted_encoded.0;
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ impl ShortintEngine {
|
||||
)?;
|
||||
|
||||
Ok(Ciphertext {
|
||||
ct: encrypted_ct,
|
||||
ct: encrypted_ct.into(),
|
||||
degree: Degree(message_modulus.0 - 1),
|
||||
message_modulus,
|
||||
carry_modulus: CarryModulus(carry_modulus),
|
||||
@@ -124,7 +124,7 @@ impl ShortintEngine {
|
||||
)?;
|
||||
|
||||
Ok(Ciphertext {
|
||||
ct: encrypted_ct,
|
||||
ct: encrypted_ct.into(),
|
||||
degree: Degree(public_key.parameters.message_modulus.0 - 1),
|
||||
message_modulus: public_key.parameters.message_modulus,
|
||||
carry_modulus: public_key.parameters.carry_modulus,
|
||||
@@ -159,7 +159,7 @@ impl ShortintEngine {
|
||||
)?;
|
||||
|
||||
Ok(Ciphertext {
|
||||
ct: encrypted_ct,
|
||||
ct: encrypted_ct.into(),
|
||||
degree: Degree(message_modulus as usize - 1),
|
||||
message_modulus: MessageModulus(message_modulus as usize),
|
||||
carry_modulus: CarryModulus(carry_modulus),
|
||||
@@ -192,7 +192,7 @@ impl ShortintEngine {
|
||||
)?;
|
||||
|
||||
Ok(Ciphertext {
|
||||
ct: encrypted_ct,
|
||||
ct: encrypted_ct.into(),
|
||||
degree: Degree(
|
||||
public_key.parameters.message_modulus.0 * public_key.parameters.carry_modulus.0 - 1,
|
||||
),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::core_crypto::prelude::*;
|
||||
use crate::core_crypto::algorithms::lwe_linear_algebra::lwe_ciphertext_in_place_addition;
|
||||
use crate::shortint::ciphertext::Degree;
|
||||
use crate::shortint::engine::{EngineResult, ShortintEngine};
|
||||
use crate::shortint::{Ciphertext, ServerKey};
|
||||
@@ -19,8 +19,7 @@ impl ShortintEngine {
|
||||
ct_left: &mut Ciphertext,
|
||||
ct_right: &Ciphertext,
|
||||
) -> EngineResult<()> {
|
||||
self.engine
|
||||
.fuse_add_lwe_ciphertext(&mut ct_left.ct, &ct_right.ct)?;
|
||||
lwe_ciphertext_in_place_addition(&mut ct_left.ct, &ct_right.ct);
|
||||
ct_left.degree = Degree(ct_left.degree.0 + ct_right.degree.0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
use super::ShortintEngine;
|
||||
use crate::core_crypto::algorithms::lwe_encryption::{
|
||||
allocate_and_trivially_encrypt_new_lwe_ciphertext, trivially_encrypt_lwe_ciphertext,
|
||||
};
|
||||
use crate::core_crypto::entities::encoded::Encoded;
|
||||
use crate::core_crypto::prelude::*;
|
||||
use crate::shortint::ciphertext::Degree;
|
||||
use crate::shortint::engine::EngineResult;
|
||||
@@ -106,16 +110,16 @@ impl ShortintEngine {
|
||||
|
||||
// Compute a keyswitch
|
||||
engine.discard_keyswitch_lwe_ciphertext(
|
||||
&mut buffers.buffer_lwe_after_ks,
|
||||
&ct.ct,
|
||||
&mut LweCiphertextMutView64(buffers.buffer_lwe_after_ks.0.as_mut_view()),
|
||||
&ct.ct.as_old_ct_view(),
|
||||
&server_key.key_switching_key,
|
||||
)?;
|
||||
|
||||
// Compute a bootstrap
|
||||
fft_engine.discard_bootstrap_lwe_ciphertext(
|
||||
&mut ct.ct,
|
||||
&buffers.buffer_lwe_after_ks,
|
||||
&buffers.accumulator,
|
||||
&mut ct.ct.as_old_ct_mut_view(),
|
||||
&LweCiphertextView64(buffers.buffer_lwe_after_ks.0.as_view()),
|
||||
&GlweCiphertextView64(buffers.accumulator.0.as_view()),
|
||||
&server_key.bootstrapping_key,
|
||||
)?;
|
||||
Ok(())
|
||||
@@ -143,16 +147,16 @@ impl ShortintEngine {
|
||||
|
||||
// Compute a key switch
|
||||
engine.discard_keyswitch_lwe_ciphertext(
|
||||
&mut buffers.buffer_lwe_after_ks,
|
||||
&ct.ct,
|
||||
&mut LweCiphertextMutView64(buffers.buffer_lwe_after_ks.0.as_mut_view()),
|
||||
&ct.ct.as_old_ct_view(),
|
||||
&server_key.key_switching_key,
|
||||
)?;
|
||||
|
||||
// Compute a bootstrap
|
||||
fftw_engine.discard_bootstrap_lwe_ciphertext(
|
||||
&mut ct.ct,
|
||||
&buffers.buffer_lwe_after_ks,
|
||||
acc,
|
||||
&mut ct.ct.as_old_ct_mut_view(),
|
||||
&LweCiphertextView64(buffers.buffer_lwe_after_ks.0.as_view()),
|
||||
&GlweCiphertextView64(acc.0.as_view()),
|
||||
&server_key.bootstrapping_key,
|
||||
)?;
|
||||
Ok(())
|
||||
@@ -369,12 +373,9 @@ impl ShortintEngine {
|
||||
|
||||
let shifted_value = (modular_value as u64) * delta;
|
||||
|
||||
let plaintext = self.engine.create_plaintext_from(&shifted_value).unwrap();
|
||||
let encoded = Encoded(shifted_value);
|
||||
|
||||
let ct = self
|
||||
.engine
|
||||
.trivially_encrypt_lwe_ciphertext(lwe_size, &plaintext)
|
||||
.unwrap();
|
||||
let ct = allocate_and_trivially_encrypt_new_lwe_ciphertext(lwe_size, encoded);
|
||||
|
||||
let degree = Degree(modular_value);
|
||||
|
||||
@@ -392,11 +393,6 @@ impl ShortintEngine {
|
||||
ct: &mut Ciphertext,
|
||||
value: u8,
|
||||
) -> EngineResult<()> {
|
||||
let lwe_size = server_key
|
||||
.bootstrapping_key
|
||||
.input_lwe_dimension()
|
||||
.to_lwe_size();
|
||||
|
||||
let modular_value = value as usize % server_key.message_modulus.0;
|
||||
|
||||
let delta =
|
||||
@@ -404,12 +400,10 @@ impl ShortintEngine {
|
||||
|
||||
let shifted_value = (modular_value as u64) * delta;
|
||||
|
||||
let plaintext = self.engine.create_plaintext_from(&shifted_value).unwrap();
|
||||
let encoded = Encoded(shifted_value);
|
||||
|
||||
trivially_encrypt_lwe_ciphertext(&mut ct.ct, encoded);
|
||||
|
||||
ct.ct = self
|
||||
.engine
|
||||
.trivially_encrypt_lwe_ciphertext(lwe_size, &plaintext)
|
||||
.unwrap();
|
||||
ct.degree = Degree(modular_value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use crate::core_crypto::prelude::*;
|
||||
use crate::core_crypto::algorithms::lwe_linear_algebra::{
|
||||
lwe_ciphertext_in_place_encoded_addition, lwe_ciphertext_in_place_opposite,
|
||||
};
|
||||
use crate::core_crypto::entities::encoded::Encoded;
|
||||
use crate::shortint::ciphertext::Degree;
|
||||
use crate::shortint::engine::{EngineResult, ShortintEngine};
|
||||
use crate::shortint::{Ciphertext, ServerKey};
|
||||
@@ -48,14 +51,12 @@ impl ShortintEngine {
|
||||
(1_u64 << 63) / (_server_key.message_modulus.0 * _server_key.carry_modulus.0) as u64;
|
||||
|
||||
//Scaling + 1 on the padding bit
|
||||
let w = z * delta;
|
||||
let w = Encoded(z * delta);
|
||||
|
||||
// (0,Delta*z) - ct
|
||||
self.engine.fuse_opp_lwe_ciphertext(&mut ct.ct)?;
|
||||
lwe_ciphertext_in_place_opposite(&mut ct.ct);
|
||||
|
||||
let clear_w = self.engine.create_plaintext_from(&w)?;
|
||||
self.engine
|
||||
.fuse_add_lwe_ciphertext_plaintext(&mut ct.ct, &clear_w)?;
|
||||
lwe_ciphertext_in_place_encoded_addition(&mut ct.ct, w);
|
||||
|
||||
// Update the degree
|
||||
ct.degree = Degree(z as usize);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::core_crypto::prelude::*;
|
||||
use crate::core_crypto::algorithms::lwe_linear_algebra::lwe_ciphertext_in_place_encoded_addition;
|
||||
use crate::core_crypto::entities::encoded::Encoded;
|
||||
use crate::shortint::ciphertext::Degree;
|
||||
use crate::shortint::engine::{EngineResult, ShortintEngine};
|
||||
use crate::shortint::{Ciphertext, ServerKey};
|
||||
@@ -21,9 +22,8 @@ impl ShortintEngine {
|
||||
) -> EngineResult<()> {
|
||||
let delta = (1_u64 << 63) / (ct.message_modulus.0 * ct.carry_modulus.0) as u64;
|
||||
let shift_plaintext = u64::from(scalar) * delta;
|
||||
let plaintext_scalar = self.engine.create_plaintext_from(&shift_plaintext).unwrap();
|
||||
self.engine
|
||||
.fuse_add_lwe_ciphertext_plaintext(&mut ct.ct, &plaintext_scalar)?;
|
||||
let encoded_scalar = Encoded(shift_plaintext);
|
||||
lwe_ciphertext_in_place_encoded_addition(&mut ct.ct, encoded_scalar);
|
||||
|
||||
ct.degree = Degree(ct.degree.0 + scalar as usize);
|
||||
Ok(())
|
||||
@@ -38,9 +38,8 @@ impl ShortintEngine {
|
||||
let delta =
|
||||
(1_u64 << 63) / (server_key.message_modulus.0 * server_key.carry_modulus.0) as u64;
|
||||
let shift_plaintext = u64::from(scalar) * delta;
|
||||
let plaintext_scalar = self.engine.create_plaintext_from(&shift_plaintext).unwrap();
|
||||
self.engine
|
||||
.fuse_add_lwe_ciphertext_plaintext(&mut ct.ct, &plaintext_scalar)?;
|
||||
let encoded_scalar = Encoded(shift_plaintext);
|
||||
lwe_ciphertext_in_place_encoded_addition(&mut ct.ct, encoded_scalar);
|
||||
|
||||
ct.degree = Degree(ct.degree.0 + scalar as usize);
|
||||
Ok(())
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::core_crypto::prelude::*;
|
||||
use crate::core_crypto::algorithms::lwe_linear_algebra::lwe_ciphertext_in_place_cleartext_multiplication;
|
||||
use crate::core_crypto::entities::cleartext::Cleartext;
|
||||
use crate::shortint::ciphertext::Degree;
|
||||
use crate::shortint::engine::{EngineResult, ShortintEngine};
|
||||
use crate::shortint::{Ciphertext, ServerKey};
|
||||
@@ -21,9 +22,8 @@ impl ShortintEngine {
|
||||
scalar: u8,
|
||||
) -> EngineResult<()> {
|
||||
let scalar = u64::from(scalar);
|
||||
let cleartext_scalar = self.engine.create_cleartext_from(&scalar).unwrap();
|
||||
self.engine
|
||||
.fuse_mul_lwe_ciphertext_cleartext(&mut ct.ct, &cleartext_scalar)?;
|
||||
let cleartext_scalar = Cleartext(scalar);
|
||||
lwe_ciphertext_in_place_cleartext_multiplication(&mut ct.ct, cleartext_scalar);
|
||||
|
||||
ct.degree = Degree(ct.degree.0 * scalar as usize);
|
||||
Ok(())
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::core_crypto::prelude::*;
|
||||
use crate::core_crypto::algorithms::lwe_linear_algebra::lwe_ciphertext_in_place_encoded_addition;
|
||||
use crate::core_crypto::entities::encoded::Encoded;
|
||||
use crate::shortint::ciphertext::Degree;
|
||||
use crate::shortint::engine::{EngineResult, ShortintEngine};
|
||||
use crate::shortint::{Ciphertext, ServerKey};
|
||||
@@ -22,9 +23,9 @@ impl ShortintEngine {
|
||||
let neg_scalar = u64::from(scalar.wrapping_neg()) % ct.message_modulus.0 as u64;
|
||||
let delta = (1_u64 << 63) / (ct.message_modulus.0 * ct.carry_modulus.0) as u64;
|
||||
let shift_plaintext = neg_scalar * delta;
|
||||
let plaintext_scalar = self.engine.create_plaintext_from(&shift_plaintext).unwrap();
|
||||
self.engine
|
||||
.fuse_add_lwe_ciphertext_plaintext(&mut ct.ct, &plaintext_scalar)?;
|
||||
let encoded_scalar = Encoded(shift_plaintext);
|
||||
|
||||
lwe_ciphertext_in_place_encoded_addition(&mut ct.ct, encoded_scalar);
|
||||
|
||||
ct.degree = Degree(ct.degree.0 + neg_scalar as usize);
|
||||
Ok(())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::core_crypto::prelude::*;
|
||||
use crate::core_crypto::algorithms::lwe_linear_algebra::lwe_ciphertext_in_place_addition;
|
||||
use crate::shortint::ciphertext::Degree;
|
||||
use crate::shortint::engine::{EngineResult, ShortintEngine};
|
||||
use crate::shortint::{Ciphertext, ServerKey};
|
||||
@@ -46,8 +46,7 @@ impl ShortintEngine {
|
||||
) -> EngineResult<u64> {
|
||||
let (neg_right, z) = self.unchecked_neg_with_z(server_key, ct_right)?;
|
||||
|
||||
self.engine
|
||||
.fuse_add_lwe_ciphertext(&mut ct_left.ct, &neg_right.ct)?;
|
||||
lwe_ciphertext_in_place_addition(&mut ct_left.ct, &neg_right.ct);
|
||||
|
||||
ct_left.degree = Degree(ct_left.degree.0 + z as usize);
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
//! # WARNING: this module is experimental.
|
||||
use crate::core_crypto::algorithms::lwe_encryption::allocate_and_trivially_encrypt_new_lwe_ciphertext;
|
||||
use crate::core_crypto::algorithms::lwe_linear_algebra::lwe_ciphertext_in_place_subtraction;
|
||||
use crate::core_crypto::entities::encoded::Encoded;
|
||||
use crate::core_crypto::entities::lwe_ciphertext::LweCiphertext;
|
||||
use crate::core_crypto::prelude::*;
|
||||
use crate::shortint::ciphertext::Degree;
|
||||
use crate::shortint::engine::{EngineResult, ShortintEngine};
|
||||
use crate::shortint::server_key::MaxDegree;
|
||||
use crate::shortint::wopbs::WopbsKey;
|
||||
use crate::shortint::{Ciphertext, ClientKey, Parameters, ServerKey};
|
||||
|
||||
use crate::core_crypto::prelude::*;
|
||||
use crate::shortint::server_key::MaxDegree;
|
||||
|
||||
impl ShortintEngine {
|
||||
// Creates a key when ONLY a wopbs is used.
|
||||
pub(crate) fn new_wopbs_key_only_for_wopbs(
|
||||
@@ -149,7 +152,7 @@ impl ShortintEngine {
|
||||
pub(crate) fn extract_bits(
|
||||
&mut self,
|
||||
delta_log: DeltaLog,
|
||||
lwe_in: &LweCiphertext64,
|
||||
lwe_in: &LweCiphertext<u64>,
|
||||
wopbs_key: &WopbsKey,
|
||||
extracted_bit_count: ExtractedBitsCount,
|
||||
) -> EngineResult<LweCiphertextVector64> {
|
||||
@@ -165,8 +168,8 @@ impl ShortintEngine {
|
||||
)?;
|
||||
|
||||
self.fft_engine.discard_extract_bits_lwe_ciphertext(
|
||||
&mut output,
|
||||
lwe_in,
|
||||
&mut LweCiphertextVectorMutView64(output.0.as_mut_view()),
|
||||
&lwe_in.as_old_ct_view(),
|
||||
&server_key.bootstrapping_key,
|
||||
&server_key.key_switching_key,
|
||||
extracted_bit_count,
|
||||
@@ -245,7 +248,7 @@ impl ShortintEngine {
|
||||
|
||||
let sks = &wopbs_key.wopbs_server_key;
|
||||
let ct_out = Ciphertext {
|
||||
ct: ct_out,
|
||||
ct: ct_out.into(),
|
||||
degree: Degree(sks.message_modulus.0 - 1),
|
||||
message_modulus: sks.message_modulus,
|
||||
carry_modulus: sks.carry_modulus,
|
||||
@@ -290,20 +293,20 @@ impl ShortintEngine {
|
||||
|
||||
// To make borrow checker happy
|
||||
let engine = &mut self.engine;
|
||||
let zero_plaintext = engine.create_plaintext_from(&0_u64).unwrap();
|
||||
let mut buffer_lwe_after_ks = engine
|
||||
.trivially_encrypt_lwe_ciphertext(
|
||||
wopbs_key
|
||||
.ksk_pbs_to_wopbs
|
||||
.output_lwe_dimension()
|
||||
.to_lwe_size(),
|
||||
&zero_plaintext,
|
||||
)
|
||||
.unwrap();
|
||||
let encoded_zero = Encoded(0);
|
||||
|
||||
let mut buffer_lwe_after_ks = allocate_and_trivially_encrypt_new_lwe_ciphertext(
|
||||
wopbs_key
|
||||
.ksk_pbs_to_wopbs
|
||||
.output_lwe_dimension()
|
||||
.to_lwe_size(),
|
||||
encoded_zero,
|
||||
);
|
||||
|
||||
// Compute a key switch
|
||||
engine.discard_keyswitch_lwe_ciphertext(
|
||||
&mut buffer_lwe_after_ks,
|
||||
&ct_clean.ct,
|
||||
&mut buffer_lwe_after_ks.as_old_ct_mut_view(),
|
||||
&ct_clean.ct.as_old_ct_view(),
|
||||
&wopbs_key.ksk_pbs_to_wopbs,
|
||||
)?;
|
||||
|
||||
@@ -329,8 +332,8 @@ impl ShortintEngine {
|
||||
let (buffers, engine, fftw_engine) = self.buffers_for_key(&wopbs_key.pbs_server_key);
|
||||
// Compute a key switch
|
||||
engine.discard_keyswitch_lwe_ciphertext(
|
||||
&mut buffers.buffer_lwe_after_ks,
|
||||
&ct_in.ct,
|
||||
&mut LweCiphertextMutView64(buffers.buffer_lwe_after_ks.0.as_mut_view()),
|
||||
&ct_in.ct.as_old_ct_view(),
|
||||
&wopbs_key.pbs_server_key.key_switching_key,
|
||||
)?;
|
||||
|
||||
@@ -339,13 +342,13 @@ impl ShortintEngine {
|
||||
.bootstrapping_key
|
||||
.output_lwe_dimension()
|
||||
.to_lwe_size();
|
||||
let mut ct_out = engine.create_lwe_ciphertext_from(vec![0; out_lwe_size.0])?;
|
||||
let mut ct_out = LweCiphertext::from_container(vec![0; out_lwe_size.0]);
|
||||
|
||||
// Compute a bootstrap
|
||||
fftw_engine.discard_bootstrap_lwe_ciphertext(
|
||||
&mut ct_out,
|
||||
&buffers.buffer_lwe_after_ks,
|
||||
&acc,
|
||||
&mut ct_out.as_old_ct_mut_view(),
|
||||
&LweCiphertextView64(buffers.buffer_lwe_after_ks.0.as_view()),
|
||||
&GlweCiphertextView64(acc.0.as_view()),
|
||||
&wopbs_key.pbs_server_key.bootstrapping_key,
|
||||
)?;
|
||||
Ok(Ciphertext {
|
||||
@@ -404,12 +407,13 @@ impl ShortintEngine {
|
||||
let delta_log = DeltaLog(64 - nb_bit_to_extract);
|
||||
|
||||
// trick ( ct - delta/2 + delta/2^4 )
|
||||
let lwe_size = ct_in.ct.lwe_dimension().to_lwe_size().0;
|
||||
let lwe_size = ct_in.ct.lwe_size().0;
|
||||
let mut cont = vec![0u64; lwe_size];
|
||||
cont[lwe_size - 1] =
|
||||
(1 << (64 - nb_bit_to_extract - 1)) - (1 << (64 - nb_bit_to_extract - 5));
|
||||
let tmp = self.engine.create_lwe_ciphertext_from(cont)?;
|
||||
self.engine.fuse_sub_lwe_ciphertext(&mut ct_in.ct, &tmp)?;
|
||||
let tmp = LweCiphertext::from_container(cont);
|
||||
|
||||
lwe_ciphertext_in_place_subtraction(&mut ct_in.ct, &tmp);
|
||||
|
||||
let ciphertext = self.extract_bits_circuit_bootstrapping(
|
||||
wopbs_key,
|
||||
|
||||
Reference in New Issue
Block a user