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

Release pr stack #1608

Merged
merged 5 commits into from
Sep 30, 2024
Merged
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 @@ -317,6 +317,15 @@ where
}
}

impl<G: Curve> Proof<G> {
pub fn content_is_usable(&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
66 changes: 65 additions & 1 deletion tfhe/js_on_wasm_tests/test-hlapi-signed.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
const test = require('node:test');
const assert = require('node:assert').strict;
const { performance } = require('perf_hooks');
const {performance} = require('perf_hooks');
const {
init_panic_hook,
ShortintParametersName,
ShortintParameters,
TfheClientKey,
TfhePublicKey,
TfheCompressedPublicKey,
TfheCompressedCompactPublicKey,
ShortintCompactPublicKeyEncryptionParametersName,
ShortintCompactPublicKeyEncryptionParameters,
TfheCompactPublicKey,
TfheConfigBuilder,
CompressedFheInt8,
Expand All @@ -23,6 +26,8 @@ const {
CompactPkePublicParams,
CompactPkeCrs,
ZkComputeLoad,
Shortint,
ShortintEncryptionKeyChoice,
} = require("../pkg/tfhe.js");
const {
randomBytes,
Expand Down Expand Up @@ -522,3 +527,62 @@ test('hlapi_compact_ciphertext_list_with_proof', (t) => {

// Verifying and expanding is too slow for single threaded node tests.
});


test('hlapi_compact_pk_conformance', (t) => {

const limit = BigInt(1 << 20);

let blockParams = new ShortintParameters(
ShortintParametersName.PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M64,
);
let publicKeyParams = new ShortintCompactPublicKeyEncryptionParameters(
ShortintCompactPublicKeyEncryptionParametersName.SHORTINT_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M64,
);

let config = TfheConfigBuilder.default()
.use_custom_parameters(blockParams)
.use_dedicated_compact_public_key_parameters(publicKeyParams)
.build();

let clientKey = TfheClientKey.generate(config);
let compressedPublicKey = TfheCompressedCompactPublicKey.new(clientKey);

let serializedCompressedPublicKey = compressedPublicKey.safe_serialize(limit);
let _compressedPublicKey = TfheCompressedCompactPublicKey.safe_deserialize_conformant(
serializedCompressedPublicKey, limit, publicKeyParams);

let publicKey = compressedPublicKey.decompress();
let serializedPublicKey = publicKey.safe_serialize(limit);
let _publicKey = TfheCompactPublicKey.safe_deserialize_conformant(serializedPublicKey, limit, publicKeyParams);

const message_modulus = 4;
const carry_modulus = 4;
const modulus_pow_2_exponent = 64;
const ks_level = 5;
const ks_base_log = 3;
let incorrectPublicKeyParams = ShortintCompactPublicKeyEncryptionParameters.new_parameters(
512,
Shortint.try_new_t_uniform(42),
message_modulus,
carry_modulus,
modulus_pow_2_exponent,
ks_base_log,
ks_level,
ShortintEncryptionKeyChoice.Small,
);

assert.throws(
() => {
let _compressedPublicKey = TfheCompressedCompactPublicKey.safe_deserialize_conformant(
serializedCompressedPublicKey, limit, incorrectPublicKeyParams);
},
)

assert.throws(
() => {
let _publicKey = TfheCompactPublicKey.safe_deserialize_conformant(
serializedPublicKey, limit, incorrectPublicKeyParams);
},
)
})
3 changes: 2 additions & 1 deletion tfhe/src/core_crypto/entities/glwe_ciphertext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,8 @@ where
ciphertext_modulus,
} = self;

check_encrypted_content_respects_mod(self, glwe_ct_parameters.ct_modulus)
polynomial_size.0.is_power_of_two()
&& check_encrypted_content_respects_mod(self, glwe_ct_parameters.ct_modulus)
&& data.container_len()
== glwe_ciphertext_size(
glwe_ct_parameters.glwe_dim.to_glwe_size(),
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
30 changes: 30 additions & 0 deletions tfhe/src/core_crypto/entities/lwe_compact_public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use tfhe_versionable::Versionize;

use crate::conformance::ParameterSetConformant;
use crate::core_crypto::backward_compatibility::entities::lwe_compact_public_key::LweCompactPublicKeyVersions;
use crate::core_crypto::commons::parameters::*;
use crate::core_crypto::commons::traits::*;
Expand Down Expand Up @@ -183,3 +184,32 @@ impl<Scalar: UnsignedInteger> LweCompactPublicKeyOwned<Scalar> {
Self::from_container(vec![fill_with; 2 * lwe_dimension.0], ciphertext_modulus)
}
}

#[derive(Clone, Copy)]
pub struct LweCompactPublicKeyEncryptionParameters<Scalar: UnsignedInteger> {
pub encryption_lwe_dimension: LweDimension,
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}

impl<C: Container> ParameterSetConformant for LweCompactPublicKey<C>
where
C::Element: UnsignedInteger,
{
type ParameterSet = LweCompactPublicKeyEncryptionParameters<C::Element>;

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

if !parameter_set.encryption_lwe_dimension.0.is_power_of_two() {
return false;
}

let glwe_ciphertext_conformance_parameters = GlweCiphertextConformanceParameters {
glwe_dim: GlweDimension(1),
polynomial_size: PolynomialSize(parameter_set.encryption_lwe_dimension.0),
ct_modulus: parameter_set.ciphertext_modulus,
};

glwe_ciphertext.is_conformant(&glwe_ciphertext_conformance_parameters)
}
}
27 changes: 27 additions & 0 deletions tfhe/src/core_crypto/entities/seeded_glwe_ciphertext.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! Module containing the definition of the SeededGlweCiphertext.

use misc::check_encrypted_content_respects_mod;
use tfhe_versionable::Versionize;

use crate::conformance::ParameterSetConformant;
use crate::core_crypto::algorithms::*;
use crate::core_crypto::backward_compatibility::entities::seeded_glwe_ciphertext::SeededGlweCiphertextVersions;
use crate::core_crypto::commons::math::random::{ActivatedRandomGenerator, CompressionSeed};
Expand Down Expand Up @@ -296,3 +298,28 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> CreateFrom<C>
Self::from_container(from, glwe_size, compression_seed, ciphertext_modulus)
}
}

impl<C: Container> ParameterSetConformant for SeededGlweCiphertext<C>
where
C::Element: UnsignedInteger,
{
type ParameterSet = GlweCiphertextConformanceParameters<C::Element>;

fn is_conformant(
&self,
glwe_ct_parameters: &GlweCiphertextConformanceParameters<C::Element>,
) -> bool {
let Self {
compression_seed: _,
data,
ciphertext_modulus,
glwe_size,
} = self;

glwe_ct_parameters.polynomial_size.0.is_power_of_two()
&& check_encrypted_content_respects_mod(self, glwe_ct_parameters.ct_modulus)
&& data.container_len() == glwe_ct_parameters.polynomial_size.0
&& *glwe_size == glwe_ct_parameters.glwe_dim.to_glwe_size()
&& *ciphertext_modulus == glwe_ct_parameters.ct_modulus
}
}
28 changes: 27 additions & 1 deletion tfhe/src/core_crypto/entities/seeded_lwe_compact_public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use tfhe_versionable::Versionize;

use crate::conformance::ParameterSetConformant;
use crate::core_crypto::algorithms::decompress_seeded_lwe_compact_public_key;
use crate::core_crypto::backward_compatibility::entities::seeded_lwe_compact_public_key::SeededLweCompactPublicKeyVersions;
use crate::core_crypto::commons::math::random::{ActivatedRandomGenerator, CompressionSeed};
Expand Down Expand Up @@ -118,7 +119,7 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> SeededLweCompactPu
Self {
seeded_glwe_ciphertext: SeededGlweCiphertext::from_container(
container,
GlweSize(1),
GlweDimension(1).to_glwe_size(),
compression_seed,
ciphertext_modulus,
),
Expand Down Expand Up @@ -229,3 +230,28 @@ impl<Scalar: UnsignedInteger> SeededLweCompactPublicKeyOwned<Scalar> {
)
}
}

impl<C: Container> ParameterSetConformant for SeededLweCompactPublicKey<C>
where
C::Element: UnsignedInteger,
{
type ParameterSet = LweCompactPublicKeyEncryptionParameters<C::Element>;

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

Copy link
Member

Choose a reason for hiding this comment

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

same here we need to check that the lwe dim is a power of 2 and glwe dim = 1 before chekcing the glwe

if !parameter_set.encryption_lwe_dimension.0.is_power_of_two() {
return false;
}

let glwe_ciphertext_conformance_parameters = GlweCiphertextConformanceParameters {
glwe_dim: GlweDimension(1),
polynomial_size: PolynomialSize(parameter_set.encryption_lwe_dimension.0),
ct_modulus: parameter_set.ciphertext_modulus,
};

seeded_glwe_ciphertext.is_conformant(&glwe_ciphertext_conformance_parameters)
}
}
92 changes: 92 additions & 0 deletions tfhe/src/high_level_api/compact_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ impl ParameterSetConformant for CompactCiphertextList {
#[cfg(feature = "zk-pok")]
mod zk {
use super::*;
use crate::conformance::ParameterSetConformant;
use crate::integer::ciphertext::IntegerProvenCompactCiphertextListConformanceParams;

#[derive(Clone, Serialize, Deserialize, Versionize)]
#[versionize(ProvenCompactCiphertextListVersions)]
Expand Down Expand Up @@ -363,6 +365,96 @@ mod zk {
})
}
}

impl ParameterSetConformant for ProvenCompactCiphertextList {
type ParameterSet = IntegerProvenCompactCiphertextListConformanceParams;

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

inner.is_conformant(parameter_set)
}
}

#[cfg(test)]
mod test {
use super::*;
use crate::integer::ciphertext::IntegerProvenCompactCiphertextListConformanceParams;
use crate::zk::CompactPkeCrs;
use rand::{thread_rng, Rng};

#[test]
fn conformance_zk_compact_ciphertext_list() {
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);

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::<bool>();

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

let params =
IntegerProvenCompactCiphertextListConformanceParams::from_crs_and_parameters(
params.try_into().unwrap(),
&crs,
);

assert!(proven_compact_list.is_conformant(&params));
}

#[test]
fn conformance_zk_compact_ciphertext_list_casting() {
let mut rng = thread_rng();

let params = crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M64;

let cpk_params = crate::shortint::parameters::compact_public_key_only::p_fail_2_minus_64::ks_pbs::PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M64;

let casting_params = crate::shortint::parameters::key_switching::p_fail_2_minus_64::ks_pbs::PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M64;

let config = crate::ConfigBuilder::with_custom_parameters(params)
.use_dedicated_compact_public_key_parameters((cpk_params, casting_params));

let client_key = crate::ClientKey::generate(config.clone());

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

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::<bool>();

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

let params =
IntegerProvenCompactCiphertextListConformanceParams::from_crs_and_parameters(
cpk_params, &crs,
);

assert!(proven_compact_list.is_conformant(&params));
}
}
}

pub struct CompactCiphertextListExpander {
Expand Down
20 changes: 20 additions & 0 deletions tfhe/src/high_level_api/keys/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,3 +608,23 @@ impl ParameterSetConformant for IntegerCompressedServerKey {
&& compression_is_ok
}
}

impl ParameterSetConformant for IntegerCompactPublicKey {
type ParameterSet = CompactPublicKeyEncryptionParameters;

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

key.is_conformant(parameter_set)
}
}

impl ParameterSetConformant for IntegerCompressedCompactPublicKey {
type ParameterSet = CompactPublicKeyEncryptionParameters;

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

key.is_conformant(parameter_set)
}
}
Loading
Loading