Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

conformance ProvenCompactCiphertextList #1602

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions tfhe-zk-pok/src/proofs/pke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ pub struct Proof<G: Curve> {
pi_kzg: Option<G::G1>,
}

impl<G: Curve> Proof<G> {
pub fn is_valid(&self) -> bool {
matches!(
(self.c_hat_t, self.c_h, self.pi_kzg),
(None, None, None) | (Some(_), Some(_), Some(_))
)
}
}

#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct PublicCommit<G: Curve> {
a: Vec<i64>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ pub type LweCompactCiphertextListMutView<'data, Scalar> =
/// Structure to store the expected properties of a ciphertext
/// Can be used on a server to check if client inputs are well formed
/// before running a computation on them
#[derive(Copy, Clone)]
pub struct LweCiphertextListParameters<T: UnsignedInteger> {
pub lwe_dim: LweDimension,
pub lwe_ciphertext_count_constraint: ListSizeConstraint,
Expand Down
59 changes: 59 additions & 0 deletions tfhe/src/high_level_api/compact_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ impl ParameterSetConformant for CompactCiphertextList {
#[cfg(feature = "zk-pok")]
mod zk {
use super::*;
use crate::conformance::ParameterSetConformant;
use crate::shortint::parameters::CompactCiphertextListExpansionKind;
use crate::shortint::ClassicPBSParameters;
use crate::zk::CompactPkeCrs;

#[derive(Clone, Serialize, Deserialize)]
pub struct ProvenCompactCiphertextList {
Expand Down Expand Up @@ -359,6 +363,61 @@ mod zk {
})
}
}

impl ParameterSetConformant for ProvenCompactCiphertextList {
type ParameterSet = (
ClassicPBSParameters,
CompactPkeCrs,
CompactCiphertextListExpansionKind,
);

fn is_conformant(&self, parameter_set: &Self::ParameterSet) -> bool {
let Self { inner, tag: _ } = self;

inner.is_conformant(parameter_set)
}
}

#[cfg(test)]
mod test {
use rand::{thread_rng, Rng};

use crate::shortint::PBSOrder;
use crate::zk::CompactPkeCrs;

use super::*;
#[test]
fn conformanceaa() {
let mut rng = thread_rng();

let params: crate::shortint::ClassicPBSParameters =
crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M64;
let config = crate::ConfigBuilder::with_custom_parameters(params);
Comment on lines +393 to +395
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need a test case with casting


let client_key = crate::ClientKey::generate(config.clone());
// This is done in an offline phase and the CRS is shared to all clients and the server
let crs = CompactPkeCrs::from_config(config.into(), 64).unwrap();
let public_zk_params = crs.public_params();
let public_key = crate::CompactPublicKey::try_new(&client_key).unwrap();
// This can be left empty, but if provided allows to tie the proof to arbitrary data
let metadata = [b'T', b'F', b'H', b'E', b'-', b'r', b's'];

let clear_a = rng.gen::<u64>();
let clear_b = rng.gen::<u64>();

let proven_compact_list = crate::ProvenCompactCiphertextList::builder(&public_key)
.push(clear_a)
.push(clear_b)
.build_with_proof_packed(public_zk_params, &metadata, ZkComputeLoad::Proof)
.unwrap();

assert!(proven_compact_list.is_conformant(&(
params,
crs,
CompactCiphertextListExpansionKind::NoCasting(PBSOrder::KeyswitchBootstrap,)
)));
}
}
}

pub struct CompactCiphertextListExpander {
Expand Down
32 changes: 32 additions & 0 deletions tfhe/src/integer/ciphertext/compact_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,16 @@ pub use crate::integer::parameters::{
IntegerCompactCiphertextListCastingMode, IntegerCompactCiphertextListUnpackingMode,
};
use crate::integer::{CompactPublicKey, ServerKey};
#[cfg(feature = "zk-pok")]
use crate::shortint::ciphertext::ProvenCompactCiphertextListConformanceParams;
use crate::shortint::parameters::CiphertextConformanceParams;
#[cfg(feature = "zk-pok")]
use crate::shortint::parameters::CompactCiphertextListExpansionKind;
#[cfg(feature = "zk-pok")]
use crate::shortint::ClassicPBSParameters;
use crate::shortint::{Ciphertext, MessageModulus};
#[cfg(feature = "zk-pok")]
use crate::zk::CompactPkeCrs;
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use tfhe_versionable::Versionize;
Expand Down Expand Up @@ -726,6 +734,30 @@ impl ProvenCompactCiphertextList {
}
}

#[cfg(feature = "zk-pok")]
impl ParameterSetConformant for ProvenCompactCiphertextList {
type ParameterSet = (
ClassicPBSParameters,
CompactPkeCrs,
CompactCiphertextListExpansionKind,
);

fn is_conformant(&self, parameter_set: &Self::ParameterSet) -> bool {
let Self { ct_list, info } = self;

let expected_len = info.iter().map(|a| a.num_blocks()).sum();

let a = ProvenCompactCiphertextListConformanceParams {
sk_params: parameter_set.0,
elements_per_block: parameter_set.1.public_params().k,
expected_len,
expansion_kind: parameter_set.2,
};

ct_list.is_conformant(&a)
}
}

#[cfg(feature = "zk-pok")]
#[cfg(test)]
mod tests {
Expand Down
75 changes: 74 additions & 1 deletion tfhe/src/shortint/ciphertext/zk.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
use crate::conformance::{ListSizeConstraint, ParameterSetConformant};
use crate::core_crypto::algorithms::verify_lwe_compact_ciphertext_list;
use crate::core_crypto::prelude::LweCiphertextListParameters;
use crate::shortint::ciphertext::CompactCiphertextList;
use crate::shortint::parameters::{
CiphertextListConformanceParams, CompactCiphertextListExpansionKind,
CompactPublicKeyEncryptionParameters, MessageModulus, ShortintCompactCiphertextListCastingMode,
};
use crate::shortint::{Ciphertext, CompactPublicKey};
use crate::shortint::{Ciphertext, ClassicPBSParameters, CompactPublicKey};
use crate::zk::{
CompactPkeCrs, CompactPkeProof, CompactPkePublicParams, ZkMSBZeroPaddingBitCount,
ZkVerificationOutCome,
};
use rayon::prelude::*;
use serde::{Deserialize, Serialize};

use super::{Degree, NoiseLevel};

impl CompactPkeCrs {
/// Construct the CRS that corresponds to the given parameters
///
Expand Down Expand Up @@ -141,6 +146,74 @@ impl ProvenCompactCiphertextList {
}
}

pub struct ProvenCompactCiphertextListConformanceParams {
pub sk_params: ClassicPBSParameters,
pub elements_per_block: usize,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be called elements_per_list/elements_per_vec/elements_per_sublist, I think block may be too confusing with integer blocks

pub expected_len: usize,
pub expansion_kind: CompactCiphertextListExpansionKind,
}

impl ParameterSetConformant for ProvenCompactCiphertextList {
type ParameterSet = ProvenCompactCiphertextListConformanceParams;

fn is_conformant(&self, parameter_set: &Self::ParameterSet) -> bool {
let Self { proved_lists } = self;

let ProvenCompactCiphertextListConformanceParams {
sk_params,
elements_per_block,
expected_len: full_expected_len,
expansion_kind,
} = parameter_set;

let mut remaining_len = *full_expected_len;

let elements_per_block = *elements_per_block;

for (compatc_ct_lict, proof) in proved_lists {
if remaining_len == 0 {
return false;
}

let expected_len;

if remaining_len > elements_per_block {
remaining_len -= elements_per_block;

expected_len = elements_per_block
} else {
expected_len = remaining_len;
remaining_len = 0;
};

let params = CiphertextListConformanceParams {
ct_list_params: LweCiphertextListParameters {
lwe_dim: sk_params
.glwe_dimension
.to_equivalent_lwe_dimension(sk_params.polynomial_size),
lwe_ciphertext_count_constraint: ListSizeConstraint::exact_size(expected_len),
ct_modulus: sk_params.ciphertext_modulus,
},
message_modulus: sk_params.message_modulus,
carry_modulus: sk_params.carry_modulus,
degree: Degree::new(sk_params.message_modulus.0 * sk_params.message_modulus.0 - 1),
noise_level: NoiseLevel::NOMINAL,
expansion_kind: *expansion_kind,
};

if !proof.is_valid() {
return false;
}
Comment on lines +204 to +206
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this API name is confusing, so more "content_is_usable"


if !compatc_ct_lict.is_conformant(&params) {
return false;
}
}

true
}
}

#[cfg(test)]
mod tests {
use crate::shortint::parameters::{
Expand Down
1 change: 1 addition & 0 deletions tfhe/src/shortint/parameters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ pub struct CompressedCiphertextConformanceParams {
/// Structure to store the expected properties of a ciphertext list
/// Can be used on a server to check if client inputs are well formed
/// before running a computation on them
#[derive(Copy, Clone)]
pub struct CiphertextListConformanceParams {
pub ct_list_params: LweCiphertextListParameters<u64>,
pub message_modulus: MessageModulus,
Expand Down
Loading