refactor(HL): disallow unpacked ZK proofs in the HL API and WASM API

- ZK timings being bad, we make the decision to always pack for ZKs
This commit is contained in:
Arthur Meyre
2024-06-06 19:47:23 +02:00
parent e4643c7919
commit 65737e83db
9 changed files with 31 additions and 98 deletions

View File

@@ -36,14 +36,19 @@ int main(void) {
assert(status == 0);
ClientKey *client_key;
status = client_key_generate(config, &client_key);
ServerKey *server_key;
status = generate_keys(config, &client_key, &server_key);
assert(status == 0);
set_server_key(server_key);
// zk proofs of encryption works only using the CompactPublicKey
CompactPublicKey *pk;
status = compact_public_key_new(client_key, &pk);
assert(status == 0);
// Then, we create the compact list
ProvenCompactCiphertextList *compact_list = NULL;
{
@@ -64,7 +69,7 @@ int main(void) {
status = compact_ciphertext_list_builder_push_u2(builder, 3);
assert(status == 0);
status = compact_ciphertext_list_builder_build_with_proof(builder, public_params,
status = compact_ciphertext_list_builder_build_with_proof_packed(builder, public_params,
ZkComputeLoadProof, &compact_list);
assert(status == 0);
@@ -124,6 +129,7 @@ int main(void) {
fhe_bool_destroy(c);
fhe_uint2_destroy(d);
client_key_destroy(client_key);
server_key_destroy(server_key);
compact_public_key_destroy(pk);
compact_pke_public_params_destroy(public_params);
compact_pke_crs_destroy(crs);

View File

@@ -36,7 +36,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
let proven_compact_list = tfhe::ProvenCompactCiphertextList::builder(&public_key)
.push(clear_a)
.push(clear_b)
.build_with_proof(public_zk_params, ZkComputeLoad::Proof)?;
.build_with_proof_packed(public_zk_params, ZkComputeLoad::Proof)?;
// Server side
let result = {

View File

@@ -484,30 +484,10 @@ test('hlapi_compact_ciphertext_list_with_proof', (t) => {
builder.push_i32(clear_i32);
builder.push_boolean(clear_bool);
builder.push_u256(clear_u256);
let list = builder.build_with_proof(public_params, ZkComputeLoad.Proof);
let list = builder.build_with_proof_packed(public_params, ZkComputeLoad.Proof);
let serialized = list.safe_serialize(BigInt(10000000));
let deserialized = ProvenCompactCiphertextList.safe_deserialize(serialized, BigInt(10000000));
let expander = deserialized.verify_and_expand(public_params, publicKey);
assert.deepStrictEqual(
expander.get_uint2(0).decrypt(clientKey),
clear_u2,
);
assert.deepStrictEqual(
expander.get_int32(1).decrypt(clientKey),
clear_i32,
);
assert.deepStrictEqual(
expander.get_bool(2).decrypt(clientKey),
clear_bool,
);
assert.deepStrictEqual(
expander.get_uint256(3).decrypt(clientKey),
clear_u256,
);
// We cannot verify packed ZK in wasm
});

View File

@@ -19,7 +19,6 @@ const {
const {
randomBytes,
} = require('node:crypto');
const {FheUint2048} = require("../pkg");
const U256_MAX = BigInt("115792089237316195423570985008687907853269984665640564039457584007913129639935");
const U128_MAX = BigInt("340282366920938463463374607431768211455");

View File

@@ -73,26 +73,6 @@ pub unsafe extern "C" fn compact_ciphertext_list_builder_build_packed(
})
}
#[cfg(feature = "zk-pok-experimental")]
#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_builder_build_with_proof(
builder: *const CompactCiphertextListBuilder,
public_params: *const CompactPkePublicParams,
compute_load: ZkComputeLoad,
list: *mut *mut ProvenCompactCiphertextList,
) -> c_int {
catch_panic(|| {
let builder = get_ref_checked(builder).unwrap();
let public_params = get_ref_checked(public_params).unwrap();
let inner = builder
.0
.build_with_proof(&public_params.0, compute_load.into())
.unwrap();
*list = Box::into_raw(Box::new(ProvenCompactCiphertextList(inner)));
})
}
#[cfg(feature = "zk-pok-experimental")]
#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_builder_build_with_proof_packed(

View File

@@ -344,17 +344,6 @@ impl CompactCiphertextListBuilder {
.expect("Internal error, invalid parameters should not have been allowed")
}
#[cfg(feature = "zk-pok-experimental")]
pub fn build_with_proof(
&self,
public_params: &CompactPkePublicParams,
compute_load: ZkComputeLoad,
) -> crate::Result<ProvenCompactCiphertextList> {
self.inner
.build_with_proof(public_params, compute_load)
.map(ProvenCompactCiphertextList)
}
#[cfg(feature = "zk-pok-experimental")]
pub fn build_with_proof_packed(
&self,

View File

@@ -1,13 +1,26 @@
use crate::zk::CompactPkeCrs;
use crate::Config;
use crate::{Config, Error};
impl CompactPkeCrs {
/// Create a new `CompactPkeCrs` from a `Config` object.
/// max_bit_size is the maximum number of bits that can be proven, e.g. 64 for a single
/// FheUint64 or 8 x FheUint8 values.
///
/// This function assumes that packing will be applied during ZK proof.
pub fn from_config(config: Config, max_bit_size: usize) -> crate::Result<Self> {
let max_num_message =
max_bit_size / config.inner.block_parameters.message_modulus().0.ilog2() as usize;
let parameters = config.inner.block_parameters;
if parameters.carry_modulus().0 < parameters.message_modulus().0 {
return Err(Error::new(
"In order to build a packed compact ciphertext list, \
parameters must have CarryModulus >= MessageModulus"
.to_string(),
));
}
let carry_and_message_bit_capacity =
(parameters.carry_modulus().0 * parameters.message_modulus().0).ilog2() as usize;
let max_num_message = max_bit_size.div_ceil(carry_and_message_bit_capacity);
let crs = Self::from_shortint_params(config.inner.block_parameters, max_num_message)?;
Ok(crs)
}

View File

@@ -948,20 +948,6 @@ impl CompactCiphertextListBuilder {
})
}
#[cfg(feature = "zk-pok-experimental")]
pub fn build_with_proof(
&self,
public_params: &CompactPkePublicParams,
compute_load: ZkComputeLoad,
) -> Result<ProvenCompactCiphertextList, JsError> {
catch_panic_result(|| {
self.0
.build_with_proof(&public_params.0, compute_load.into())
.map_err(into_js_error)
.map(ProvenCompactCiphertextList)
})
}
#[cfg(feature = "zk-pok-experimental")]
pub fn build_with_proof_packed(
&self,

View File

@@ -277,7 +277,7 @@ async function compactPublicKeyZeroKnowledge() {
let builder = CompactCiphertextList.builder(publicKey);
builder.push_u64(input);
let list = builder.build_with_proof(public_params, ZkComputeLoad.Proof);
let list = builder.build_with_proof_packed(public_params, ZkComputeLoad.Proof);
let end = performance.now();
console.log(
"Time to encrypt + prove CompactFheUint64: ",
@@ -288,16 +288,7 @@ async function compactPublicKeyZeroKnowledge() {
let bytes = list.serialize();
console.log("CompactCiphertextList size:", bytes.length);
start = performance.now();
let expander = list.verify_and_expand(public_params, publicKey);
end = performance.now();
console.log(
"Time to verify + expand CompactFheUint64: ",
end - start,
" ms",
);
assert_eq(expander.get_uint64(0).decrypt(clientKey), input);
// We cannot expand a packed list in WASM
}
{
@@ -312,7 +303,7 @@ async function compactPublicKeyZeroKnowledge() {
for (let input of inputs) {
builder.push_u64(input);
}
let encrypted = builder.build_with_proof(
let encrypted = builder.build_with_proof_packed(
public_params,
ZkComputeLoad.Proof,
);
@@ -323,18 +314,7 @@ async function compactPublicKeyZeroKnowledge() {
" ms",
);
start = performance.now();
let expander = encrypted.verify_and_expand(public_params, publicKey);
end = performance.now();
console.log(
"Time to verify + expand CompactFheUint64: ",
end - start,
" ms",
);
for (let i = 0; i < inputs.length; i++) {
assert_eq(expander.get_uint64(i).decrypt(clientKey), inputs[i]);
}
// We cannot expand a packed list in WASM
}
}