From 2668555f38f2c00b0ac2936f13ef9d94d216ba79 Mon Sep 17 00:00:00 2001 From: natalie Date: Wed, 31 May 2023 22:23:29 +0100 Subject: [PATCH] Refactor test folders (#366) * move test functions that differ from other ciphersuites to make gencode simpler to use (#364) * Refactored folder structure for ristretto255 (#364) * Add batch and signing tests folders to ristretto255 (#364) * Refactor test folders for ed25519 (#364) * Refactor test folders for ed448 (#364) * Refactor test folders for ed448 (#364) * Refactor test folders for secp256k1 (#364) * Refactor test folders for frost-core (#364) Update ciphersuites due to refactoring in core * Update coverage tool to exclude new test files (#364) * Rename signing_tests to ciphersuite_generic_tests to match frost-core (#364) * Set default branch as main in codecov (#364) * Fix incorrect file name in gencode (#364) * Remove test file targets in gencode and replace with only md files (#364) * Rename helper_functions to helpers (#364) Remove unecessary test traits * Rename ciphersuite tests (#364) * Rename test_helpers to helpers (#364) * move tests to integration_tests (#364) * Re-add dkg.rs and repairable.rs to gendoc (#364) * Refactored rest of ciphersuite integration tests (#364) * Fix fmt in gencode (#364) --- .github/workflows/coverage.yaml | 4 +- README.md | 2 +- codecov.yml | 3 + frost-core/src/tests.rs | 492 +----------------- frost-core/src/tests/ciphersuite_generic.rs | 325 ++++++++++++ .../src/tests/coefficient_commitment.rs | 69 +++ frost-core/src/tests/helpers.rs | 12 + frost-core/src/tests/repairable.rs | 8 +- frost-core/src/tests/vss_commitment.rs | 109 ++++ frost-ed25519/src/keys/repairable.rs | 37 ++ frost-ed25519/src/tests.rs | 34 +- frost-ed25519/src/tests/batch.rs | 17 + .../src/tests/coefficient_commitment.rs | 46 ++ frost-ed25519/src/tests/deserialize.rs | 21 + frost-ed25519/{ => src}/tests/proptests.rs | 2 +- frost-ed25519/src/tests/vss_commitment.rs | 32 ++ frost-ed25519/tests.rs | 4 + frost-ed25519/tests/frost.rs | 169 ------ .../tests/{ => helpers}/elements.json | 0 frost-ed25519/tests/helpers/mod.rs | 20 + .../tests/{ => helpers}/repair-share.json | 0 .../helpers}/vectors-big-identifier.json | 0 .../{src/tests => tests/helpers}/vectors.json | 0 frost-ed25519/tests/integration_test.rs | 74 +++ frost-ed448/src/keys/repairable.rs | 37 ++ frost-ed448/src/tests.rs | 34 +- frost-ed448/src/tests/batch.rs | 21 + .../src/tests/coefficient_commitment.rs | 46 ++ frost-ed448/src/tests/deserialize.rs | 42 ++ frost-ed448/{ => src}/tests/proptests.rs | 3 +- frost-ed448/src/tests/vss_commitment.rs | 32 ++ frost-ed448/tests/frost.rs | 158 ------ frost-ed448/tests/{ => helpers}/elements.json | 0 .../tests/{ => helpers}/repair-share.json | 0 .../helpers}/vectors-big-identifier.json | 0 .../{src/tests => tests/helpers}/vectors.json | 0 frost-ed448/tests/integration_tests.rs | 50 ++ frost-p256/src/keys/repairable.rs | 37 ++ frost-p256/src/tests.rs | 32 +- frost-p256/src/tests/batch.rs | 17 + .../src/tests/coefficient_commitment.rs | 45 ++ frost-p256/src/tests/deserialize.rs | 37 ++ frost-p256/{ => src}/tests/proptests.rs | 2 +- frost-p256/src/tests/vss_commitment.rs | 32 ++ frost-p256/tests/frost.rs | 146 ------ frost-p256/tests/{ => helpers}/elements.json | 0 .../tests/{ => helpers}/repair-share.json | 0 .../helpers}/vectors-big-identifier.json | 0 .../{src/tests => tests/helpers}/vectors.json | 0 frost-p256/tests/integration_tests.rs | 48 ++ frost-ristretto255/src/keys/repairable.rs | 39 ++ frost-ristretto255/src/tests.rs | 34 +- frost-ristretto255/src/tests/batch.rs | 17 + .../src/tests/coefficient_commitment.rs | 46 ++ frost-ristretto255/src/tests/deserialize.rs | 11 + .../{ => src}/tests/proptests.rs | 2 +- .../tests/proptests}/bincode.rs.bck | 0 .../proptests}/proptests.proptest-regressions | 0 .../src/tests/vss_commitment.rs | 35 ++ frost-ristretto255/tests.rs | 2 + frost-ristretto255/tests/frost.rs | 125 ----- .../tests/{ => helpers}/elements.json | 0 .../tests/{ => helpers}/repair-share.json | 0 .../helpers}/vectors-big-identifier.json | 0 .../{src/tests => tests/helpers}/vectors.json | 0 frost-ristretto255/tests/integration_tests.rs | 50 ++ frost-secp256k1/src/keys/repairable.rs | 37 ++ frost-secp256k1/src/tests.rs | 34 +- frost-secp256k1/src/tests/batch.rs | 17 + .../src/tests/coefficient_commitment.rs | 46 ++ frost-secp256k1/src/tests/deserialize.rs | 37 ++ frost-secp256k1/{ => src}/tests/proptests.rs | 2 +- frost-secp256k1/src/tests/vss_commitment.rs | 32 ++ frost-secp256k1/tests/frost.rs | 149 ------ .../tests/{ => helpers}/elements.json | 0 .../tests/{ => helpers}/repair-share.json | 0 .../helpers}/vectors-big-identifier.json | 0 .../{src/tests => tests/helpers}/vectors.json | 0 frost-secp256k1/tests/integration_tests.rs | 50 ++ gencode/src/main.rs | 5 + 80 files changed, 1680 insertions(+), 1389 deletions(-) create mode 100644 frost-core/src/tests/ciphersuite_generic.rs create mode 100644 frost-core/src/tests/coefficient_commitment.rs create mode 100644 frost-core/src/tests/helpers.rs create mode 100644 frost-core/src/tests/vss_commitment.rs create mode 100644 frost-ed25519/src/tests/batch.rs create mode 100644 frost-ed25519/src/tests/coefficient_commitment.rs create mode 100644 frost-ed25519/src/tests/deserialize.rs rename frost-ed25519/{ => src}/tests/proptests.rs (97%) create mode 100644 frost-ed25519/src/tests/vss_commitment.rs create mode 100644 frost-ed25519/tests.rs delete mode 100644 frost-ed25519/tests/frost.rs rename frost-ed25519/tests/{ => helpers}/elements.json (100%) create mode 100644 frost-ed25519/tests/helpers/mod.rs rename frost-ed25519/tests/{ => helpers}/repair-share.json (100%) rename frost-ed25519/{src/tests => tests/helpers}/vectors-big-identifier.json (100%) rename frost-ed25519/{src/tests => tests/helpers}/vectors.json (100%) create mode 100644 frost-ed25519/tests/integration_test.rs create mode 100644 frost-ed448/src/tests/batch.rs create mode 100644 frost-ed448/src/tests/coefficient_commitment.rs create mode 100644 frost-ed448/src/tests/deserialize.rs rename frost-ed448/{ => src}/tests/proptests.rs (97%) create mode 100644 frost-ed448/src/tests/vss_commitment.rs delete mode 100644 frost-ed448/tests/frost.rs rename frost-ed448/tests/{ => helpers}/elements.json (100%) rename frost-ed448/tests/{ => helpers}/repair-share.json (100%) rename frost-ed448/{src/tests => tests/helpers}/vectors-big-identifier.json (100%) rename frost-ed448/{src/tests => tests/helpers}/vectors.json (100%) create mode 100644 frost-ed448/tests/integration_tests.rs create mode 100644 frost-p256/src/tests/batch.rs create mode 100644 frost-p256/src/tests/coefficient_commitment.rs create mode 100644 frost-p256/src/tests/deserialize.rs rename frost-p256/{ => src}/tests/proptests.rs (97%) create mode 100644 frost-p256/src/tests/vss_commitment.rs delete mode 100644 frost-p256/tests/frost.rs rename frost-p256/tests/{ => helpers}/elements.json (100%) rename frost-p256/tests/{ => helpers}/repair-share.json (100%) rename frost-p256/{src/tests => tests/helpers}/vectors-big-identifier.json (100%) rename frost-p256/{src/tests => tests/helpers}/vectors.json (100%) create mode 100644 frost-p256/tests/integration_tests.rs create mode 100644 frost-ristretto255/src/tests/batch.rs create mode 100644 frost-ristretto255/src/tests/coefficient_commitment.rs create mode 100644 frost-ristretto255/src/tests/deserialize.rs rename frost-ristretto255/{ => src}/tests/proptests.rs (97%) rename frost-ristretto255/{tests => src/tests/proptests}/bincode.rs.bck (100%) rename frost-ristretto255/{tests => src/tests/proptests}/proptests.proptest-regressions (100%) create mode 100644 frost-ristretto255/src/tests/vss_commitment.rs create mode 100644 frost-ristretto255/tests.rs delete mode 100644 frost-ristretto255/tests/frost.rs rename frost-ristretto255/tests/{ => helpers}/elements.json (100%) rename frost-ristretto255/tests/{ => helpers}/repair-share.json (100%) rename frost-ristretto255/{src/tests => tests/helpers}/vectors-big-identifier.json (100%) rename frost-ristretto255/{src/tests => tests/helpers}/vectors.json (100%) create mode 100644 frost-ristretto255/tests/integration_tests.rs create mode 100644 frost-secp256k1/src/tests/batch.rs create mode 100644 frost-secp256k1/src/tests/coefficient_commitment.rs create mode 100644 frost-secp256k1/src/tests/deserialize.rs rename frost-secp256k1/{ => src}/tests/proptests.rs (97%) create mode 100644 frost-secp256k1/src/tests/vss_commitment.rs delete mode 100644 frost-secp256k1/tests/frost.rs rename frost-secp256k1/tests/{ => helpers}/elements.json (100%) rename frost-secp256k1/tests/{ => helpers}/repair-share.json (100%) rename frost-secp256k1/{src/tests => tests/helpers}/vectors-big-identifier.json (100%) rename frost-secp256k1/{src/tests => tests/helpers}/vectors.json (100%) create mode 100644 frost-secp256k1/tests/integration_tests.rs diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index c3ff432..f1a44de 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -38,10 +38,10 @@ jobs: run: cargo install cargo-llvm-cov - name: Run tests - run: cargo llvm-cov --lcov --no-report --ignore-filename-regex 'tests.rs|benches.rs|gencode' + run: cargo llvm-cov --lcov --no-report --ignore-filename-regex '.*(tests).*|benches.rs|gencode|helpers.rs' - name: Generate coverage report - run: cargo llvm-cov report --lcov --ignore-filename-regex 'tests.rs|benches.rs|gencode' --output-path lcov.info + run: cargo llvm-cov report --lcov --ignore-filename-regex '.*(tests).*|benches.rs|gencode|helpers.rs' --output-path lcov.info - name: Upload coverage report to Codecov uses: codecov/codecov-action@v3.1.4 diff --git a/README.md b/README.md index 1124075..fa2be59 100644 --- a/README.md +++ b/README.md @@ -43,4 +43,4 @@ dependency. Test coverage checks are performed in the pipeline. This is cofigured here: `.github/workflows/coverage.yaml` To run these locally: 1. Install coverage tool by running `cargo install cargo-llvm-cov` -2. Run `cargo llvm-cov --ignore-filename-regex 'tests.rs|benches.rs|gencode'` (you may be asked if you want to install `llvm-tools-preview`, if so type `Y`) +2. Run `cargo llvm-cov --ignore-filename-regex '.*(tests).*|benches.rs|gencode|helpers.rs` (you may be asked if you want to install `llvm-tools-preview`, if so type `Y`) diff --git a/codecov.yml b/codecov.yml index 419999f..c369603 100644 --- a/codecov.yml +++ b/codecov.yml @@ -27,3 +27,6 @@ parsers: github_checks: annotations: false + +codecov: + branch: main diff --git a/frost-core/src/tests.rs b/frost-core/src/tests.rs index 11888c5..5e9fa28 100644 --- a/frost-core/src/tests.rs +++ b/frost-core/src/tests.rs @@ -1,492 +1,10 @@ -//! Ciphersuite-generic test functions. -use std::{collections::HashMap, convert::TryFrom}; - -use crate::{ - frost::{ - self, - keys::{CoefficientCommitment, VerifiableSecretSharingCommitment}, - }, - Error, Field, Group, Signature, VerifyingKey, -}; -use debugless_unwrap::DebuglessUnwrap; -use debugless_unwrap::DebuglessUnwrapErr; -use rand_core::{CryptoRng, RngCore}; -use serde_json::Value; - -use crate::Ciphersuite; +//! Test modules pub mod batch; +pub mod ciphersuite_generic; +pub mod coefficient_commitment; +pub mod helpers; pub mod proptests; pub mod repairable; pub mod vectors; - -/// Test share generation with a Ciphersuite -pub fn check_share_generation(mut rng: R) { - let secret = crate::SigningKey::::new(&mut rng); - - let max_signers = 5; - let min_signers = 3; - - let coefficients = - frost::keys::generate_coefficients::(min_signers as usize - 1, &mut rng); - - let secret_shares = - frost::keys::generate_secret_shares(&secret, max_signers, min_signers, coefficients) - .unwrap(); - - for secret_share in secret_shares.iter() { - assert!(secret_share.verify().is_ok()); - } - - assert_eq!( - frost::keys::reconstruct::(&secret_shares) - .unwrap() - .to_bytes() - .as_ref(), - secret.to_bytes().as_ref() - ); - - // Test error cases - - assert_eq!( - frost::keys::reconstruct::(&[]).debugless_unwrap_err(), - Error::IncorrectNumberOfShares - ); - - let mut secret_shares = secret_shares; - secret_shares[0] = secret_shares[1].clone(); - - assert_eq!( - frost::keys::reconstruct::(&secret_shares).debugless_unwrap_err(), - Error::DuplicatedShares - ); -} - -/// Test FROST signing with trusted dealer with a Ciphersuite. -pub fn check_sign_with_dealer( - mut rng: R, -) -> (Vec, Signature, VerifyingKey) { - //////////////////////////////////////////////////////////////////////////// - // Key generation - //////////////////////////////////////////////////////////////////////////// - - let max_signers = 5; - let min_signers = 3; - let (shares, pubkeys) = - frost::keys::generate_with_dealer(max_signers, min_signers, &mut rng).unwrap(); - - // Verifies the secret shares from the dealer - let mut key_packages: HashMap, frost::keys::KeyPackage> = - HashMap::new(); - - for (k, v) in shares { - let key_package = frost::keys::KeyPackage::try_from(v).unwrap(); - key_packages.insert(k, key_package); - } - - check_sign(min_signers, key_packages, rng, pubkeys) -} - -fn check_sign( - min_signers: u16, - key_packages: HashMap, frost::keys::KeyPackage>, - mut rng: R, - pubkeys: frost::keys::PublicKeyPackage, -) -> (Vec, Signature, VerifyingKey) { - let mut nonces: HashMap, frost::round1::SigningNonces> = HashMap::new(); - let mut commitments: HashMap, frost::round1::SigningCommitments> = - HashMap::new(); - - //////////////////////////////////////////////////////////////////////////// - // Round 1: generating nonces and signing commitments for each participant - //////////////////////////////////////////////////////////////////////////// - - for participant_index in 1..(min_signers + 1) { - let participant_identifier = participant_index.try_into().expect("should be nonzero"); - // Generate one (1) nonce and one SigningCommitments instance for each - // participant, up to _min_signers_. - let (nonce, commitment) = frost::round1::commit( - participant_identifier, - key_packages - .get(&participant_identifier) - .unwrap() - .secret_share(), - &mut rng, - ); - nonces.insert(participant_identifier, nonce); - commitments.insert(participant_identifier, commitment); - } - - // This is what the signature aggregator / coordinator needs to do: - // - decide what message to sign - // - take one (unused) commitment per signing participant - let mut signature_shares = Vec::new(); - let message = "message to sign".as_bytes(); - let comms = commitments.clone().into_values().collect(); - let signing_package = frost::SigningPackage::new(comms, message.to_vec()); - - //////////////////////////////////////////////////////////////////////////// - // Round 2: each participant generates their signature share - //////////////////////////////////////////////////////////////////////////// - - for participant_identifier in nonces.keys() { - let key_package = key_packages.get(participant_identifier).unwrap(); - - let nonces_to_use = &nonces.get(participant_identifier).unwrap(); - - // Each participant generates their signature share. - let signature_share = - frost::round2::sign(&signing_package, nonces_to_use, key_package).unwrap(); - signature_shares.push(signature_share); - } - - //////////////////////////////////////////////////////////////////////////// - // Aggregation: collects the signing shares from all participants, - // generates the final signature. - //////////////////////////////////////////////////////////////////////////// - - // Aggregate (also verifies the signature shares) - let group_signature_res = frost::aggregate(&signing_package, &signature_shares[..], &pubkeys); - - assert!(group_signature_res.is_ok()); - - let group_signature = group_signature_res.unwrap(); - - // Check that the threshold signature can be verified by the group public - // key (the verification key). - assert!(pubkeys - .group_public - .verify(message, &group_signature) - .is_ok()); - - // Check that the threshold signature can be verified by the group public - // key (the verification key) from KeyPackage.group_public - for (participant_identifier, _) in nonces.clone() { - let key_package = key_packages.get(&participant_identifier).unwrap(); - - assert!(key_package - .group_public - .verify(message, &group_signature) - .is_ok()); - } - - (message.to_owned(), group_signature, pubkeys.group_public) -} - -/// Test FROST signing with trusted dealer with a Ciphersuite. -pub fn check_sign_with_dkg( - mut rng: R, -) -> (Vec, Signature, VerifyingKey) -where - C::Group: std::cmp::PartialEq, -{ - //////////////////////////////////////////////////////////////////////////// - // Key generation, Round 1 - //////////////////////////////////////////////////////////////////////////// - - let max_signers = 5; - let min_signers = 3; - - // Keep track of each participant's round 1 secret package. - // In practice each participant will keep its copy; no one - // will have all the participant's packages. - let mut round1_secret_packages: HashMap< - frost::Identifier, - frost::keys::dkg::round1::SecretPackage, - > = HashMap::new(); - - // Keep track of all round 1 packages sent to the given participant. - // This is used to simulate the broadcast; in practice the packages - // will be sent through some communication channel. - let mut received_round1_packages: HashMap< - frost::Identifier, - Vec>, - > = HashMap::new(); - - // For each participant, perform the first part of the DKG protocol. - // In practice, each participant will perform this on their own environments. - for participant_index in 1..=max_signers { - let participant_identifier = participant_index.try_into().expect("should be nonzero"); - let (secret_package, round1_package) = - frost::keys::dkg::part1(participant_identifier, max_signers, min_signers, &mut rng) - .unwrap(); - - // Store the participant's secret package for later use. - // In practice each participant will store it in their own environment. - round1_secret_packages.insert(participant_identifier, secret_package); - - // "Send" the round 1 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be - // sent through some communication channel. - for receiver_participant_index in 1..=max_signers { - if receiver_participant_index == participant_index { - continue; - } - let receiver_participant_identifier = receiver_participant_index - .try_into() - .expect("should be nonzero"); - received_round1_packages - .entry(receiver_participant_identifier) - .or_insert_with(Vec::new) - .push(round1_package.clone()); - } - } - - //////////////////////////////////////////////////////////////////////////// - // Key generation, Round 2 - //////////////////////////////////////////////////////////////////////////// - - // Keep track of each participant's round 2 secret package. - // In practice each participant will keep its copy; no one - // will have all the participant's packages. - let mut round2_secret_packages = HashMap::new(); - - // Keep track of all round 2 packages sent to the given participant. - // This is used to simulate the broadcast; in practice the packages - // will be sent through some communication channel. - let mut received_round2_packages = HashMap::new(); - - // For each participant, perform the second part of the DKG protocol. - // In practice, each participant will perform this on their own environments. - for participant_index in 1..=max_signers { - let participant_identifier = participant_index.try_into().expect("should be nonzero"); - let (round2_secret_package, round2_packages) = frost::keys::dkg::part2( - round1_secret_packages - .remove(&participant_identifier) - .unwrap(), - received_round1_packages - .get(&participant_identifier) - .unwrap(), - ) - .expect("should work"); - - // Store the participant's secret package for later use. - // In practice each participant will store it in their own environment. - round2_secret_packages.insert(participant_identifier, round2_secret_package); - - // "Send" the round 2 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be - // sent through some communication channel. - // Note that, in contrast to the previous part, here each other participant - // gets its own specific package. - for round2_package in round2_packages { - received_round2_packages - .entry(round2_package.receiver_identifier) - .or_insert_with(Vec::new) - .push(round2_package); - } - } - - //////////////////////////////////////////////////////////////////////////// - // Key generation, final computation - //////////////////////////////////////////////////////////////////////////// - - // Keep track of each participant's long-lived key package. - // In practice each participant will keep its copy; no one - // will have all the participant's packages. - let mut key_packages = HashMap::new(); - - // Map of the verifying key of each participant. - // Used by the signing test that follows. - let mut verifying_keys = HashMap::new(); - // The group public key, used by the signing test that follows. - let mut group_public = None; - // For each participant, store the set of verifying keys they have computed. - // This is used to check if the set is correct (the same) for all participants. - // In practice, if there is a Coordinator, only they need to store the set. - // If there is not, then all candidates must store their own sets. - // The verifying keys are used to verify the signature shares produced - // for each signature before being aggregated. - let mut pubkey_packages_by_participant = HashMap::new(); - - // For each participant, perform the third part of the DKG protocol. - // In practice, each participant will perform this on their own environments. - for participant_index in 1..=max_signers { - let participant_identifier = participant_index.try_into().expect("should be nonzero"); - let (key_package, pubkey_package_for_participant) = frost::keys::dkg::part3( - &round2_secret_packages[&participant_identifier], - &received_round1_packages[&participant_identifier], - &received_round2_packages[&participant_identifier], - ) - .unwrap(); - verifying_keys.insert(participant_identifier, key_package.public); - // Test if all group_public are equal - if let Some(previous_group_public) = group_public { - assert_eq!(previous_group_public, key_package.group_public) - } - group_public = Some(key_package.group_public); - key_packages.insert(participant_identifier, key_package); - pubkey_packages_by_participant - .insert(participant_identifier, pubkey_package_for_participant); - } - - // Test if the set of verifying keys is correct for all participants. - for verifying_keys_for_participant in pubkey_packages_by_participant.values() { - assert!(verifying_keys_for_participant.signer_pubkeys == verifying_keys); - } - - let pubkeys = frost::keys::PublicKeyPackage { - signer_pubkeys: verifying_keys, - group_public: group_public.unwrap(), - }; - - // Proceed with the signing test. - check_sign(min_signers, key_packages, rng, pubkeys) -} - -fn generate_element( - rng: &mut R, -) -> <::Group as Group>::Element { - let scalar = <::Field>::random(rng); - ::generator() * scalar -} - -/// Test retrieving Element from CoefficientCommitment -pub fn check_serialization_of_coefficient_commitment( - mut rng: R, -) { - let element = generate_element::(&mut rng); - - let expected = ::serialize(&element); - - let data = frost::keys::CoefficientCommitment::(element).serialize(); - - assert!(expected.as_ref() == data.as_ref()); -} - -/// Test create a CoefficientCommitment. -pub fn check_create_coefficient_commitment(mut rng: R) { - let element = generate_element::(&mut rng); - - let expected = CoefficientCommitment::(element); - - let serialized_element = ::serialize(&element); - - let coeff_commitment = - frost::keys::CoefficientCommitment::::deserialize(serialized_element).unwrap(); - - assert!(expected == coeff_commitment); -} - -/// Test error handling for creation of a coefficient commitment -pub fn check_create_coefficient_commitment_error( - commitment_helper_functions: &Value, -) { - let values = &commitment_helper_functions["elements"]; - let serialized: ::Serialization = - ::Serialization::try_from( - hex::decode(values["invalid_element"].as_str().unwrap()).unwrap(), - ) - .debugless_unwrap(); - - let coeff_commitment = frost::keys::CoefficientCommitment::::deserialize(serialized); - - assert!(coeff_commitment.is_err()); -} - -/// Test retrieve Element from CoefficientCommitment -pub fn check_get_value_of_coefficient_commitment( - mut rng: R, -) { - let element = generate_element::(&mut rng); - - let coeff_commitment = frost::keys::CoefficientCommitment::(element); - let value = coeff_commitment.value(); - - assert!(value == element) -} - -/// Test serialize VerifiableSecretSharingCommitment -pub fn check_serialize_vss_commitment(mut rng: R) { - // Generate test CoefficientCommitments - - // --- - let input_1 = generate_element::(&mut rng); - let input_2 = generate_element::(&mut rng); - let input_3 = generate_element::(&mut rng); - - let coeff_comms = vec![ - CoefficientCommitment::(input_1), - CoefficientCommitment(input_2), - CoefficientCommitment(input_3), - ]; - - // --- - - let expected = vec![ - ::serialize(&input_1), - ::serialize(&input_2), - ::serialize(&input_3), - ]; - - let vss_commitment = VerifiableSecretSharingCommitment(coeff_comms).serialize(); - - assert!(expected.len() == vss_commitment.len()); - assert!(expected - .iter() - .zip(vss_commitment.iter()) - .all(|(e, c)| e.as_ref() == c.as_ref())); -} - -/// Test deserialize VerifiableSecretSharingCommitment -pub fn check_deserialize_vss_commitment(mut rng: R) { - // Generate test CoefficientCommitments - - // --- - let input_1 = generate_element::(&mut rng); - let input_2 = generate_element::(&mut rng); - let input_3 = generate_element::(&mut rng); - - let coeff_comms = vec![ - CoefficientCommitment::(input_1), - CoefficientCommitment(input_2), - CoefficientCommitment(input_3), - ]; - // --- - - let expected = VerifiableSecretSharingCommitment(coeff_comms); - - let data = vec![ - ::serialize(&input_1), - ::serialize(&input_2), - ::serialize(&input_3), - ]; - - let vss_value = VerifiableSecretSharingCommitment::deserialize(data); - - assert!(vss_value.is_ok()); - assert!(expected == vss_value.unwrap()); -} - -/// Test deserialize VerifiableSecretSharingCommitment error -pub fn check_deserialize_vss_commitment_error( - mut rng: R, - commitment_helper_functions: &Value, -) { - // Generate test CoefficientCommitments - - // --- - let values = &commitment_helper_functions["elements"]; - - let input_1 = generate_element::(&mut rng); - let input_2 = generate_element::(&mut rng); - let input_3 = generate_element::(&mut rng); - - let serialized: ::Serialization = - ::Serialization::try_from( - hex::decode(values["invalid_element"].as_str().unwrap()).unwrap(), - ) - .debugless_unwrap(); - // --- - - let data = vec![ - ::serialize(&input_1), - ::serialize(&input_2), - ::serialize(&input_3), - serialized, - ]; - - let vss_value = VerifiableSecretSharingCommitment::::deserialize(data); - - assert!(vss_value.is_err()); -} +pub mod vss_commitment; diff --git a/frost-core/src/tests/ciphersuite_generic.rs b/frost-core/src/tests/ciphersuite_generic.rs new file mode 100644 index 0000000..114d4d9 --- /dev/null +++ b/frost-core/src/tests/ciphersuite_generic.rs @@ -0,0 +1,325 @@ +//! Ciphersuite-generic test functions. +use std::{collections::HashMap, convert::TryFrom}; + +use crate::{ + frost::{self}, + Error, Signature, VerifyingKey, +}; +use debugless_unwrap::DebuglessUnwrapErr; +use rand_core::{CryptoRng, RngCore}; + +use crate::Ciphersuite; + +/// Test share generation with a Ciphersuite +pub fn check_share_generation(mut rng: R) { + let secret = crate::SigningKey::::new(&mut rng); + + let max_signers = 5; + let min_signers = 3; + + let coefficients = + frost::keys::generate_coefficients::(min_signers as usize - 1, &mut rng); + + let secret_shares = + frost::keys::generate_secret_shares(&secret, max_signers, min_signers, coefficients) + .unwrap(); + + for secret_share in secret_shares.iter() { + assert!(secret_share.verify().is_ok()); + } + + assert_eq!( + frost::keys::reconstruct::(&secret_shares) + .unwrap() + .to_bytes() + .as_ref(), + secret.to_bytes().as_ref() + ); + + // Test error cases + + assert_eq!( + frost::keys::reconstruct::(&[]).debugless_unwrap_err(), + Error::IncorrectNumberOfShares + ); + + let mut secret_shares = secret_shares; + secret_shares[0] = secret_shares[1].clone(); + + assert_eq!( + frost::keys::reconstruct::(&secret_shares).debugless_unwrap_err(), + Error::DuplicatedShares + ); +} + +/// Test FROST signing with trusted dealer with a Ciphersuite. +pub fn check_sign_with_dealer( + mut rng: R, +) -> (Vec, Signature, VerifyingKey) { + //////////////////////////////////////////////////////////////////////////// + // Key generation + //////////////////////////////////////////////////////////////////////////// + + let max_signers = 5; + let min_signers = 3; + let (shares, pubkeys) = + frost::keys::generate_with_dealer(max_signers, min_signers, &mut rng).unwrap(); + + // Verifies the secret shares from the dealer + let mut key_packages: HashMap, frost::keys::KeyPackage> = + HashMap::new(); + + for (k, v) in shares { + let key_package = frost::keys::KeyPackage::try_from(v).unwrap(); + key_packages.insert(k, key_package); + } + + check_sign(min_signers, key_packages, rng, pubkeys) +} + +fn check_sign( + min_signers: u16, + key_packages: HashMap, frost::keys::KeyPackage>, + mut rng: R, + pubkeys: frost::keys::PublicKeyPackage, +) -> (Vec, Signature, VerifyingKey) { + let mut nonces: HashMap, frost::round1::SigningNonces> = HashMap::new(); + let mut commitments: HashMap, frost::round1::SigningCommitments> = + HashMap::new(); + + //////////////////////////////////////////////////////////////////////////// + // Round 1: generating nonces and signing commitments for each participant + //////////////////////////////////////////////////////////////////////////// + + for participant_index in 1..(min_signers + 1) { + let participant_identifier = participant_index.try_into().expect("should be nonzero"); + // Generate one (1) nonce and one SigningCommitments instance for each + // participant, up to _min_signers_. + let (nonce, commitment) = frost::round1::commit( + participant_identifier, + key_packages + .get(&participant_identifier) + .unwrap() + .secret_share(), + &mut rng, + ); + nonces.insert(participant_identifier, nonce); + commitments.insert(participant_identifier, commitment); + } + + // This is what the signature aggregator / coordinator needs to do: + // - decide what message to sign + // - take one (unused) commitment per signing participant + let mut signature_shares = Vec::new(); + let message = "message to sign".as_bytes(); + let comms = commitments.clone().into_values().collect(); + let signing_package = frost::SigningPackage::new(comms, message.to_vec()); + + //////////////////////////////////////////////////////////////////////////// + // Round 2: each participant generates their signature share + //////////////////////////////////////////////////////////////////////////// + + for participant_identifier in nonces.keys() { + let key_package = key_packages.get(participant_identifier).unwrap(); + + let nonces_to_use = &nonces.get(participant_identifier).unwrap(); + + // Each participant generates their signature share. + let signature_share = + frost::round2::sign(&signing_package, nonces_to_use, key_package).unwrap(); + signature_shares.push(signature_share); + } + + //////////////////////////////////////////////////////////////////////////// + // Aggregation: collects the signing shares from all participants, + // generates the final signature. + //////////////////////////////////////////////////////////////////////////// + + // Aggregate (also verifies the signature shares) + let group_signature_res = frost::aggregate(&signing_package, &signature_shares[..], &pubkeys); + + assert!(group_signature_res.is_ok()); + + let group_signature = group_signature_res.unwrap(); + + // Check that the threshold signature can be verified by the group public + // key (the verification key). + assert!(pubkeys + .group_public + .verify(message, &group_signature) + .is_ok()); + + // Check that the threshold signature can be verified by the group public + // key (the verification key) from KeyPackage.group_public + for (participant_identifier, _) in nonces.clone() { + let key_package = key_packages.get(&participant_identifier).unwrap(); + + assert!(key_package + .group_public + .verify(message, &group_signature) + .is_ok()); + } + + (message.to_owned(), group_signature, pubkeys.group_public) +} + +/// Test FROST signing with trusted dealer with a Ciphersuite. +pub fn check_sign_with_dkg( + mut rng: R, +) -> (Vec, Signature, VerifyingKey) +where + C::Group: std::cmp::PartialEq, +{ + //////////////////////////////////////////////////////////////////////////// + // Key generation, Round 1 + //////////////////////////////////////////////////////////////////////////// + + let max_signers = 5; + let min_signers = 3; + + // Keep track of each participant's round 1 secret package. + // In practice each participant will keep its copy; no one + // will have all the participant's packages. + let mut round1_secret_packages: HashMap< + frost::Identifier, + frost::keys::dkg::round1::SecretPackage, + > = HashMap::new(); + + // Keep track of all round 1 packages sent to the given participant. + // This is used to simulate the broadcast; in practice the packages + // will be sent through some communication channel. + let mut received_round1_packages: HashMap< + frost::Identifier, + Vec>, + > = HashMap::new(); + + // For each participant, perform the first part of the DKG protocol. + // In practice, each participant will perform this on their own environments. + for participant_index in 1..=max_signers { + let participant_identifier = participant_index.try_into().expect("should be nonzero"); + let (secret_package, round1_package) = + frost::keys::dkg::part1(participant_identifier, max_signers, min_signers, &mut rng) + .unwrap(); + + // Store the participant's secret package for later use. + // In practice each participant will store it in their own environment. + round1_secret_packages.insert(participant_identifier, secret_package); + + // "Send" the round 1 package to all other participants. In this + // test this is simulated using a HashMap; in practice this will be + // sent through some communication channel. + for receiver_participant_index in 1..=max_signers { + if receiver_participant_index == participant_index { + continue; + } + let receiver_participant_identifier = receiver_participant_index + .try_into() + .expect("should be nonzero"); + received_round1_packages + .entry(receiver_participant_identifier) + .or_insert_with(Vec::new) + .push(round1_package.clone()); + } + } + + //////////////////////////////////////////////////////////////////////////// + // Key generation, Round 2 + //////////////////////////////////////////////////////////////////////////// + + // Keep track of each participant's round 2 secret package. + // In practice each participant will keep its copy; no one + // will have all the participant's packages. + let mut round2_secret_packages = HashMap::new(); + + // Keep track of all round 2 packages sent to the given participant. + // This is used to simulate the broadcast; in practice the packages + // will be sent through some communication channel. + let mut received_round2_packages = HashMap::new(); + + // For each participant, perform the second part of the DKG protocol. + // In practice, each participant will perform this on their own environments. + for participant_index in 1..=max_signers { + let participant_identifier = participant_index.try_into().expect("should be nonzero"); + let (round2_secret_package, round2_packages) = frost::keys::dkg::part2( + round1_secret_packages + .remove(&participant_identifier) + .unwrap(), + received_round1_packages + .get(&participant_identifier) + .unwrap(), + ) + .expect("should work"); + + // Store the participant's secret package for later use. + // In practice each participant will store it in their own environment. + round2_secret_packages.insert(participant_identifier, round2_secret_package); + + // "Send" the round 2 package to all other participants. In this + // test this is simulated using a HashMap; in practice this will be + // sent through some communication channel. + // Note that, in contrast to the previous part, here each other participant + // gets its own specific package. + for round2_package in round2_packages { + received_round2_packages + .entry(round2_package.receiver_identifier) + .or_insert_with(Vec::new) + .push(round2_package); + } + } + + //////////////////////////////////////////////////////////////////////////// + // Key generation, final computation + //////////////////////////////////////////////////////////////////////////// + + // Keep track of each participant's long-lived key package. + // In practice each participant will keep its copy; no one + // will have all the participant's packages. + let mut key_packages = HashMap::new(); + + // Map of the verifying key of each participant. + // Used by the signing test that follows. + let mut verifying_keys = HashMap::new(); + // The group public key, used by the signing test that follows. + let mut group_public = None; + // For each participant, store the set of verifying keys they have computed. + // This is used to check if the set is correct (the same) for all participants. + // In practice, if there is a Coordinator, only they need to store the set. + // If there is not, then all candidates must store their own sets. + // The verifying keys are used to verify the signature shares produced + // for each signature before being aggregated. + let mut pubkey_packages_by_participant = HashMap::new(); + + // For each participant, perform the third part of the DKG protocol. + // In practice, each participant will perform this on their own environments. + for participant_index in 1..=max_signers { + let participant_identifier = participant_index.try_into().expect("should be nonzero"); + let (key_package, pubkey_package_for_participant) = frost::keys::dkg::part3( + &round2_secret_packages[&participant_identifier], + &received_round1_packages[&participant_identifier], + &received_round2_packages[&participant_identifier], + ) + .unwrap(); + verifying_keys.insert(participant_identifier, key_package.public); + // Test if all group_public are equal + if let Some(previous_group_public) = group_public { + assert_eq!(previous_group_public, key_package.group_public) + } + group_public = Some(key_package.group_public); + key_packages.insert(participant_identifier, key_package); + pubkey_packages_by_participant + .insert(participant_identifier, pubkey_package_for_participant); + } + + // Test if the set of verifying keys is correct for all participants. + for verifying_keys_for_participant in pubkey_packages_by_participant.values() { + assert!(verifying_keys_for_participant.signer_pubkeys == verifying_keys); + } + + let pubkeys = frost::keys::PublicKeyPackage { + signer_pubkeys: verifying_keys, + group_public: group_public.unwrap(), + }; + + // Proceed with the signing test. + check_sign(min_signers, key_packages, rng, pubkeys) +} diff --git a/frost-core/src/tests/coefficient_commitment.rs b/frost-core/src/tests/coefficient_commitment.rs new file mode 100644 index 0000000..03de69f --- /dev/null +++ b/frost-core/src/tests/coefficient_commitment.rs @@ -0,0 +1,69 @@ +//! CoefficientCommitment functions + +use std::convert::TryFrom; + +use crate::{ + frost::{self, keys::CoefficientCommitment}, + tests::helpers::generate_element, + Group, +}; +use debugless_unwrap::DebuglessUnwrap; +use rand_core::{CryptoRng, RngCore}; +use serde_json::Value; + +use crate::Ciphersuite; + +/// Test retrieving Element from CoefficientCommitment +pub fn check_serialization_of_coefficient_commitment( + mut rng: R, +) { + let element = generate_element::(&mut rng); + + let expected = ::serialize(&element); + + let data = frost::keys::CoefficientCommitment::(element).serialize(); + + assert!(expected.as_ref() == data.as_ref()); +} + +/// Test create a CoefficientCommitment. +pub fn check_create_coefficient_commitment(mut rng: R) { + let element = generate_element::(&mut rng); + + let expected = CoefficientCommitment::(element); + + let serialized_element = ::serialize(&element); + + let coeff_commitment = + frost::keys::CoefficientCommitment::::deserialize(serialized_element).unwrap(); + + assert!(expected == coeff_commitment); +} + +/// Test error handling for creation of a coefficient commitment +pub fn check_create_coefficient_commitment_error( + commitment_helpers: &Value, +) { + let values = &commitment_helpers["elements"]; + let serialized: ::Serialization = + ::Serialization::try_from( + hex::decode(values["invalid_element"].as_str().unwrap()).unwrap(), + ) + .debugless_unwrap(); + + let coeff_commitment = frost::keys::CoefficientCommitment::::deserialize(serialized); + + assert!(coeff_commitment.is_err()); +} + +/// Test retrieve Element from CoefficientCommitment +pub fn check_get_value_of_coefficient_commitment( + mut rng: R, +) { + let element = generate_element::(&mut rng); + + let coeff_commitment = frost::keys::CoefficientCommitment::(element); + let value = coeff_commitment.value(); + + assert!(value == element) +} diff --git a/frost-core/src/tests/helpers.rs b/frost-core/src/tests/helpers.rs new file mode 100644 index 0000000..b441e72 --- /dev/null +++ b/frost-core/src/tests/helpers.rs @@ -0,0 +1,12 @@ +//! Helper function for testing + +use crate::{Ciphersuite, Field, Group}; +use rand_core::{CryptoRng, RngCore}; + +/// Helper function for randomly generating an element +pub fn generate_element( + rng: &mut R, +) -> <::Group as Group>::Element { + let scalar = <::Field>::random(rng); + ::generator() * scalar +} diff --git a/frost-core/src/tests/repairable.rs b/frost-core/src/tests/repairable.rs index c9e6f86..0aecbb6 100644 --- a/frost-core/src/tests/repairable.rs +++ b/frost-core/src/tests/repairable.rs @@ -134,8 +134,8 @@ pub fn check_repair_share_step_1(mut rng } /// Test repair_share_step_2 -pub fn check_repair_share_step_2(repair_share_helper_functions: &Value) { - let values = &repair_share_helper_functions["scalar_generation"]; +pub fn check_repair_share_step_2(repair_share_helpers: &Value) { + let values = &repair_share_helpers["scalar_generation"]; let value_1 = generate_scalar_from_byte_string::(values["random_scalar_1"].as_str().unwrap()); @@ -155,7 +155,7 @@ pub fn check_repair_share_step_2(repair_share_helper_functions: /// Test repair_share pub fn check_repair_share_step_3( mut rng: R, - repair_share_helper_functions: &Value, + repair_share_helpers: &Value, ) { // Generate shares let max_signers = 5; @@ -163,7 +163,7 @@ pub fn check_repair_share_step_3( let (shares, _pubkeys): (HashMap, SecretShare>, PublicKeyPackage) = frost::keys::generate_with_dealer(max_signers, min_signers, &mut rng).unwrap(); - let sigmas: &Value = &repair_share_helper_functions["sigma_generation"]; + let sigmas: &Value = &repair_share_helpers["sigma_generation"]; let sigma_1 = generate_scalar_from_byte_string::(sigmas["sigma_1"].as_str().unwrap()); let sigma_2 = generate_scalar_from_byte_string::(sigmas["sigma_2"].as_str().unwrap()); diff --git a/frost-core/src/tests/vss_commitment.rs b/frost-core/src/tests/vss_commitment.rs new file mode 100644 index 0000000..e37efe1 --- /dev/null +++ b/frost-core/src/tests/vss_commitment.rs @@ -0,0 +1,109 @@ +//! VerifiableSecretSharingCommitment functions + +use std::convert::TryFrom; + +use crate::{ + frost::keys::{CoefficientCommitment, VerifiableSecretSharingCommitment}, + tests::helpers::generate_element, + Group, +}; +use debugless_unwrap::DebuglessUnwrap; +use rand_core::{CryptoRng, RngCore}; +use serde_json::Value; + +use crate::Ciphersuite; + +/// Test serialize VerifiableSecretSharingCommitment +pub fn check_serialize_vss_commitment(mut rng: R) { + // Generate test CoefficientCommitments + + // --- + let input_1 = generate_element::(&mut rng); + let input_2 = generate_element::(&mut rng); + let input_3 = generate_element::(&mut rng); + + let coeff_comms = vec![ + CoefficientCommitment::(input_1), + CoefficientCommitment(input_2), + CoefficientCommitment(input_3), + ]; + + // --- + + let expected = vec![ + ::serialize(&input_1), + ::serialize(&input_2), + ::serialize(&input_3), + ]; + + let vss_commitment = VerifiableSecretSharingCommitment(coeff_comms).serialize(); + + assert!(expected.len() == vss_commitment.len()); + assert!(expected + .iter() + .zip(vss_commitment.iter()) + .all(|(e, c)| e.as_ref() == c.as_ref())); +} + +/// Test deserialize VerifiableSecretSharingCommitment +pub fn check_deserialize_vss_commitment(mut rng: R) { + // Generate test CoefficientCommitments + + // --- + let input_1 = generate_element::(&mut rng); + let input_2 = generate_element::(&mut rng); + let input_3 = generate_element::(&mut rng); + + let coeff_comms = vec![ + CoefficientCommitment::(input_1), + CoefficientCommitment(input_2), + CoefficientCommitment(input_3), + ]; + // --- + + let expected = VerifiableSecretSharingCommitment(coeff_comms); + + let data = vec![ + ::serialize(&input_1), + ::serialize(&input_2), + ::serialize(&input_3), + ]; + + let vss_value = VerifiableSecretSharingCommitment::deserialize(data); + + assert!(vss_value.is_ok()); + assert!(expected == vss_value.unwrap()); +} + +/// Test deserialize VerifiableSecretSharingCommitment error +pub fn check_deserialize_vss_commitment_error( + mut rng: R, + commitment_helpers: &Value, +) { + // Generate test CoefficientCommitments + + // --- + let values = &commitment_helpers["elements"]; + + let input_1 = generate_element::(&mut rng); + let input_2 = generate_element::(&mut rng); + let input_3 = generate_element::(&mut rng); + + let serialized: ::Serialization = + ::Serialization::try_from( + hex::decode(values["invalid_element"].as_str().unwrap()).unwrap(), + ) + .debugless_unwrap(); + // --- + + let data = vec![ + ::serialize(&input_1), + ::serialize(&input_2), + ::serialize(&input_3), + serialized, + ]; + + let vss_value = VerifiableSecretSharingCommitment::::deserialize(data); + + assert!(vss_value.is_err()); +} diff --git a/frost-ed25519/src/keys/repairable.rs b/frost-ed25519/src/keys/repairable.rs index 7d7f15b..edac670 100644 --- a/frost-ed25519/src/keys/repairable.rs +++ b/frost-ed25519/src/keys/repairable.rs @@ -53,3 +53,40 @@ pub fn repair_share_step_3( ) -> SecretShare { frost::keys::repairable::repair_share_step_3(sigmas, identifier, commitment) } + +#[cfg(test)] +mod tests { + + use lazy_static::lazy_static; + use rand::thread_rng; + use serde_json::Value; + + use crate::Ed25519Sha512; + + lazy_static! { + pub static ref REPAIR_SHARE: Value = + serde_json::from_str(include_str!("../../tests/helpers/repair-share.json").trim()) + .unwrap(); + } + + #[test] + fn check_repair_share_step_1() { + let rng = thread_rng(); + + frost_core::tests::repairable::check_repair_share_step_1::(rng); + } + + #[test] + fn check_repair_share_step_2() { + frost_core::tests::repairable::check_repair_share_step_2::(&REPAIR_SHARE); + } + + #[test] + fn check_repair_share_step_3() { + let rng = thread_rng(); + frost_core::tests::repairable::check_repair_share_step_3::( + rng, + &REPAIR_SHARE, + ); + } +} diff --git a/frost-ed25519/src/tests.rs b/frost-ed25519/src/tests.rs index f55fd78..15a3e18 100644 --- a/frost-ed25519/src/tests.rs +++ b/frost-ed25519/src/tests.rs @@ -1,29 +1,5 @@ -use lazy_static::lazy_static; -use rand::thread_rng; -use serde_json::Value; - -use crate::*; - -lazy_static! { - pub static ref VECTORS: Value = serde_json::from_str(include_str!("tests/vectors.json").trim()) - .expect("Test vector is valid JSON"); - pub static ref VECTORS_BIG_IDENTIFIER: Value = - serde_json::from_str(include_str!("tests/vectors-big-identifier.json").trim()) - .expect("Test vector is valid JSON"); -} - -/// This is testing that Shamir's secret sharing to compute and arbitrary -/// value is working. -#[test] -fn check_share_generation_ed25519_sha512() { - let rng = thread_rng(); - frost_core::tests::check_share_generation::(rng); -} - -#[test] -fn check_sign_with_test_vectors() { - frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS); - frost_core::tests::vectors::check_sign_with_test_vectors::( - &VECTORS_BIG_IDENTIFIER, - ); -} +mod batch; +mod coefficient_commitment; +mod deserialize; +mod proptests; +mod vss_commitment; diff --git a/frost-ed25519/src/tests/batch.rs b/frost-ed25519/src/tests/batch.rs new file mode 100644 index 0000000..47e5f2e --- /dev/null +++ b/frost-ed25519/src/tests/batch.rs @@ -0,0 +1,17 @@ +use rand::thread_rng; + +use crate::*; + +#[test] +fn check_batch_verify() { + let rng = thread_rng(); + + frost_core::tests::batch::batch_verify::(rng); +} + +#[test] +fn check_bad_batch_verify() { + let rng = thread_rng(); + + frost_core::tests::batch::bad_batch_verify::(rng); +} diff --git a/frost-ed25519/src/tests/coefficient_commitment.rs b/frost-ed25519/src/tests/coefficient_commitment.rs new file mode 100644 index 0000000..113eb1c --- /dev/null +++ b/frost-ed25519/src/tests/coefficient_commitment.rs @@ -0,0 +1,46 @@ +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +use crate::*; + +// Tests for serialization and deserialization of CoefficientCommitment + +lazy_static! { + pub static ref ELEMENTS: Value = + serde_json::from_str(include_str!("../../tests/helpers/elements.json").trim()).unwrap(); +} + +#[test] +fn check_serialization_of_coefficient_commitment() { + let rng = thread_rng(); + frost_core::tests::coefficient_commitment::check_serialization_of_coefficient_commitment::< + Ed25519Sha512, + _, + >(rng); +} + +#[test] +fn check_create_coefficient_commitment() { + let rng = thread_rng(); + frost_core::tests::coefficient_commitment::check_create_coefficient_commitment::< + Ed25519Sha512, + _, + >(rng); +} +#[test] +fn check_create_coefficient_commitment_error() { + frost_core::tests::coefficient_commitment::check_create_coefficient_commitment_error::< + Ed25519Sha512, + >(&ELEMENTS); +} + +#[test] +fn check_get_value_of_coefficient_commitment() { + let rng = thread_rng(); + + frost_core::tests::coefficient_commitment::check_get_value_of_coefficient_commitment::< + Ed25519Sha512, + _, + >(rng); +} diff --git a/frost-ed25519/src/tests/deserialize.rs b/frost-ed25519/src/tests/deserialize.rs new file mode 100644 index 0000000..949435c --- /dev/null +++ b/frost-ed25519/src/tests/deserialize.rs @@ -0,0 +1,21 @@ +use crate::*; +use curve25519_dalek::{edwards::EdwardsPoint, traits::Identity}; + +#[test] +fn check_deserialize_non_prime_order() { + let encoded_point = + hex::decode("0300000000000000000000000000000000000000000000000000000000000000") + .unwrap() + .try_into() + .unwrap(); + let r = ::Group::deserialize(&encoded_point); + assert_eq!(r, Err(GroupError::InvalidNonPrimeOrderElement)); +} + +#[test] +fn check_deserialize_identity() { + let encoded_identity = EdwardsPoint::identity().compress().to_bytes(); + + let r = ::Group::deserialize(&encoded_identity); + assert_eq!(r, Err(GroupError::InvalidIdentityElement)); +} diff --git a/frost-ed25519/tests/proptests.rs b/frost-ed25519/src/tests/proptests.rs similarity index 97% rename from frost-ed25519/tests/proptests.rs rename to frost-ed25519/src/tests/proptests.rs index a5f49c6..1e77313 100644 --- a/frost-ed25519/tests/proptests.rs +++ b/frost-ed25519/src/tests/proptests.rs @@ -1,5 +1,5 @@ +use crate::*; use frost_core::tests::proptests::{tweak_strategy, SignatureCase}; -use frost_ed25519::*; use proptest::prelude::*; use rand_chacha::ChaChaRng; diff --git a/frost-ed25519/src/tests/vss_commitment.rs b/frost-ed25519/src/tests/vss_commitment.rs new file mode 100644 index 0000000..b034b08 --- /dev/null +++ b/frost-ed25519/src/tests/vss_commitment.rs @@ -0,0 +1,32 @@ +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +use crate::*; + +// Tests for serialization and deserialization VerifiableSecretSharingCommitment + +lazy_static! { + pub static ref ELEMENTS: Value = + serde_json::from_str(include_str!("../../tests/helpers/elements.json").trim()).unwrap(); +} + +#[test] +fn check_serialize_vss_commitment() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_serialize_vss_commitment::(rng); +} + +#[test] +fn check_deserialize_vss_commitment() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_deserialize_vss_commitment::(rng); +} + +#[test] +fn check_deserialize_vss_commitment_error() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_deserialize_vss_commitment_error::( + rng, &ELEMENTS, + ); +} diff --git a/frost-ed25519/tests.rs b/frost-ed25519/tests.rs new file mode 100644 index 0000000..dc18690 --- /dev/null +++ b/frost-ed25519/tests.rs @@ -0,0 +1,4 @@ +#[cfg(test)] +mod integration_tests; +#[cfg(test)] +mod helpers; \ No newline at end of file diff --git a/frost-ed25519/tests/frost.rs b/frost-ed25519/tests/frost.rs deleted file mode 100644 index d84fcb1..0000000 --- a/frost-ed25519/tests/frost.rs +++ /dev/null @@ -1,169 +0,0 @@ -use frost_ed25519::*; - -use curve25519_dalek::{edwards::EdwardsPoint, traits::Identity}; -use ed25519_dalek::Verifier; -use lazy_static::lazy_static; -use rand::thread_rng; -use serde_json::Value; - -fn verify_signature( - msg: &[u8], - group_signature: frost_core::Signature, - group_pubkey: frost_core::VerifyingKey, -) { - let sig = { - let bytes: [u8; 64] = group_signature.to_bytes(); - ed25519_dalek::Signature::from(bytes) - }; - let pub_key = { - let bytes = group_pubkey.to_bytes(); - ed25519_dalek::PublicKey::from_bytes(&bytes).unwrap() - }; - // Check that signature validation has the expected result. - assert!(pub_key.verify(msg, &sig).is_ok()); -} - -#[test] -fn check_sign_with_dealer() { - let rng = thread_rng(); - - // Test with multiple keys/signatures to better exercise the key generation - // and the interoperability check. - for _ in 0..256 { - let (msg, group_signature, group_pubkey) = - frost_core::tests::check_sign_with_dealer::(rng.clone()); - - // Check that the threshold signature can be verified by the `ed25519_dalek` crate - // public key (interoperability test) - verify_signature(&msg, group_signature, group_pubkey); - } -} - -#[test] -fn check_sign_with_dkg() { - let rng = thread_rng(); - - // Test with multiple keys/signatures to better exercise the key generation - // and the interoperability check. A smaller number of iterations is used - // because DKG takes longer and otherwise the test would be too slow. - for _ in 0..32 { - let (msg, group_signature, group_pubkey) = - frost_core::tests::check_sign_with_dkg::(rng.clone()); - - verify_signature(&msg, group_signature, group_pubkey); - } -} - -#[test] -fn check_batch_verify() { - let rng = thread_rng(); - - frost_core::tests::batch::batch_verify::(rng); -} - -#[test] -fn check_bad_batch_verify() { - let rng = thread_rng(); - - frost_core::tests::batch::bad_batch_verify::(rng); -} - -#[test] -fn check_deserialize_identity() { - let encoded_identity = EdwardsPoint::identity().compress().to_bytes(); - - let r = ::Group::deserialize(&encoded_identity); - assert_eq!(r, Err(GroupError::InvalidIdentityElement)); -} - -#[test] -fn check_deserialize_non_prime_order() { - let encoded_point = - hex::decode("0300000000000000000000000000000000000000000000000000000000000000") - .unwrap() - .try_into() - .unwrap(); - let r = ::Group::deserialize(&encoded_point); - assert_eq!(r, Err(GroupError::InvalidNonPrimeOrderElement)); -} - -#[test] -fn check_repair_share_step_1() { - let rng = thread_rng(); - - frost_core::tests::repairable::check_repair_share_step_1::(rng); -} - -lazy_static! { - pub static ref REPAIR_SHARE: Value = - serde_json::from_str(include_str!("repair-share.json").trim()).unwrap(); -} - -#[test] -fn check_repair_share_step_2() { - frost_core::tests::repairable::check_repair_share_step_2::(&REPAIR_SHARE); -} - -#[test] -fn check_repair_share() { - let rng = thread_rng(); - frost_core::tests::repairable::check_repair_share_step_3::( - rng, - &REPAIR_SHARE, - ); -} - -#[test] -fn check_rts() { - let rng = thread_rng(); - - frost_core::tests::repairable::check_rts::(rng); -} - -/// Tests for serialization and deserialization of CoefficientCommitment and VerifiableSecretSharingCommitment - -#[test] -fn check_serialization_of_coefficient_commitment() { - let rng = thread_rng(); - frost_core::tests::check_serialization_of_coefficient_commitment::(rng); -} - -#[test] -fn check_create_coefficient_commitment() { - let rng = thread_rng(); - frost_core::tests::check_create_coefficient_commitment::(rng); -} -#[test] -fn check_create_coefficient_commitment_error() { - frost_core::tests::check_create_coefficient_commitment_error::(&ELEMENTS); -} - -#[test] -fn check_get_value_of_coefficient_commitment() { - let rng = thread_rng(); - - frost_core::tests::check_get_value_of_coefficient_commitment::(rng); -} - -lazy_static! { - pub static ref ELEMENTS: Value = - serde_json::from_str(include_str!("elements.json").trim()).unwrap(); -} - -#[test] -fn check_serialize_vss_commitment() { - let rng = thread_rng(); - frost_core::tests::check_serialize_vss_commitment::(rng); -} - -#[test] -fn check_deserialize_vss_commitment() { - let rng = thread_rng(); - frost_core::tests::check_deserialize_vss_commitment::(rng); -} - -#[test] -fn check_deserialize_vss_commitment_error() { - let rng = thread_rng(); - frost_core::tests::check_deserialize_vss_commitment_error::(rng, &ELEMENTS); -} diff --git a/frost-ed25519/tests/elements.json b/frost-ed25519/tests/helpers/elements.json similarity index 100% rename from frost-ed25519/tests/elements.json rename to frost-ed25519/tests/helpers/elements.json diff --git a/frost-ed25519/tests/helpers/mod.rs b/frost-ed25519/tests/helpers/mod.rs new file mode 100644 index 0000000..dd5c1f2 --- /dev/null +++ b/frost-ed25519/tests/helpers/mod.rs @@ -0,0 +1,20 @@ +use ed25519_dalek::Verifier; +use frost_ed25519::*; + +// #[cfg(test)] +pub fn verify_signature( + msg: &[u8], + group_signature: frost_core::Signature, + group_pubkey: frost_core::VerifyingKey, +) { + let sig = { + let bytes: [u8; 64] = group_signature.to_bytes(); + ed25519_dalek::Signature::from(bytes) + }; + let pub_key = { + let bytes = group_pubkey.to_bytes(); + ed25519_dalek::PublicKey::from_bytes(&bytes).unwrap() + }; + // Check that signature validation has the expected result. + assert!(pub_key.verify(msg, &sig).is_ok()); +} diff --git a/frost-ed25519/tests/repair-share.json b/frost-ed25519/tests/helpers/repair-share.json similarity index 100% rename from frost-ed25519/tests/repair-share.json rename to frost-ed25519/tests/helpers/repair-share.json diff --git a/frost-ed25519/src/tests/vectors-big-identifier.json b/frost-ed25519/tests/helpers/vectors-big-identifier.json similarity index 100% rename from frost-ed25519/src/tests/vectors-big-identifier.json rename to frost-ed25519/tests/helpers/vectors-big-identifier.json diff --git a/frost-ed25519/src/tests/vectors.json b/frost-ed25519/tests/helpers/vectors.json similarity index 100% rename from frost-ed25519/src/tests/vectors.json rename to frost-ed25519/tests/helpers/vectors.json diff --git a/frost-ed25519/tests/integration_test.rs b/frost-ed25519/tests/integration_test.rs new file mode 100644 index 0000000..b3a40b4 --- /dev/null +++ b/frost-ed25519/tests/integration_test.rs @@ -0,0 +1,74 @@ +use crate::Ed25519Sha512; +use frost_ed25519::*; +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +mod helpers; + +#[test] +fn check_sign_with_dkg() { + let rng = thread_rng(); + + // Test with multiple keys/signatures to better exercise the key generation + // and the interoperability check. A smaller number of iterations is used + // because DKG takes longer and otherwise the test would be too slow. + for _ in 0..32 { + let (msg, group_signature, group_pubkey) = + frost_core::tests::ciphersuite_generic::check_sign_with_dkg::( + rng.clone(), + ); + + helpers::verify_signature(&msg, group_signature, group_pubkey); + } +} + +#[test] +fn check_rts() { + let rng = thread_rng(); + + frost_core::tests::repairable::check_rts::(rng); +} + +#[test] +fn check_sign_with_dealer() { + let rng = thread_rng(); + + // Test with multiple keys/signatures to better exercise the key generation + // and the interoperability check. + for _ in 0..256 { + let (msg, group_signature, group_pubkey) = + frost_core::tests::ciphersuite_generic::check_sign_with_dealer::( + rng.clone(), + ); + + // Check that the threshold signature can be verified by the `ed25519_dalek` crate + // public key (interoperability test) + helpers::verify_signature(&msg, group_signature, group_pubkey); + } +} + +/// This is testing that Shamir's secret sharing to compute and arbitrary +/// value is working. +#[test] +fn check_share_generation_ed25519_sha512() { + let rng = thread_rng(); + frost_core::tests::ciphersuite_generic::check_share_generation::(rng); +} + +lazy_static! { + pub static ref VECTORS: Value = + serde_json::from_str(include_str!("../tests/helpers/vectors.json").trim()) + .expect("Test vector is valid JSON"); + pub static ref VECTORS_BIG_IDENTIFIER: Value = + serde_json::from_str(include_str!("../tests/helpers/vectors-big-identifier.json").trim()) + .expect("Test vector is valid JSON"); +} + +#[test] +fn check_sign_with_test_vectors() { + frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS); + frost_core::tests::vectors::check_sign_with_test_vectors::( + &VECTORS_BIG_IDENTIFIER, + ); +} diff --git a/frost-ed448/src/keys/repairable.rs b/frost-ed448/src/keys/repairable.rs index 80d14dd..2e8fbac 100644 --- a/frost-ed448/src/keys/repairable.rs +++ b/frost-ed448/src/keys/repairable.rs @@ -53,3 +53,40 @@ pub fn repair_share_step_3( ) -> SecretShare { frost::keys::repairable::repair_share_step_3(sigmas, identifier, commitment) } + +#[cfg(test)] +mod tests { + + use lazy_static::lazy_static; + use rand::thread_rng; + use serde_json::Value; + + use crate::Ed448Shake256; + + lazy_static! { + pub static ref REPAIR_SHARE: Value = + serde_json::from_str(include_str!("../../tests/helpers/repair-share.json").trim()) + .unwrap(); + } + + #[test] + fn check_repair_share_step_1() { + let rng = thread_rng(); + + frost_core::tests::repairable::check_repair_share_step_1::(rng); + } + + #[test] + fn check_repair_share_step_2() { + frost_core::tests::repairable::check_repair_share_step_2::(&REPAIR_SHARE); + } + + #[test] + fn check_repair_share_step_3() { + let rng = thread_rng(); + frost_core::tests::repairable::check_repair_share_step_3::( + rng, + &REPAIR_SHARE, + ); + } +} diff --git a/frost-ed448/src/tests.rs b/frost-ed448/src/tests.rs index 4bb142d..15a3e18 100644 --- a/frost-ed448/src/tests.rs +++ b/frost-ed448/src/tests.rs @@ -1,29 +1,5 @@ -use lazy_static::lazy_static; -use rand::thread_rng; -use serde_json::Value; - -use crate::*; - -lazy_static! { - pub static ref VECTORS: Value = serde_json::from_str(include_str!("tests/vectors.json").trim()) - .expect("Test vector is valid JSON"); - pub static ref VECTORS_BIG_IDENTIFIER: Value = - serde_json::from_str(include_str!("tests/vectors-big-identifier.json").trim()) - .expect("Test vector is valid JSON"); -} - -/// This is testing that Shamir's secret sharing to compute and arbitrary -/// value is working. -#[test] -fn check_share_generation_ed448_shake256() { - let rng = thread_rng(); - frost_core::tests::check_share_generation::(rng); -} - -#[test] -fn check_sign_with_test_vectors() { - frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS); - frost_core::tests::vectors::check_sign_with_test_vectors::( - &VECTORS_BIG_IDENTIFIER, - ); -} +mod batch; +mod coefficient_commitment; +mod deserialize; +mod proptests; +mod vss_commitment; diff --git a/frost-ed448/src/tests/batch.rs b/frost-ed448/src/tests/batch.rs new file mode 100644 index 0000000..77fb83e --- /dev/null +++ b/frost-ed448/src/tests/batch.rs @@ -0,0 +1,21 @@ +use rand::thread_rng; + +use crate::*; + +// TODO: make batching work for larger scalars +// #[test] +#[allow(unused)] +fn check_batch_verify() { + let rng = thread_rng(); + + frost_core::tests::batch::batch_verify::(rng); +} + +// TODO: make batching work for larger scalars +// #[test] +#[allow(unused)] +fn check_bad_batch_verify() { + let rng = thread_rng(); + + frost_core::tests::batch::bad_batch_verify::(rng); +} diff --git a/frost-ed448/src/tests/coefficient_commitment.rs b/frost-ed448/src/tests/coefficient_commitment.rs new file mode 100644 index 0000000..d088ad1 --- /dev/null +++ b/frost-ed448/src/tests/coefficient_commitment.rs @@ -0,0 +1,46 @@ +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +use crate::*; + +// Tests for serialization and deserialization of CoefficientCommitment + +lazy_static! { + pub static ref ELEMENTS: Value = + serde_json::from_str(include_str!("../../tests/helpers/elements.json").trim()).unwrap(); +} + +#[test] +fn check_serialization_of_coefficient_commitment() { + let rng = thread_rng(); + frost_core::tests::coefficient_commitment::check_serialization_of_coefficient_commitment::< + Ed448Shake256, + _, + >(rng); +} + +#[test] +fn check_create_coefficient_commitment() { + let rng = thread_rng(); + frost_core::tests::coefficient_commitment::check_create_coefficient_commitment::< + Ed448Shake256, + _, + >(rng); +} +#[test] +fn check_create_coefficient_commitment_error() { + frost_core::tests::coefficient_commitment::check_create_coefficient_commitment_error::< + Ed448Shake256, + >(&ELEMENTS); +} + +#[test] +fn check_get_value_of_coefficient_commitment() { + let rng = thread_rng(); + + frost_core::tests::coefficient_commitment::check_get_value_of_coefficient_commitment::< + Ed448Shake256, + _, + >(rng); +} diff --git a/frost-ed448/src/tests/deserialize.rs b/frost-ed448/src/tests/deserialize.rs new file mode 100644 index 0000000..6c86b77 --- /dev/null +++ b/frost-ed448/src/tests/deserialize.rs @@ -0,0 +1,42 @@ +use crate::*; +use ed448_goldilocks::curve::ExtendedPoint; +use frost_core::Ciphersuite; + +#[test] +fn check_deserialize_non_canonical() { + let mut encoded_generator = ExtendedPoint::generator().compress().0; + + let r = ::Group::deserialize(&encoded_generator); + assert!(r.is_ok()); + + // The last byte only should have the sign bit. Set all other bits to + // create a non-canonical encoding. + encoded_generator[56] |= 0x7f; + let r = ::Group::deserialize(&encoded_generator); + assert_eq!(r, Err(GroupError::MalformedElement)); + + // Besides the last byte, it is still possible to get non-canonical encodings. + // This is y = p + 19 which is non-canonical and maps to a valid prime-order point. + let encoded_point = hex::decode("12000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00").unwrap().try_into().unwrap(); + let r = ::Group::deserialize(&encoded_point); + assert_eq!(r, Err(GroupError::MalformedElement)); +} + +#[test] +fn check_deserialize_non_prime_order() { + let encoded_point = + hex::decode("030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + .unwrap() + .try_into() + .unwrap(); + let r = ::Group::deserialize(&encoded_point); + assert_eq!(r, Err(GroupError::InvalidNonPrimeOrderElement)); +} + +#[test] +fn check_deserialize_identity() { + let encoded_identity = ExtendedPoint::identity().compress().0; + + let r = ::Group::deserialize(&encoded_identity); + assert_eq!(r, Err(GroupError::InvalidIdentityElement)); +} diff --git a/frost-ed448/tests/proptests.rs b/frost-ed448/src/tests/proptests.rs similarity index 97% rename from frost-ed448/tests/proptests.rs rename to frost-ed448/src/tests/proptests.rs index 4f03ce2..b01fd0e 100644 --- a/frost-ed448/tests/proptests.rs +++ b/frost-ed448/src/tests/proptests.rs @@ -1,10 +1,11 @@ use frost_core::tests::proptests::{tweak_strategy, SignatureCase}; -use frost_ed448::*; use proptest::prelude::*; use rand_chacha::ChaChaRng; use rand_core::SeedableRng; +use crate::*; + proptest! { #[test] diff --git a/frost-ed448/src/tests/vss_commitment.rs b/frost-ed448/src/tests/vss_commitment.rs new file mode 100644 index 0000000..8ed10e0 --- /dev/null +++ b/frost-ed448/src/tests/vss_commitment.rs @@ -0,0 +1,32 @@ +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +use crate::*; + +// Tests for serialization and deserialization VerifiableSecretSharingCommitment + +lazy_static! { + pub static ref ELEMENTS: Value = + serde_json::from_str(include_str!("../../tests/helpers/elements.json").trim()).unwrap(); +} + +#[test] +fn check_serialize_vss_commitment() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_serialize_vss_commitment::(rng); +} + +#[test] +fn check_deserialize_vss_commitment() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_deserialize_vss_commitment::(rng); +} + +#[test] +fn check_deserialize_vss_commitment_error() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_deserialize_vss_commitment_error::( + rng, &ELEMENTS, + ); +} diff --git a/frost-ed448/tests/frost.rs b/frost-ed448/tests/frost.rs deleted file mode 100644 index a8162f5..0000000 --- a/frost-ed448/tests/frost.rs +++ /dev/null @@ -1,158 +0,0 @@ -use ed448_goldilocks::curve::ExtendedPoint; - -use frost_ed448::*; -use lazy_static::lazy_static; -use rand::thread_rng; -use serde_json::Value; - -#[test] -fn check_sign_with_dealer() { - let rng = thread_rng(); - - frost_core::tests::check_sign_with_dealer::(rng); -} - -#[test] -fn check_sign_with_dkg() { - let rng = thread_rng(); - - frost_core::tests::check_sign_with_dkg::(rng); -} - -// TODO: make batching work for larger scalars -// #[test] -#[allow(unused)] -fn check_batch_verify() { - let rng = thread_rng(); - - frost_core::tests::batch::batch_verify::(rng); -} - -// TODO: make batching work for larger scalars -// #[test] -#[allow(unused)] -fn check_bad_batch_verify() { - let rng = thread_rng(); - - frost_core::tests::batch::bad_batch_verify::(rng); -} - -#[test] -fn check_deserialize_identity() { - let encoded_identity = ExtendedPoint::identity().compress().0; - - let r = ::Group::deserialize(&encoded_identity); - assert_eq!(r, Err(GroupError::InvalidIdentityElement)); -} - -#[test] -fn check_deserialize_non_canonical() { - let mut encoded_generator = ExtendedPoint::generator().compress().0; - - let r = ::Group::deserialize(&encoded_generator); - assert!(r.is_ok()); - - // The last byte only should have the sign bit. Set all other bits to - // create a non-canonical encoding. - encoded_generator[56] |= 0x7f; - let r = ::Group::deserialize(&encoded_generator); - assert_eq!(r, Err(GroupError::MalformedElement)); - - // Besides the last byte, it is still possible to get non-canonical encodings. - // This is y = p + 19 which is non-canonical and maps to a valid prime-order point. - let encoded_point = hex::decode("12000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00").unwrap().try_into().unwrap(); - let r = ::Group::deserialize(&encoded_point); - assert_eq!(r, Err(GroupError::MalformedElement)); -} - -#[test] -fn check_deserialize_non_prime_order() { - let encoded_point = - hex::decode("030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") - .unwrap() - .try_into() - .unwrap(); - let r = ::Group::deserialize(&encoded_point); - assert_eq!(r, Err(GroupError::InvalidNonPrimeOrderElement)); -} - -#[test] -fn check_repair_share_step_1() { - let rng = thread_rng(); - - frost_core::tests::repairable::check_repair_share_step_1::(rng); -} - -lazy_static! { - pub static ref REPAIR_SHARE: Value = - serde_json::from_str(include_str!("repair-share.json").trim()).unwrap(); -} - -#[test] -fn check_repair_share_step_2() { - frost_core::tests::repairable::check_repair_share_step_2::(&REPAIR_SHARE); -} - -#[test] -fn check_repair_share() { - let rng = thread_rng(); - frost_core::tests::repairable::check_repair_share_step_3::( - rng, - &REPAIR_SHARE, - ); -} - -#[test] -fn check_rts() { - let rng = thread_rng(); - - frost_core::tests::repairable::check_rts::(rng); -} - -/// Tests for serialization and deserialization of CoefficientCommitment and VerifiableSecretSharingCommitment - -#[test] -fn check_serialization_of_coefficient_commitment() { - let rng = thread_rng(); - frost_core::tests::check_serialization_of_coefficient_commitment::(rng); -} - -#[test] -fn check_create_coefficient_commitment() { - let rng = thread_rng(); - frost_core::tests::check_create_coefficient_commitment::(rng); -} -#[test] -fn check_create_coefficient_commitment_error() { - frost_core::tests::check_create_coefficient_commitment_error::(&ELEMENTS); -} - -#[test] -fn check_get_value_of_coefficient_commitment() { - let rng = thread_rng(); - - frost_core::tests::check_get_value_of_coefficient_commitment::(rng); -} - -lazy_static! { - pub static ref ELEMENTS: Value = - serde_json::from_str(include_str!("elements.json").trim()).unwrap(); -} - -#[test] -fn check_serialize_vss_commitment() { - let rng = thread_rng(); - frost_core::tests::check_serialize_vss_commitment::(rng); -} - -#[test] -fn check_deserialize_vss_commitment() { - let rng = thread_rng(); - frost_core::tests::check_deserialize_vss_commitment::(rng); -} - -#[test] -fn check_deserialize_vss_commitment_error() { - let rng = thread_rng(); - frost_core::tests::check_deserialize_vss_commitment_error::(rng, &ELEMENTS); -} diff --git a/frost-ed448/tests/elements.json b/frost-ed448/tests/helpers/elements.json similarity index 100% rename from frost-ed448/tests/elements.json rename to frost-ed448/tests/helpers/elements.json diff --git a/frost-ed448/tests/repair-share.json b/frost-ed448/tests/helpers/repair-share.json similarity index 100% rename from frost-ed448/tests/repair-share.json rename to frost-ed448/tests/helpers/repair-share.json diff --git a/frost-ed448/src/tests/vectors-big-identifier.json b/frost-ed448/tests/helpers/vectors-big-identifier.json similarity index 100% rename from frost-ed448/src/tests/vectors-big-identifier.json rename to frost-ed448/tests/helpers/vectors-big-identifier.json diff --git a/frost-ed448/src/tests/vectors.json b/frost-ed448/tests/helpers/vectors.json similarity index 100% rename from frost-ed448/src/tests/vectors.json rename to frost-ed448/tests/helpers/vectors.json diff --git a/frost-ed448/tests/integration_tests.rs b/frost-ed448/tests/integration_tests.rs new file mode 100644 index 0000000..0e45097 --- /dev/null +++ b/frost-ed448/tests/integration_tests.rs @@ -0,0 +1,50 @@ +use frost_ed448::*; +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +#[test] +fn check_sign_with_dkg() { + let rng = thread_rng(); + + frost_core::tests::ciphersuite_generic::check_sign_with_dkg::(rng); +} + +#[test] +fn check_rts() { + let rng = thread_rng(); + + frost_core::tests::repairable::check_rts::(rng); +} + +#[test] +fn check_sign_with_dealer() { + let rng = thread_rng(); + + frost_core::tests::ciphersuite_generic::check_sign_with_dealer::(rng); +} + +/// This is testing that Shamir's secret sharing to compute and arbitrary +/// value is working. +#[test] +fn check_share_generation_ed448_shake256() { + let rng = thread_rng(); + frost_core::tests::ciphersuite_generic::check_share_generation::(rng); +} + +lazy_static! { + pub static ref VECTORS: Value = + serde_json::from_str(include_str!("../tests/helpers/vectors.json").trim()) + .expect("Test vector is valid JSON"); + pub static ref VECTORS_BIG_IDENTIFIER: Value = + serde_json::from_str(include_str!("../tests/helpers/vectors-big-identifier.json").trim()) + .expect("Test vector is valid JSON"); +} + +#[test] +fn check_sign_with_test_vectors() { + frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS); + frost_core::tests::vectors::check_sign_with_test_vectors::( + &VECTORS_BIG_IDENTIFIER, + ); +} diff --git a/frost-p256/src/keys/repairable.rs b/frost-p256/src/keys/repairable.rs index 587056e..5aa9728 100644 --- a/frost-p256/src/keys/repairable.rs +++ b/frost-p256/src/keys/repairable.rs @@ -53,3 +53,40 @@ pub fn repair_share_step_3( ) -> SecretShare { frost::keys::repairable::repair_share_step_3(sigmas, identifier, commitment) } + +#[cfg(test)] +mod tests { + + use lazy_static::lazy_static; + use rand::thread_rng; + use serde_json::Value; + + use crate::P256Sha256; + + lazy_static! { + pub static ref REPAIR_SHARE: Value = + serde_json::from_str(include_str!("../../tests/helpers/repair-share.json").trim()) + .unwrap(); + } + + #[test] + fn check_repair_share_step_1() { + let rng = thread_rng(); + + frost_core::tests::repairable::check_repair_share_step_1::(rng); + } + + #[test] + fn check_repair_share_step_2() { + frost_core::tests::repairable::check_repair_share_step_2::(&REPAIR_SHARE); + } + + #[test] + fn check_repair_share_step_3() { + let rng = thread_rng(); + frost_core::tests::repairable::check_repair_share_step_3::( + rng, + &REPAIR_SHARE, + ); + } +} diff --git a/frost-p256/src/tests.rs b/frost-p256/src/tests.rs index fcf5645..15a3e18 100644 --- a/frost-p256/src/tests.rs +++ b/frost-p256/src/tests.rs @@ -1,27 +1,5 @@ -use lazy_static::lazy_static; -use rand::thread_rng; -use serde_json::Value; - -use crate::*; - -lazy_static! { - pub static ref VECTORS: Value = serde_json::from_str(include_str!("tests/vectors.json").trim()) - .expect("Test vector is valid JSON"); - pub static ref VECTORS_BIG_IDENTIFIER: Value = - serde_json::from_str(include_str!("tests/vectors-big-identifier.json").trim()) - .expect("Test vector is valid JSON"); -} - -/// This is testing that Shamir's secret sharing to compute and arbitrary -/// value is working. -#[test] -fn check_share_generation_p256_sha256() { - let rng = thread_rng(); - frost_core::tests::check_share_generation::(rng); -} - -#[test] -fn check_sign_with_test_vectors() { - frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS); - frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS_BIG_IDENTIFIER); -} +mod batch; +mod coefficient_commitment; +mod deserialize; +mod proptests; +mod vss_commitment; diff --git a/frost-p256/src/tests/batch.rs b/frost-p256/src/tests/batch.rs new file mode 100644 index 0000000..c6b6e7d --- /dev/null +++ b/frost-p256/src/tests/batch.rs @@ -0,0 +1,17 @@ +use rand::thread_rng; + +use crate::*; + +#[test] +fn check_batch_verify() { + let rng = thread_rng(); + + frost_core::tests::batch::batch_verify::(rng); +} + +#[test] +fn check_bad_batch_verify() { + let rng = thread_rng(); + + frost_core::tests::batch::bad_batch_verify::(rng); +} diff --git a/frost-p256/src/tests/coefficient_commitment.rs b/frost-p256/src/tests/coefficient_commitment.rs new file mode 100644 index 0000000..8083aea --- /dev/null +++ b/frost-p256/src/tests/coefficient_commitment.rs @@ -0,0 +1,45 @@ +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +use crate::*; + +// Tests for serialization and deserialization of CoefficientCommitment + +lazy_static! { + pub static ref ELEMENTS: Value = + serde_json::from_str(include_str!("../../tests/helpers/elements.json").trim()).unwrap(); +} + +#[test] +fn check_serialization_of_coefficient_commitment() { + let rng = thread_rng(); + frost_core::tests::coefficient_commitment::check_serialization_of_coefficient_commitment::< + P256Sha256, + _, + >(rng); +} + +#[test] +fn check_create_coefficient_commitment() { + let rng = thread_rng(); + frost_core::tests::coefficient_commitment::check_create_coefficient_commitment::( + rng, + ); +} +#[test] +fn check_create_coefficient_commitment_error() { + frost_core::tests::coefficient_commitment::check_create_coefficient_commitment_error::< + P256Sha256, + >(&ELEMENTS); +} + +#[test] +fn check_get_value_of_coefficient_commitment() { + let rng = thread_rng(); + + frost_core::tests::coefficient_commitment::check_get_value_of_coefficient_commitment::< + P256Sha256, + _, + >(rng); +} diff --git a/frost-p256/src/tests/deserialize.rs b/frost-p256/src/tests/deserialize.rs new file mode 100644 index 0000000..38aa9e6 --- /dev/null +++ b/frost-p256/src/tests/deserialize.rs @@ -0,0 +1,37 @@ +use crate::*; + +#[test] +fn check_deserialize_non_canonical() { + let mut encoded_generator = ::Group::serialize( + &::Group::generator(), + ); + + let r = ::Group::deserialize(&encoded_generator); + assert!(r.is_ok()); + + // The first byte should be 0x02 or 0x03. Set other value to + // create a non-canonical encoding. + encoded_generator[0] = 0xFF; + let r = ::Group::deserialize(&encoded_generator); + assert_eq!(r, Err(GroupError::MalformedElement)); + + // Besides the first byte, it is still possible to get non-canonical encodings. + // This is x = p + 5 which is non-canonical and maps to a valid prime-order point. + let encoded_point = + hex::decode("02ffffffff00000001000000000000000000000001000000000000000000000004") + .unwrap() + .try_into() + .unwrap(); + let r = ::Group::deserialize(&encoded_point); + assert_eq!(r, Err(GroupError::MalformedElement)); +} + +#[test] +fn check_deserialize_identity() { + // The identity is actually encoded as a single byte; but the API does not + // allow us to change that. Try to send something similar. + let encoded_identity = [0u8; 33]; + + let r = ::Group::deserialize(&encoded_identity); + assert_eq!(r, Err(GroupError::MalformedElement)); +} diff --git a/frost-p256/tests/proptests.rs b/frost-p256/src/tests/proptests.rs similarity index 97% rename from frost-p256/tests/proptests.rs rename to frost-p256/src/tests/proptests.rs index 3214742..9da4b7e 100644 --- a/frost-p256/tests/proptests.rs +++ b/frost-p256/src/tests/proptests.rs @@ -1,5 +1,5 @@ +use crate::*; use frost_core::tests::proptests::{tweak_strategy, SignatureCase}; -use frost_p256::*; use proptest::prelude::*; use rand_chacha::ChaChaRng; diff --git a/frost-p256/src/tests/vss_commitment.rs b/frost-p256/src/tests/vss_commitment.rs new file mode 100644 index 0000000..1eeceff --- /dev/null +++ b/frost-p256/src/tests/vss_commitment.rs @@ -0,0 +1,32 @@ +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +use crate::*; + +// Tests for serialization and deserialization VerifiableSecretSharingCommitment + +lazy_static! { + pub static ref ELEMENTS: Value = + serde_json::from_str(include_str!("../../tests/helpers/elements.json").trim()).unwrap(); +} + +#[test] +fn check_serialize_vss_commitment() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_serialize_vss_commitment::(rng); +} + +#[test] +fn check_deserialize_vss_commitment() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_deserialize_vss_commitment::(rng); +} + +#[test] +fn check_deserialize_vss_commitment_error() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_deserialize_vss_commitment_error::( + rng, &ELEMENTS, + ); +} diff --git a/frost-p256/tests/frost.rs b/frost-p256/tests/frost.rs deleted file mode 100644 index 266c477..0000000 --- a/frost-p256/tests/frost.rs +++ /dev/null @@ -1,146 +0,0 @@ -use frost_p256::*; -use lazy_static::lazy_static; -use rand::thread_rng; -use serde_json::Value; - -#[test] -fn check_sign_with_dealer() { - let rng = thread_rng(); - - frost_core::tests::check_sign_with_dealer::(rng); -} - -#[test] -fn check_sign_with_dkg() { - let rng = thread_rng(); - - frost_core::tests::check_sign_with_dkg::(rng); -} - -#[test] -fn check_batch_verify() { - let rng = thread_rng(); - - frost_core::tests::batch::batch_verify::(rng); -} - -#[test] -fn check_bad_batch_verify() { - let rng = thread_rng(); - - frost_core::tests::batch::bad_batch_verify::(rng); -} - -#[test] -fn check_deserialize_identity() { - // The identity is actually encoded as a single byte; but the API does not - // allow us to change that. Try to send something similar. - let encoded_identity = [0u8; 33]; - - let r = ::Group::deserialize(&encoded_identity); - assert_eq!(r, Err(GroupError::MalformedElement)); -} - -#[test] -fn check_deserialize_non_canonical() { - let mut encoded_generator = ::Group::serialize( - &::Group::generator(), - ); - - let r = ::Group::deserialize(&encoded_generator); - assert!(r.is_ok()); - - // The first byte should be 0x02 or 0x03. Set other value to - // create a non-canonical encoding. - encoded_generator[0] = 0xFF; - let r = ::Group::deserialize(&encoded_generator); - assert_eq!(r, Err(GroupError::MalformedElement)); - - // Besides the first byte, it is still possible to get non-canonical encodings. - // This is x = p + 5 which is non-canonical and maps to a valid prime-order point. - let encoded_point = - hex::decode("02ffffffff00000001000000000000000000000001000000000000000000000004") - .unwrap() - .try_into() - .unwrap(); - let r = ::Group::deserialize(&encoded_point); - assert_eq!(r, Err(GroupError::MalformedElement)); -} - -#[test] -fn check_repair_share_step_1() { - let rng = thread_rng(); - - frost_core::tests::repairable::check_repair_share_step_1::(rng); -} - -lazy_static! { - pub static ref REPAIR_SHARE: Value = - serde_json::from_str(include_str!("repair-share.json").trim()).unwrap(); -} - -#[test] -fn check_repair_share_step_2() { - frost_core::tests::repairable::check_repair_share_step_2::(&REPAIR_SHARE); -} - -#[test] -fn check_repair_share() { - let rng = thread_rng(); - frost_core::tests::repairable::check_repair_share_step_3::(rng, &REPAIR_SHARE); -} - -#[test] -fn check_rts() { - let rng = thread_rng(); - - frost_core::tests::repairable::check_rts::(rng); -} - -/// Tests for serialization and deserialization of CoefficientCommitment and VerifiableSecretSharingCommitment - -#[test] -fn check_serialization_of_coefficient_commitment() { - let rng = thread_rng(); - frost_core::tests::check_serialization_of_coefficient_commitment::(rng); -} - -#[test] -fn check_create_coefficient_commitment() { - let rng = thread_rng(); - frost_core::tests::check_create_coefficient_commitment::(rng); -} -#[test] -fn check_create_coefficient_commitment_error() { - frost_core::tests::check_create_coefficient_commitment_error::(&ELEMENTS); -} - -#[test] -fn check_get_value_of_coefficient_commitment() { - let rng = thread_rng(); - - frost_core::tests::check_get_value_of_coefficient_commitment::(rng); -} - -lazy_static! { - pub static ref ELEMENTS: Value = - serde_json::from_str(include_str!("elements.json").trim()).unwrap(); -} - -#[test] -fn check_serialize_vss_commitment() { - let rng = thread_rng(); - frost_core::tests::check_serialize_vss_commitment::(rng); -} - -#[test] -fn check_deserialize_vss_commitment() { - let rng = thread_rng(); - frost_core::tests::check_deserialize_vss_commitment::(rng); -} - -#[test] -fn check_deserialize_vss_commitment_error() { - let rng = thread_rng(); - frost_core::tests::check_deserialize_vss_commitment_error::(rng, &ELEMENTS); -} diff --git a/frost-p256/tests/elements.json b/frost-p256/tests/helpers/elements.json similarity index 100% rename from frost-p256/tests/elements.json rename to frost-p256/tests/helpers/elements.json diff --git a/frost-p256/tests/repair-share.json b/frost-p256/tests/helpers/repair-share.json similarity index 100% rename from frost-p256/tests/repair-share.json rename to frost-p256/tests/helpers/repair-share.json diff --git a/frost-p256/src/tests/vectors-big-identifier.json b/frost-p256/tests/helpers/vectors-big-identifier.json similarity index 100% rename from frost-p256/src/tests/vectors-big-identifier.json rename to frost-p256/tests/helpers/vectors-big-identifier.json diff --git a/frost-p256/src/tests/vectors.json b/frost-p256/tests/helpers/vectors.json similarity index 100% rename from frost-p256/src/tests/vectors.json rename to frost-p256/tests/helpers/vectors.json diff --git a/frost-p256/tests/integration_tests.rs b/frost-p256/tests/integration_tests.rs new file mode 100644 index 0000000..18b18a9 --- /dev/null +++ b/frost-p256/tests/integration_tests.rs @@ -0,0 +1,48 @@ +use frost_p256::*; +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +#[test] +fn check_sign_with_dkg() { + let rng = thread_rng(); + + frost_core::tests::ciphersuite_generic::check_sign_with_dkg::(rng); +} + +#[test] +fn check_rts() { + let rng = thread_rng(); + + frost_core::tests::repairable::check_rts::(rng); +} + +#[test] +fn check_sign_with_dealer() { + let rng = thread_rng(); + + frost_core::tests::ciphersuite_generic::check_sign_with_dealer::(rng); +} + +/// This is testing that Shamir's secret sharing to compute and arbitrary +/// value is working. +#[test] +fn check_share_generation_p256_sha256() { + let rng = thread_rng(); + frost_core::tests::ciphersuite_generic::check_share_generation::(rng); +} + +lazy_static! { + pub static ref VECTORS: Value = + serde_json::from_str(include_str!("../tests/helpers/vectors.json").trim()) + .expect("Test vector is valid JSON"); + pub static ref VECTORS_BIG_IDENTIFIER: Value = + serde_json::from_str(include_str!("../tests/helpers/vectors-big-identifier.json").trim()) + .expect("Test vector is valid JSON"); +} + +#[test] +fn check_sign_with_test_vectors() { + frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS); + frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS_BIG_IDENTIFIER); +} diff --git a/frost-ristretto255/src/keys/repairable.rs b/frost-ristretto255/src/keys/repairable.rs index 3710c0a..5b325f0 100644 --- a/frost-ristretto255/src/keys/repairable.rs +++ b/frost-ristretto255/src/keys/repairable.rs @@ -53,3 +53,42 @@ pub fn repair_share_step_3( ) -> SecretShare { frost::keys::repairable::repair_share_step_3(sigmas, identifier, commitment) } + +#[cfg(test)] +mod tests { + + use lazy_static::lazy_static; + use rand::thread_rng; + use serde_json::Value; + + use crate::Ristretto255Sha512; + + lazy_static! { + pub static ref REPAIR_SHARE: Value = + serde_json::from_str(include_str!("../../tests/helpers/repair-share.json").trim()) + .unwrap(); + } + + #[test] + fn check_repair_share_step_1() { + let rng = thread_rng(); + + frost_core::tests::repairable::check_repair_share_step_1::(rng); + } + + #[test] + fn check_repair_share_step_2() { + frost_core::tests::repairable::check_repair_share_step_2::( + &REPAIR_SHARE, + ); + } + + #[test] + fn check_repair_share_step_3() { + let rng = thread_rng(); + frost_core::tests::repairable::check_repair_share_step_3::( + rng, + &REPAIR_SHARE, + ); + } +} diff --git a/frost-ristretto255/src/tests.rs b/frost-ristretto255/src/tests.rs index 7a746d8..15a3e18 100644 --- a/frost-ristretto255/src/tests.rs +++ b/frost-ristretto255/src/tests.rs @@ -1,29 +1,5 @@ -use lazy_static::lazy_static; -use rand::thread_rng; -use serde_json::Value; - -use crate::*; - -lazy_static! { - pub static ref VECTORS: Value = serde_json::from_str(include_str!("tests/vectors.json").trim()) - .expect("Test vector is valid JSON"); - pub static ref VECTORS_BIG_IDENTIFIER: Value = - serde_json::from_str(include_str!("tests/vectors-big-identifier.json").trim()) - .expect("Test vector is valid JSON"); -} - -/// This is testing that Shamir's secret sharing to compute and arbitrary -/// value is working. -#[test] -fn check_share_generation_ristretto255_sha512() { - let rng = thread_rng(); - frost_core::tests::check_share_generation::(rng); -} - -#[test] -fn check_sign_with_test_vectors() { - frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS); - frost_core::tests::vectors::check_sign_with_test_vectors::( - &VECTORS_BIG_IDENTIFIER, - ); -} +mod batch; +mod coefficient_commitment; +mod deserialize; +mod proptests; +mod vss_commitment; diff --git a/frost-ristretto255/src/tests/batch.rs b/frost-ristretto255/src/tests/batch.rs new file mode 100644 index 0000000..5256eb9 --- /dev/null +++ b/frost-ristretto255/src/tests/batch.rs @@ -0,0 +1,17 @@ +use rand::thread_rng; + +use crate::*; + +#[test] +fn check_batch_verify() { + let rng = thread_rng(); + + frost_core::tests::batch::batch_verify::(rng); +} + +#[test] +fn check_bad_batch_verify() { + let rng = thread_rng(); + + frost_core::tests::batch::bad_batch_verify::(rng); +} diff --git a/frost-ristretto255/src/tests/coefficient_commitment.rs b/frost-ristretto255/src/tests/coefficient_commitment.rs new file mode 100644 index 0000000..e5df351 --- /dev/null +++ b/frost-ristretto255/src/tests/coefficient_commitment.rs @@ -0,0 +1,46 @@ +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +use crate::*; + +// Tests for serialization and deserialization of CoefficientCommitment + +lazy_static! { + pub static ref ELEMENTS: Value = + serde_json::from_str(include_str!("../../tests/helpers/elements.json").trim()).unwrap(); +} + +#[test] +fn check_serialization_of_coefficient_commitment() { + let rng = thread_rng(); + frost_core::tests::coefficient_commitment::check_serialization_of_coefficient_commitment::< + Ristretto255Sha512, + _, + >(rng); +} + +#[test] +fn check_create_coefficient_commitment() { + let rng = thread_rng(); + frost_core::tests::coefficient_commitment::check_create_coefficient_commitment::< + Ristretto255Sha512, + _, + >(rng); +} +#[test] +fn check_create_coefficient_commitment_error() { + frost_core::tests::coefficient_commitment::check_create_coefficient_commitment_error::< + Ristretto255Sha512, + >(&ELEMENTS); +} + +#[test] +fn check_get_value_of_coefficient_commitment() { + let rng = thread_rng(); + + frost_core::tests::coefficient_commitment::check_get_value_of_coefficient_commitment::< + Ristretto255Sha512, + _, + >(rng); +} diff --git a/frost-ristretto255/src/tests/deserialize.rs b/frost-ristretto255/src/tests/deserialize.rs new file mode 100644 index 0000000..f7d2ddf --- /dev/null +++ b/frost-ristretto255/src/tests/deserialize.rs @@ -0,0 +1,11 @@ +use crate::*; +use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity}; +use frost_core::{Ciphersuite, Group, GroupError}; + +#[test] +fn check_deserialize_identity() { + let encoded_identity = RistrettoPoint::identity().compress().to_bytes(); + + let r = ::Group::deserialize(&encoded_identity); + assert_eq!(r, Err(GroupError::InvalidIdentityElement)); +} diff --git a/frost-ristretto255/tests/proptests.rs b/frost-ristretto255/src/tests/proptests.rs similarity index 97% rename from frost-ristretto255/tests/proptests.rs rename to frost-ristretto255/src/tests/proptests.rs index a92817a..c82dafe 100644 --- a/frost-ristretto255/tests/proptests.rs +++ b/frost-ristretto255/src/tests/proptests.rs @@ -1,5 +1,5 @@ +use crate::*; use frost_core::tests::proptests::{tweak_strategy, SignatureCase}; -use frost_ristretto255::*; use proptest::prelude::*; use rand_chacha::ChaChaRng; diff --git a/frost-ristretto255/tests/bincode.rs.bck b/frost-ristretto255/src/tests/proptests/bincode.rs.bck similarity index 100% rename from frost-ristretto255/tests/bincode.rs.bck rename to frost-ristretto255/src/tests/proptests/bincode.rs.bck diff --git a/frost-ristretto255/tests/proptests.proptest-regressions b/frost-ristretto255/src/tests/proptests/proptests.proptest-regressions similarity index 100% rename from frost-ristretto255/tests/proptests.proptest-regressions rename to frost-ristretto255/src/tests/proptests/proptests.proptest-regressions diff --git a/frost-ristretto255/src/tests/vss_commitment.rs b/frost-ristretto255/src/tests/vss_commitment.rs new file mode 100644 index 0000000..7375510 --- /dev/null +++ b/frost-ristretto255/src/tests/vss_commitment.rs @@ -0,0 +1,35 @@ +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +use crate::*; + +// Tests for serialization and deserialization VerifiableSecretSharingCommitment + +lazy_static! { + pub static ref ELEMENTS: Value = + serde_json::from_str(include_str!("../../tests/helpers/elements.json").trim()).unwrap(); +} + +#[test] +fn check_serialize_vss_commitment() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_serialize_vss_commitment::(rng); +} + +#[test] +fn check_deserialize_vss_commitment() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_deserialize_vss_commitment::( + rng, + ); +} + +#[test] +fn check_deserialize_vss_commitment_error() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_deserialize_vss_commitment_error::< + Ristretto255Sha512, + _, + >(rng, &ELEMENTS); +} diff --git a/frost-ristretto255/tests.rs b/frost-ristretto255/tests.rs new file mode 100644 index 0000000..633668f --- /dev/null +++ b/frost-ristretto255/tests.rs @@ -0,0 +1,2 @@ +#[cfg(test)] +mod integration_tests; \ No newline at end of file diff --git a/frost-ristretto255/tests/frost.rs b/frost-ristretto255/tests/frost.rs deleted file mode 100644 index 1e02ae9..0000000 --- a/frost-ristretto255/tests/frost.rs +++ /dev/null @@ -1,125 +0,0 @@ -use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity}; -use frost_core::{Ciphersuite, Group, GroupError}; -use frost_ristretto255::*; -use lazy_static::lazy_static; -use rand::thread_rng; -use serde_json::Value; - -#[test] -fn check_sign_with_dealer() { - let rng = thread_rng(); - - frost_core::tests::check_sign_with_dealer::(rng); -} - -#[test] -fn check_sign_with_dkg() { - let rng = thread_rng(); - - frost_core::tests::check_sign_with_dkg::(rng); -} - -#[test] -fn check_batch_verify() { - let rng = thread_rng(); - - frost_core::tests::batch::batch_verify::(rng); -} - -#[test] -fn check_bad_batch_verify() { - let rng = thread_rng(); - - frost_core::tests::batch::bad_batch_verify::(rng); -} - -#[test] -fn check_deserialize_identity() { - let encoded_identity = RistrettoPoint::identity().compress().to_bytes(); - - let r = ::Group::deserialize(&encoded_identity); - assert_eq!(r, Err(GroupError::InvalidIdentityElement)); -} - -lazy_static! { - pub static ref REPAIR_SHARE: Value = - serde_json::from_str(include_str!("repair-share.json").trim()).unwrap(); -} - -#[test] -fn check_repair_share_step_1() { - let rng = thread_rng(); - - frost_core::tests::repairable::check_repair_share_step_1::(rng); -} - -#[test] -fn check_repair_share_step_2() { - frost_core::tests::repairable::check_repair_share_step_2::(&REPAIR_SHARE); -} - -#[test] -fn check_repair_share_step_3() { - let rng = thread_rng(); - frost_core::tests::repairable::check_repair_share_step_3::( - rng, - &REPAIR_SHARE, - ); -} - -#[test] -fn check_rts() { - let rng = thread_rng(); - - frost_core::tests::repairable::check_rts::(rng); -} - -/// Tests for serialization and deserialization of CoefficientCommitment and VerifiableSecretSharingCommitment - -#[test] -fn check_serialization_of_coefficient_commitment() { - let rng = thread_rng(); - frost_core::tests::check_serialization_of_coefficient_commitment::(rng); -} - -#[test] -fn check_create_coefficient_commitment() { - let rng = thread_rng(); - frost_core::tests::check_create_coefficient_commitment::(rng); -} -#[test] -fn check_create_coefficient_commitment_error() { - frost_core::tests::check_create_coefficient_commitment_error::(&ELEMENTS); -} - -#[test] -fn check_get_value_of_coefficient_commitment() { - let rng = thread_rng(); - - frost_core::tests::check_get_value_of_coefficient_commitment::(rng); -} - -lazy_static! { - pub static ref ELEMENTS: Value = - serde_json::from_str(include_str!("elements.json").trim()).unwrap(); -} - -#[test] -fn check_serialize_vss_commitment() { - let rng = thread_rng(); - frost_core::tests::check_serialize_vss_commitment::(rng); -} - -#[test] -fn check_deserialize_vss_commitment() { - let rng = thread_rng(); - frost_core::tests::check_deserialize_vss_commitment::(rng); -} - -#[test] -fn check_deserialize_vss_commitment_error() { - let rng = thread_rng(); - frost_core::tests::check_deserialize_vss_commitment_error::( - rng, &ELEMENTS, - ); -} diff --git a/frost-ristretto255/tests/elements.json b/frost-ristretto255/tests/helpers/elements.json similarity index 100% rename from frost-ristretto255/tests/elements.json rename to frost-ristretto255/tests/helpers/elements.json diff --git a/frost-ristretto255/tests/repair-share.json b/frost-ristretto255/tests/helpers/repair-share.json similarity index 100% rename from frost-ristretto255/tests/repair-share.json rename to frost-ristretto255/tests/helpers/repair-share.json diff --git a/frost-ristretto255/src/tests/vectors-big-identifier.json b/frost-ristretto255/tests/helpers/vectors-big-identifier.json similarity index 100% rename from frost-ristretto255/src/tests/vectors-big-identifier.json rename to frost-ristretto255/tests/helpers/vectors-big-identifier.json diff --git a/frost-ristretto255/src/tests/vectors.json b/frost-ristretto255/tests/helpers/vectors.json similarity index 100% rename from frost-ristretto255/src/tests/vectors.json rename to frost-ristretto255/tests/helpers/vectors.json diff --git a/frost-ristretto255/tests/integration_tests.rs b/frost-ristretto255/tests/integration_tests.rs new file mode 100644 index 0000000..0d2e3b0 --- /dev/null +++ b/frost-ristretto255/tests/integration_tests.rs @@ -0,0 +1,50 @@ +use frost_ristretto255::*; +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +#[test] +fn check_sign_with_dkg() { + let rng = thread_rng(); + + frost_core::tests::ciphersuite_generic::check_sign_with_dkg::(rng); +} + +#[test] +fn check_rts() { + let rng = thread_rng(); + + frost_core::tests::repairable::check_rts::(rng); +} + +#[test] +fn check_sign_with_dealer() { + let rng = thread_rng(); + + frost_core::tests::ciphersuite_generic::check_sign_with_dealer::(rng); +} + +/// This is testing that Shamir's secret sharing to compute and arbitrary +/// value is working. +#[test] +fn check_share_generation_ristretto255_sha512() { + let rng = thread_rng(); + frost_core::tests::ciphersuite_generic::check_share_generation::(rng); +} + +lazy_static! { + pub static ref VECTORS: Value = + serde_json::from_str(include_str!("../tests/helpers/vectors.json").trim()) + .expect("Test vector is valid JSON"); + pub static ref VECTORS_BIG_IDENTIFIER: Value = + serde_json::from_str(include_str!("../tests/helpers/vectors-big-identifier.json").trim()) + .expect("Test vector is valid JSON"); +} + +#[test] +fn check_sign_with_test_vectors() { + frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS); + frost_core::tests::vectors::check_sign_with_test_vectors::( + &VECTORS_BIG_IDENTIFIER, + ); +} diff --git a/frost-secp256k1/src/keys/repairable.rs b/frost-secp256k1/src/keys/repairable.rs index de1db4d..badf2d7 100644 --- a/frost-secp256k1/src/keys/repairable.rs +++ b/frost-secp256k1/src/keys/repairable.rs @@ -53,3 +53,40 @@ pub fn repair_share_step_3( ) -> SecretShare { frost::keys::repairable::repair_share_step_3(sigmas, identifier, commitment) } + +#[cfg(test)] +mod tests { + + use lazy_static::lazy_static; + use rand::thread_rng; + use serde_json::Value; + + use crate::Secp256K1Sha256; + + lazy_static! { + pub static ref REPAIR_SHARE: Value = + serde_json::from_str(include_str!("../../tests/helpers/repair-share.json").trim()) + .unwrap(); + } + + #[test] + fn check_repair_share_step_1() { + let rng = thread_rng(); + + frost_core::tests::repairable::check_repair_share_step_1::(rng); + } + + #[test] + fn check_repair_share_step_2() { + frost_core::tests::repairable::check_repair_share_step_2::(&REPAIR_SHARE); + } + + #[test] + fn check_repair_share_step_3() { + let rng = thread_rng(); + frost_core::tests::repairable::check_repair_share_step_3::( + rng, + &REPAIR_SHARE, + ); + } +} diff --git a/frost-secp256k1/src/tests.rs b/frost-secp256k1/src/tests.rs index d3c13f1..15a3e18 100644 --- a/frost-secp256k1/src/tests.rs +++ b/frost-secp256k1/src/tests.rs @@ -1,29 +1,5 @@ -use lazy_static::lazy_static; -use rand::thread_rng; -use serde_json::Value; - -use crate::*; - -lazy_static! { - pub static ref VECTORS: Value = serde_json::from_str(include_str!("tests/vectors.json").trim()) - .expect("Test vector is valid JSON"); - pub static ref VECTORS_BIG_IDENTIFIER: Value = - serde_json::from_str(include_str!("tests/vectors-big-identifier.json").trim()) - .expect("Test vector is valid JSON"); -} - -/// This is testing that Shamir's secret sharing to compute and arbitrary -/// value is working. -#[test] -fn check_share_generation_secp256k1_sha256() { - let rng = thread_rng(); - frost_core::tests::check_share_generation::(rng); -} - -#[test] -fn check_sign_with_test_vectors() { - frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS); - frost_core::tests::vectors::check_sign_with_test_vectors::( - &VECTORS_BIG_IDENTIFIER, - ); -} +mod batch; +mod coefficient_commitment; +mod deserialize; +mod proptests; +mod vss_commitment; diff --git a/frost-secp256k1/src/tests/batch.rs b/frost-secp256k1/src/tests/batch.rs new file mode 100644 index 0000000..49357e0 --- /dev/null +++ b/frost-secp256k1/src/tests/batch.rs @@ -0,0 +1,17 @@ +use rand::thread_rng; + +use crate::*; + +#[test] +fn check_batch_verify() { + let rng = thread_rng(); + + frost_core::tests::batch::batch_verify::(rng); +} + +#[test] +fn check_bad_batch_verify() { + let rng = thread_rng(); + + frost_core::tests::batch::bad_batch_verify::(rng); +} diff --git a/frost-secp256k1/src/tests/coefficient_commitment.rs b/frost-secp256k1/src/tests/coefficient_commitment.rs new file mode 100644 index 0000000..d1b6c22 --- /dev/null +++ b/frost-secp256k1/src/tests/coefficient_commitment.rs @@ -0,0 +1,46 @@ +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +use crate::*; + +// Tests for serialization and deserialization of CoefficientCommitment + +lazy_static! { + pub static ref ELEMENTS: Value = + serde_json::from_str(include_str!("../../tests/helpers/elements.json").trim()).unwrap(); +} + +#[test] +fn check_serialization_of_coefficient_commitment() { + let rng = thread_rng(); + frost_core::tests::coefficient_commitment::check_serialization_of_coefficient_commitment::< + Secp256K1Sha256, + _, + >(rng); +} + +#[test] +fn check_create_coefficient_commitment() { + let rng = thread_rng(); + frost_core::tests::coefficient_commitment::check_create_coefficient_commitment::< + Secp256K1Sha256, + _, + >(rng); +} +#[test] +fn check_create_coefficient_commitment_error() { + frost_core::tests::coefficient_commitment::check_create_coefficient_commitment_error::< + Secp256K1Sha256, + >(&ELEMENTS); +} + +#[test] +fn check_get_value_of_coefficient_commitment() { + let rng = thread_rng(); + + frost_core::tests::coefficient_commitment::check_get_value_of_coefficient_commitment::< + Secp256K1Sha256, + _, + >(rng); +} diff --git a/frost-secp256k1/src/tests/deserialize.rs b/frost-secp256k1/src/tests/deserialize.rs new file mode 100644 index 0000000..bce8200 --- /dev/null +++ b/frost-secp256k1/src/tests/deserialize.rs @@ -0,0 +1,37 @@ +use crate::*; + +#[test] +fn check_deserialize_non_canonical() { + let mut encoded_generator = ::Group::serialize( + &::Group::generator(), + ); + + let r = ::Group::deserialize(&encoded_generator); + assert!(r.is_ok()); + + // The first byte should be 0x02 or 0x03. Set other value to + // create a non-canonical encoding. + encoded_generator[0] = 0xFF; + let r = ::Group::deserialize(&encoded_generator); + assert_eq!(r, Err(GroupError::MalformedElement)); + + // Besides the first byte, it is still possible to get non-canonical encodings. + // This is x = p + 2 which is non-canonical and maps to a valid prime-order point. + let encoded_point = + hex::decode("02fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc31") + .unwrap() + .try_into() + .unwrap(); + let r = ::Group::deserialize(&encoded_point); + assert_eq!(r, Err(GroupError::MalformedElement)); +} + +#[test] +fn check_deserialize_identity() { + // The identity is actually encoded as a single byte; but the API does not + // allow us to change that. Try to send something similar. + let encoded_identity = [0u8; 33]; + + let r = ::Group::deserialize(&encoded_identity); + assert_eq!(r, Err(GroupError::MalformedElement)); +} diff --git a/frost-secp256k1/tests/proptests.rs b/frost-secp256k1/src/tests/proptests.rs similarity index 97% rename from frost-secp256k1/tests/proptests.rs rename to frost-secp256k1/src/tests/proptests.rs index c280b91..dd59856 100644 --- a/frost-secp256k1/tests/proptests.rs +++ b/frost-secp256k1/src/tests/proptests.rs @@ -1,5 +1,5 @@ +use crate::*; use frost_core::tests::proptests::{tweak_strategy, SignatureCase}; -use frost_secp256k1::*; use proptest::prelude::*; use rand_chacha::ChaChaRng; diff --git a/frost-secp256k1/src/tests/vss_commitment.rs b/frost-secp256k1/src/tests/vss_commitment.rs new file mode 100644 index 0000000..1434d7c --- /dev/null +++ b/frost-secp256k1/src/tests/vss_commitment.rs @@ -0,0 +1,32 @@ +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +use crate::*; + +// Tests for serialization and deserialization VerifiableSecretSharingCommitment + +lazy_static! { + pub static ref ELEMENTS: Value = + serde_json::from_str(include_str!("../../tests/helpers/elements.json").trim()).unwrap(); +} + +#[test] +fn check_serialize_vss_commitment() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_serialize_vss_commitment::(rng); +} + +#[test] +fn check_deserialize_vss_commitment() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_deserialize_vss_commitment::(rng); +} + +#[test] +fn check_deserialize_vss_commitment_error() { + let rng = thread_rng(); + frost_core::tests::vss_commitment::check_deserialize_vss_commitment_error::( + rng, &ELEMENTS, + ); +} diff --git a/frost-secp256k1/tests/frost.rs b/frost-secp256k1/tests/frost.rs deleted file mode 100644 index 70494da..0000000 --- a/frost-secp256k1/tests/frost.rs +++ /dev/null @@ -1,149 +0,0 @@ -use frost_secp256k1::*; -use lazy_static::lazy_static; -use rand::thread_rng; -use serde_json::Value; - -#[test] -fn check_sign_with_dealer() { - let rng = thread_rng(); - - frost_core::tests::check_sign_with_dealer::(rng); -} - -#[test] -fn check_sign_with_dkg() { - let rng = thread_rng(); - - frost_core::tests::check_sign_with_dkg::(rng); -} - -#[test] -fn check_batch_verify() { - let rng = thread_rng(); - - frost_core::tests::batch::batch_verify::(rng); -} - -#[test] -fn check_bad_batch_verify() { - let rng = thread_rng(); - - frost_core::tests::batch::bad_batch_verify::(rng); -} - -#[test] -fn check_deserialize_identity() { - // The identity is actually encoded as a single byte; but the API does not - // allow us to change that. Try to send something similar. - let encoded_identity = [0u8; 33]; - - let r = ::Group::deserialize(&encoded_identity); - assert_eq!(r, Err(GroupError::MalformedElement)); -} - -#[test] -fn check_deserialize_non_canonical() { - let mut encoded_generator = ::Group::serialize( - &::Group::generator(), - ); - - let r = ::Group::deserialize(&encoded_generator); - assert!(r.is_ok()); - - // The first byte should be 0x02 or 0x03. Set other value to - // create a non-canonical encoding. - encoded_generator[0] = 0xFF; - let r = ::Group::deserialize(&encoded_generator); - assert_eq!(r, Err(GroupError::MalformedElement)); - - // Besides the first byte, it is still possible to get non-canonical encodings. - // This is x = p + 2 which is non-canonical and maps to a valid prime-order point. - let encoded_point = - hex::decode("02fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc31") - .unwrap() - .try_into() - .unwrap(); - let r = ::Group::deserialize(&encoded_point); - assert_eq!(r, Err(GroupError::MalformedElement)); -} - -#[test] -fn check_repair_share_step_1() { - let rng = thread_rng(); - - frost_core::tests::repairable::check_repair_share_step_1::(rng); -} - -lazy_static! { - pub static ref REPAIR_SHARE: Value = - serde_json::from_str(include_str!("repair-share.json").trim()).unwrap(); -} - -#[test] -fn check_repair_share_step_2() { - frost_core::tests::repairable::check_repair_share_step_2::(&REPAIR_SHARE); -} - -#[test] -fn check_repair_share() { - let rng = thread_rng(); - frost_core::tests::repairable::check_repair_share_step_3::( - rng, - &REPAIR_SHARE, - ); -} - -#[test] -fn check_rts() { - let rng = thread_rng(); - - frost_core::tests::repairable::check_rts::(rng); -} - -/// Tests for serialization and deserialization of CoefficientCommitment and VerifiableSecretSharingCommitment - -#[test] -fn check_serialization_of_coefficient_commitment() { - let rng = thread_rng(); - frost_core::tests::check_serialization_of_coefficient_commitment::(rng); -} - -#[test] -fn check_create_coefficient_commitment() { - let rng = thread_rng(); - frost_core::tests::check_create_coefficient_commitment::(rng); -} -#[test] -fn check_create_coefficient_commitment_error() { - frost_core::tests::check_create_coefficient_commitment_error::(&ELEMENTS); -} - -#[test] -fn check_get_value_of_coefficient_commitment() { - let rng = thread_rng(); - - frost_core::tests::check_get_value_of_coefficient_commitment::(rng); -} - -lazy_static! { - pub static ref ELEMENTS: Value = - serde_json::from_str(include_str!("elements.json").trim()).unwrap(); -} - -#[test] -fn check_serialize_vss_commitment() { - let rng = thread_rng(); - frost_core::tests::check_serialize_vss_commitment::(rng); -} - -#[test] -fn check_deserialize_vss_commitment() { - let rng = thread_rng(); - frost_core::tests::check_deserialize_vss_commitment::(rng); -} - -#[test] -fn check_deserialize_vss_commitment_error() { - let rng = thread_rng(); - frost_core::tests::check_deserialize_vss_commitment_error::(rng, &ELEMENTS); -} diff --git a/frost-secp256k1/tests/elements.json b/frost-secp256k1/tests/helpers/elements.json similarity index 100% rename from frost-secp256k1/tests/elements.json rename to frost-secp256k1/tests/helpers/elements.json diff --git a/frost-secp256k1/tests/repair-share.json b/frost-secp256k1/tests/helpers/repair-share.json similarity index 100% rename from frost-secp256k1/tests/repair-share.json rename to frost-secp256k1/tests/helpers/repair-share.json diff --git a/frost-secp256k1/src/tests/vectors-big-identifier.json b/frost-secp256k1/tests/helpers/vectors-big-identifier.json similarity index 100% rename from frost-secp256k1/src/tests/vectors-big-identifier.json rename to frost-secp256k1/tests/helpers/vectors-big-identifier.json diff --git a/frost-secp256k1/src/tests/vectors.json b/frost-secp256k1/tests/helpers/vectors.json similarity index 100% rename from frost-secp256k1/src/tests/vectors.json rename to frost-secp256k1/tests/helpers/vectors.json diff --git a/frost-secp256k1/tests/integration_tests.rs b/frost-secp256k1/tests/integration_tests.rs new file mode 100644 index 0000000..e9ecede --- /dev/null +++ b/frost-secp256k1/tests/integration_tests.rs @@ -0,0 +1,50 @@ +use frost_secp256k1::*; +use lazy_static::lazy_static; +use rand::thread_rng; +use serde_json::Value; + +#[test] +fn check_sign_with_dkg() { + let rng = thread_rng(); + + frost_core::tests::ciphersuite_generic::check_sign_with_dkg::(rng); +} + +#[test] +fn check_rts() { + let rng = thread_rng(); + + frost_core::tests::repairable::check_rts::(rng); +} + +#[test] +fn check_sign_with_dealer() { + let rng = thread_rng(); + + frost_core::tests::ciphersuite_generic::check_sign_with_dealer::(rng); +} + +/// This is testing that Shamir's secret sharing to compute and arbitrary +/// value is working. +#[test] +fn check_share_generation_secp256k1_sha256() { + let rng = thread_rng(); + frost_core::tests::ciphersuite_generic::check_share_generation::(rng); +} + +lazy_static! { + pub static ref VECTORS: Value = + serde_json::from_str(include_str!("../tests/helpers/vectors.json").trim()) + .expect("Test vector is valid JSON"); + pub static ref VECTORS_BIG_IDENTIFIER: Value = + serde_json::from_str(include_str!("../tests/helpers/vectors-big-identifier.json").trim()) + .expect("Test vector is valid JSON"); +} + +#[test] +fn check_sign_with_test_vectors() { + frost_core::tests::vectors::check_sign_with_test_vectors::(&VECTORS); + frost_core::tests::vectors::check_sign_with_test_vectors::( + &VECTORS_BIG_IDENTIFIER, + ); +} diff --git a/gencode/src/main.rs b/gencode/src/main.rs index c034aee..ac5f0d5 100644 --- a/gencode/src/main.rs +++ b/gencode/src/main.rs @@ -211,6 +211,7 @@ fn main() -> ExitCode { "Ristretto group", "Ristretto", "FROST(ristretto255, SHA-512)", + "ristretto255_sha512", "ristretto255", "", ]; @@ -228,6 +229,7 @@ fn main() -> ExitCode { "P-256 curve", "P256", "FROST(P-256, SHA-256)", + "p256_sha256", "p256", "

", ], @@ -239,6 +241,7 @@ fn main() -> ExitCode { "Ed25519 curve", "Ed25519", "FROST(Ed25519, SHA-512)", + "ed25519_sha512", "ed25519", "", ], @@ -250,6 +253,7 @@ fn main() -> ExitCode { "Ed448 curve", "Ed448", "FROST(Ed448, SHAKE256)", + "ed448_shake256", "ed448", "", ], @@ -261,6 +265,7 @@ fn main() -> ExitCode { "secp256k1 curve", "Secp256K1", "FROST(secp256k1, SHA-256)", + "secp256k1_sha256", "secp256k1", "", ],