From aebaab39e18a1c114e2aaae62ec9061d49f7a78a Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Fri, 19 Jan 2024 15:19:44 +0100 Subject: [PATCH] fix: prevent precomputed shares from being created with inapprioriate variant --- ferveo-wasm/examples/node/src/main.test.ts | 24 +++++---------- ferveo-wasm/tests/node.rs | 34 ++++++++-------------- ferveo/src/api.rs | 10 +++++-- ferveo/src/bindings_python.rs | 5 ++++ ferveo/src/lib.rs | 4 +++ 5 files changed, 37 insertions(+), 40 deletions(-) diff --git a/ferveo-wasm/examples/node/src/main.test.ts b/ferveo-wasm/examples/node/src/main.test.ts index 28144861..047beeb5 100644 --- a/ferveo-wasm/examples/node/src/main.test.ts +++ b/ferveo-wasm/examples/node/src/main.test.ts @@ -22,11 +22,8 @@ const genEthAddr = (i: number) => { return EthereumAddress.fromString(ethAddr); }; -function setupTest() { - const tau = 1; - const sharesNum = 4; - const threshold = Math.floor((sharesNum * 2) / 3); - +const tau = 1; +function setupTest(sharesNum :number, threshold: number) { const validatorKeypairs: Keypair[] = []; const validators: Validator[] = []; for (let i = 0; i < sharesNum; i++) { @@ -63,9 +60,6 @@ function setupTest() { const ciphertext = ferveoEncrypt(msg, aad, dkg.publicKey()); return { - tau, - sharesNum, - threshold, validatorKeypairs, validators, dkg, @@ -79,17 +73,16 @@ function setupTest() { // This test suite replicates tests from ferveo-wasm/tests/node.rs describe("ferveo-wasm", () => { it("simple tdec variant", () => { + const sharesNum = 4; + const threshold = 3; const { - tau, - sharesNum, - threshold, validatorKeypairs, validators, messages, msg, aad, ciphertext, - } = setupTest(); + } = setupTest(sharesNum, threshold); // Having aggregated the transcripts, the validators can now create decryption shares const decryptionShares: DecryptionShareSimple[] = []; @@ -128,17 +121,16 @@ describe("ferveo-wasm", () => { }); it("precomputed tdec variant", () => { + const sharesNum = 4; + const threshold = sharesNum; // threshold is equal to sharesNum in precomputed variant const { - tau, - sharesNum, - threshold, validatorKeypairs, validators, messages, msg, aad, ciphertext, - } = setupTest(); + } = setupTest(sharesNum, threshold); // Having aggregated the transcripts, the validators can now create decryption shares const decryptionShares: DecryptionSharePrecomputed[] = []; diff --git a/ferveo-wasm/tests/node.rs b/ferveo-wasm/tests/node.rs index 4ac71429..68e5f641 100644 --- a/ferveo-wasm/tests/node.rs +++ b/ferveo-wasm/tests/node.rs @@ -7,9 +7,6 @@ use itertools::zip_eq; use wasm_bindgen_test::*; type TestSetup = ( - u32, - u32, - u32, Vec, Vec, ValidatorArray, @@ -19,11 +16,9 @@ type TestSetup = ( Ciphertext, ); -fn setup_dkg() -> TestSetup { - let tau = 1; - let shares_num: u32 = 16; - let security_threshold = shares_num * 2 / 3; +const TAU: u32 = 0; +fn setup_dkg(shares_num: u32, security_threshold: u32) -> TestSetup { let validator_keypairs = (0..shares_num as usize) .map(gen_keypair) .collect::>(); @@ -38,7 +33,7 @@ fn setup_dkg() -> TestSetup { // validator, including themselves let messages = validators.iter().map(|sender| { let dkg = Dkg::new( - tau, + TAU, shares_num, security_threshold, &validators_js, @@ -54,7 +49,7 @@ fn setup_dkg() -> TestSetup { // every validator can aggregate the transcripts let mut dkg = Dkg::new( - tau, + TAU, shares_num, security_threshold, &validators_js, @@ -80,9 +75,6 @@ fn setup_dkg() -> TestSetup { let ciphertext = ferveo_encrypt(&msg, &aad, &dkg.public_key()).unwrap(); ( - tau, - shares_num, - security_threshold, validator_keypairs, validators, validators_js, @@ -95,10 +87,9 @@ fn setup_dkg() -> TestSetup { #[wasm_bindgen_test] fn tdec_simple() { + let shares_num = 16; + let security_threshold = 10; let ( - tau, - shares_num, - security_threshold, validator_keypairs, validators, validators_js, @@ -106,13 +97,13 @@ fn tdec_simple() { msg, aad, ciphertext, - ) = setup_dkg(); + ) = setup_dkg(shares_num, security_threshold); // Having aggregated the transcripts, the validators can now create decryption shares let decryption_shares = zip_eq(validators, validator_keypairs) .map(|(validator, keypair)| { let mut dkg = Dkg::new( - tau, + TAU, shares_num, security_threshold, &validators_js, @@ -149,10 +140,9 @@ fn tdec_simple() { #[wasm_bindgen_test] fn tdec_precomputed() { + let shares_num = 16; + let security_threshold = shares_num; // Must be equal to shares_num in precomputed variant let ( - tau, - shares_num, - security_threshold, validator_keypairs, validators, validators_js, @@ -160,13 +150,13 @@ fn tdec_precomputed() { msg, aad, ciphertext, - ) = setup_dkg(); + ) = setup_dkg(shares_num, security_threshold); // Having aggregated the transcripts, the validators can now create decryption shares let decryption_shares = zip_eq(validators, validator_keypairs) .map(|(validator, keypair)| { let mut dkg = Dkg::new( - tau, + TAU, shares_num, security_threshold, &validators_js, diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index 0a8bf2aa..3c2295d1 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -309,6 +309,14 @@ impl AggregatedTranscript { aad: &[u8], validator_keypair: &Keypair, ) -> Result { + if dkg.0.dkg_params.shares_num() + != dkg.0.dkg_params.security_threshold() + { + return Err(Error::InvalidDkgParametersForPrecomputedVariant( + dkg.0.dkg_params.shares_num(), + dkg.0.dkg_params.security_threshold(), + )); + } let domain_points: Vec<_> = dkg .0 .domain @@ -455,8 +463,6 @@ mod test_ferveo_api { let rng = &mut StdRng::seed_from_u64(0); // In precomputed variant, the security threshold is equal to the number of shares - // TODO: Refactor DKG constructor to not require security threshold or this case. - // Or figure out a different way to simplify the precomputed variant API. let security_threshold = shares_num; let (messages, validators, validator_keypairs) = diff --git a/ferveo/src/bindings_python.rs b/ferveo/src/bindings_python.rs index 411b42c5..f897c8f6 100644 --- a/ferveo/src/bindings_python.rs +++ b/ferveo/src/bindings_python.rs @@ -104,6 +104,11 @@ impl From for PyErr { "{index}" )) }, + Error::InvalidDkgParametersForPrecomputedVariant(num_shares, security_threshold) => { + InvalidDkgParameters::new_err(format!( + "num_shares: {num_shares}, security_threshold: {security_threshold}" + )) + }, }, _ => default(), } diff --git a/ferveo/src/lib.rs b/ferveo/src/lib.rs index 394afb1a..c316c815 100644 --- a/ferveo/src/lib.rs +++ b/ferveo/src/lib.rs @@ -114,6 +114,10 @@ pub enum Error { /// Failed to access a share for a given share index #[error("Invalid share index: {0}")] InvalidShareIndex(u32), + + /// Failed to produce a precomputed variant decryption share + #[error("Invalid DKG parameters for precomputed variant: number of shares {0}, threshold {1}")] + InvalidDkgParametersForPrecomputedVariant(u32, u32), } pub type Result = std::result::Result;