Skip to content
Open
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
207 changes: 199 additions & 8 deletions tests/backward_compatibility/high_level_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@ use tfhe::zk::{CompactPkeCrs, CompactPkeCrsConformanceParams};
use tfhe::ProvenCompactCiphertextList;
use tfhe::{
set_server_key, ClientKey, CompactCiphertextList, CompactCiphertextListBuilder,
CompactPublicKey, CompressedCiphertextList, CompressedCiphertextListBuilder,
CompressedCompactPublicKey, CompressedFheBool, CompressedFheInt8, CompressedFheUint8,
CompressedKVStore, CompressedPublicKey, CompressedServerKey,
CompressedSquashedNoiseCiphertextList, CompressedSquashedNoiseCiphertextListBuilder, FheBool,
FheInt8, FheUint32, FheUint64, FheUint8, ReRandomizationContext, ReRandomizationMode,
ReRandomizationSupport, ServerKey, SquashedNoiseFheBool, SquashedNoiseFheInt,
SquashedNoiseFheUint,
CompactCiphertextListExpander, CompactPublicKey, CompressedCiphertextList,
CompressedCiphertextListBuilder, CompressedCompactPublicKey, CompressedFheBool,
CompressedFheInt8, CompressedFheUint8, CompressedKVStore, CompressedPublicKey,
CompressedServerKey, CompressedSquashedNoiseCiphertextList,
CompressedSquashedNoiseCiphertextListBuilder, FheBool, FheInt8, FheUint32, FheUint64, FheUint8,
ReRandomizationContext, ReRandomizationMode, ReRandomizationSupport, ServerKey,
SquashedNoiseFheBool, SquashedNoiseFheInt, SquashedNoiseFheUint,
};
use tfhe_backward_compat_data::load::{
load_versioned_auxiliary, DataFormat, TestFailure, TestResult, TestSuccess,
};
use tfhe_backward_compat_data::{
DataKind, HlBoolCiphertextTest, HlCiphertextTest, HlClientKeyTest, HlCompressedKVStoreTest,
HlCompressedSquashedNoiseCiphertextListTest, HlCompressedXofKeySetTest,
HlHeterogeneousCiphertextListTest, HlPublicKeyTest, HlServerKeyTest, HlSignedCiphertextTest,
HlHeterogeneousCiphertextListTest, HlPublicKeyTest, HlSeededCompactCiphertextListTest,
HlSeededProvenCompactCiphertextListTest, HlServerKeyTest, HlSignedCiphertextTest,
HlSquashedNoiseBoolCiphertextTest, HlSquashedNoiseSignedCiphertextTest,
HlSquashedNoiseUnsignedCiphertextTest, TestMetadata, TestType, Testcase, ZkPkePublicParamsTest,
};
Expand Down Expand Up @@ -287,6 +288,189 @@ pub fn test_hl_heterogeneous_ciphertext_list_elements<CtList: CiphertextList>(
Ok(())
}

fn verify_expanded_values(
expander: &CompactCiphertextListExpander,
clear_values: &[u64],
data_kinds: &[DataKind],
key: &ClientKey,
) -> Result<(), String> {
for (idx, (value, kind)) in clear_values.iter().zip(data_kinds.iter()).enumerate() {
match kind {
DataKind::Bool => {
let ct: FheBool = expander
.get(idx)
.map_err(|e| format!("Failed to get bool at index {idx}: {e}"))?
.ok_or_else(|| format!("No value at index {idx}"))?;
let clear = ct.decrypt(key);
if clear != (*value != 0) {
return Err(format!(
"Invalid decrypted bool at index {idx}: expected {:?}, got {clear:?}",
*value != 0
));
}
}
DataKind::Signed => {
let ct: FheInt8 = expander
.get(idx)
.map_err(|e| format!("Failed to get signed at index {idx}: {e}"))?
.ok_or_else(|| format!("No value at index {idx}"))?;
let clear: i8 = ct.decrypt(key);
if clear != *value as i8 {
return Err(format!(
"Invalid decrypted signed at index {idx}: expected {:?}, got {clear:?}",
*value as i8
));
}
}
DataKind::Unsigned => {
let ct: FheUint8 = expander
.get(idx)
.map_err(|e| format!("Failed to get unsigned at index {idx}: {e}"))?
.ok_or_else(|| format!("No value at index {idx}"))?;
let clear: u8 = ct.decrypt(key);
if clear != *value as u8 {
return Err(format!(
"Invalid decrypted unsigned at index {idx}: expected {:?}, got {clear:?}",
*value as u8
));
}
}
}
}
Ok(())
}

/// Test seeded compact ciphertext list: loads pregenerated list, rebuilds from
/// stored values/seed, asserts they match via PartialEq.
pub fn test_hl_seeded_compact_ciphertext_list(
dir: &Path,
test: &HlSeededCompactCiphertextListTest,
format: DataFormat,
) -> Result<TestSuccess, TestFailure> {
let key_file = dir.join(&*test.key_filename);
let key = ClientKey::unversionize(
load_versioned_auxiliary(key_file).map_err(|e| test.failure(e, format))?,
)
.map_err(|e| test.failure(e, format))?;

let server_key = key.generate_server_key();
set_server_key(server_key);

let pubkey_file = dir.join(&*test.public_key_filename);
let pubkey = CompactPublicKey::unversionize(
load_versioned_auxiliary(pubkey_file).map_err(|e| test.failure(e, format))?,
)
.map_err(|e| test.failure(e, format))?;

let pregenerated: CompactCiphertextList = load_and_unversionize(dir, test, format)?;

let mut builder = CompactCiphertextList::builder(&pubkey);
for (value, kind) in test.clear_values.iter().zip(test.data_kinds.iter()) {
match kind {
DataKind::Unsigned => {
builder.push(*value as u8);
}
DataKind::Signed => {
builder.push(*value as i8);
}
DataKind::Bool => {
builder.push(*value != 0);
}
}
}
let rebuilt = builder.build_packed_seeded(&test.seed).unwrap();

if pregenerated != rebuilt {
return Err(test.failure(
"Seeded compact list rebuilt from values/seed does not match pregenerated",
format,
));
}

let expanded = pregenerated.expand().map_err(|e| test.failure(e, format))?;
verify_expanded_values(&expanded, &test.clear_values, &test.data_kinds, &key)
.map_err(|e| test.failure(e, format))?;

Ok(test.success(format))
}

/// Test seeded proven compact ciphertext list: loads pregenerated list, rebuilds
/// from stored values/seed/proof params, asserts they match via PartialEq.
pub fn test_hl_seeded_proven_compact_ciphertext_list(
dir: &Path,
test: &HlSeededProvenCompactCiphertextListTest,
format: DataFormat,
) -> Result<TestSuccess, TestFailure> {
#[cfg(feature = "zk-pok")]
{
use tfhe::zk::ZkComputeLoad;

let key_file = dir.join(&*test.key_filename);
let key = ClientKey::unversionize(
load_versioned_auxiliary(key_file).map_err(|e| test.failure(e, format))?,
)
.map_err(|e| test.failure(e, format))?;

let server_key = key.generate_server_key();
set_server_key(server_key);

let pubkey_file = dir.join(&*test.public_key_filename);
let pubkey = CompactPublicKey::unversionize(
load_versioned_auxiliary(pubkey_file).map_err(|e| test.failure(e, format))?,
)
.map_err(|e| test.failure(e, format))?;

let crs_file = dir.join(&*test.proof_info.params_filename);
let crs = CompactPkeCrs::unversionize(
load_versioned_auxiliary(crs_file).map_err(|e| test.failure(e, format))?,
)
.map_err(|e| test.failure(e, format))?;

let pregenerated: ProvenCompactCiphertextList = load_and_unversionize(dir, test, format)?;

let mut builder = ProvenCompactCiphertextList::builder(&pubkey);
for (value, kind) in test.clear_values.iter().zip(test.data_kinds.iter()) {
match kind {
DataKind::Unsigned => {
builder.push(*value as u8);
}
DataKind::Signed => {
builder.push(*value as i8);
}
DataKind::Bool => {
builder.push(*value != 0);
}
}
}
let rebuilt = builder
.build_with_proof_packed_seeded(
&crs,
test.proof_info.metadata.as_bytes(),
ZkComputeLoad::Proof,
&test.seed,
)
.map_err(|e| test.failure(e, format))?;

if pregenerated != rebuilt {
return Err(test.failure(
"Seeded proven compact list rebuilt from values/seed does not match pregenerated",
format,
));
}

let expanded = pregenerated
.verify_and_expand(&crs, &pubkey, test.proof_info.metadata.as_bytes())
.map_err(|e| test.failure(e, format))?;
verify_expanded_values(&expanded, &test.clear_values, &test.data_kinds, &key)
.map_err(|e| test.failure(e, format))?;
}

#[cfg(not(feature = "zk-pok"))]
let _ = dir;

Ok(test.success(format))
}

/// Test HL client key: loads the key and checks the parameters using the values stored in
/// the test metadata.
pub fn test_hl_clientkey(
Expand Down Expand Up @@ -953,6 +1137,13 @@ impl TestedModule for Hl {
TestMetadata::HlCompressedXofKeySet(test) => {
test_hl_compressed_xof_key_set_test(test_dir.as_ref(), test, format).into()
}
TestMetadata::HlSeededCompactCiphertextList(test) => {
test_hl_seeded_compact_ciphertext_list(test_dir.as_ref(), test, format).into()
}
TestMetadata::HlSeededProvenCompactCiphertextList(test) => {
test_hl_seeded_proven_compact_ciphertext_list(test_dir.as_ref(), test, format)
.into()
}
_ => {
println!("WARNING: missing test: {:?}", testcase.metadata);
TestResult::Skipped(testcase.skip())
Expand Down
2 changes: 1 addition & 1 deletion tfhe-csprng/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tfhe-csprng"
version = "0.8.0"
version = "0.9.0"
edition = "2021"
license = "BSD-3-Clause-Clear"
description = "Cryptographically Secure PRNG used in the TFHE-rs library."
Expand Down
2 changes: 1 addition & 1 deletion tfhe-zk-pok/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tfhe-zk-pok"
version = "0.8.0"
version = "0.8.1"
edition = "2021"
keywords = ["zero", "knowledge", "proof", "vector-commitments"]
homepage = "https://zama.org/"
Expand Down
4 changes: 2 additions & 2 deletions tfhe-zk-pok/src/curve_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,9 +446,9 @@ impl PairingGroupOps<bls12_446::Zp, bls12_446::G1, bls12_446::G2> for bls12_446:

// These are just ZSTs that are not actually produced and are only used for their
// associated types. So it's ok to derive "NotVersioned" for them.
#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize, NotVersioned)]
#[derive(Debug, Copy, Clone, PartialEq, serde::Serialize, serde::Deserialize, NotVersioned)]
pub struct Bls12_381;
#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize, NotVersioned)]
#[derive(Debug, Copy, Clone, PartialEq, serde::Serialize, serde::Deserialize, NotVersioned)]
pub struct Bls12_446;

impl Curve for Bls12_381 {
Expand Down
4 changes: 2 additions & 2 deletions tfhe-zk-pok/src/proofs/pke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ impl<G: Curve> PublicParams<G> {
}
}

#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Versionize)]
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, Versionize)]
#[serde(bound(
deserialize = "G: Curve, G::G1: serde::Deserialize<'de>, G::G2: serde::Deserialize<'de>",
serialize = "G: Curve, G::G1: serde::Serialize, G::G2: serde::Serialize"
Expand Down Expand Up @@ -325,7 +325,7 @@ impl<G: Curve> Proof<G> {

/// These fields can be pre-computed on the prover side in the faster Verifier scheme. If that's the
/// case, they should be included in the proof.
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Versionize)]
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, Versionize)]
#[serde(bound(
deserialize = "G: Curve, G::G1: serde::Deserialize<'de>, G::G2: serde::Deserialize<'de>",
serialize = "G: Curve, G::G1: serde::Serialize, G::G2: serde::Serialize"
Expand Down
2 changes: 1 addition & 1 deletion tfhe-zk-pok/src/proofs/pke_v2/hashes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl PkeV2HashConfig {
/// List of hash config that were used for a given version of this crate
///
/// This is stored in the proof so that we only support a specific subset of all possible config.
#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, Versionize)]
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Versionize)]
#[versionize(PkeV2SupportedHashConfigVersions)]
pub enum PkeV2SupportedHashConfig {
V0_4_0 = 0,
Expand Down
4 changes: 2 additions & 2 deletions tfhe-zk-pok/src/proofs/pke_v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ impl<G: Curve> PublicParams<G> {

/// This represents a proof that the given ciphertext is a valid encryptions of the input messages
/// with the provided public key.
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Versionize)]
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, Versionize)]
#[serde(bound(
deserialize = "G: Curve, G::G1: serde::Deserialize<'de>, G::G2: serde::Deserialize<'de>",
serialize = "G: Curve, G::G1: serde::Serialize, G::G2: serde::Serialize"
Expand Down Expand Up @@ -428,7 +428,7 @@ impl<G: Curve> Proof<G> {

/// These fields can be pre-computed on the prover side in the faster Verifier scheme. If that's the
/// case, they should be included in the proof.
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Versionize)]
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, Versionize)]
#[versionize(ComputeLoadProofFieldsVersions)]
pub(crate) struct ComputeLoadProofFields<G: Curve> {
pub(crate) C_hat_h3: G::G2,
Expand Down
4 changes: 2 additions & 2 deletions tfhe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ clap-num = { version = "1.1.1" }
cbindgen = { version = "0.28", optional = true }

[dependencies]
tfhe-csprng = { version = "0.8.0", path = "../tfhe-csprng", features = [
tfhe-csprng = { version = "0.9.0", path = "../tfhe-csprng", features = [
"parallel",
] }
serde = { workspace = true, features = ["default", "derive"] }
Expand All @@ -78,7 +78,7 @@ blake3 = { version = "1.8", optional = true }
itertools = { workspace = true }
rand_core = { version = "0.6.4", features = ["std"] }
strum = { version = "0.27", features = ["derive"], optional = true }
tfhe-zk-pok = { version = "0.8.0", path = "../tfhe-zk-pok", optional = true }
tfhe-zk-pok = { version = "0.8.1", path = "../tfhe-zk-pok", optional = true }
tfhe-versionable = { version = "0.7.0", path = "../utils/tfhe-versionable" }

# wasm deps
Expand Down
Loading
Loading