refactor(shortint): change the LweCiphertext type

This commit is contained in:
Arthur Meyre
2022-11-17 18:00:20 +01:00
committed by jborfila
parent 1c40890aeb
commit 3185310610
18 changed files with 278 additions and 111 deletions

View File

@@ -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>,

View 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());
}

View File

@@ -1,4 +1,3 @@
pub mod lwe_encryption;
pub mod lwe_linear_algebra;
pub mod slice_algorithms;
pub use slice_algorithms::*;

View File

@@ -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));
}

View File

@@ -0,0 +1,4 @@
use crate::core_crypto::commons::numeric::Numeric;
/// A cleartext, not encoded, value
pub struct Cleartext<T: Numeric>(pub T);

View File

@@ -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>>;

View File

@@ -1,3 +1,4 @@
pub mod cleartext;
pub mod encoded;
pub mod lwe_ciphertext;
pub mod lwe_secret_key;

View File

@@ -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,

View File

@@ -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;

View File

@@ -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,
),

View File

@@ -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(())
}

View File

@@ -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(())
}

View File

@@ -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);

View File

@@ -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(())

View File

@@ -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(())

View File

@@ -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(())

View File

@@ -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);

View File

@@ -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,