From ba7fd182fa30c7a45de83c9380a6ba0636c732b8 Mon Sep 17 00:00:00 2001 From: Zhen Lu Date: Wed, 27 Nov 2024 17:30:39 -0800 Subject: [PATCH 1/5] Nested signing with Spark --- frost-core/src/lib.rs | 19 +++++++++++++++++++ frost-core/src/round2.rs | 9 ++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/frost-core/src/lib.rs b/frost-core/src/lib.rs index 76078d9..9c751b6 100644 --- a/frost-core/src/lib.rs +++ b/frost-core/src/lib.rs @@ -367,6 +367,10 @@ pub struct SigningPackage { /// The set of commitments participants published in the first round of the /// protocol. signing_commitments: BTreeMap, round1::SigningCommitments>, + + /// The set of participants that are signing. + signing_participants: Option>>, + /// Message which each participant will sign. /// /// Each signer should perform protocol-specific verification on the @@ -395,6 +399,21 @@ where SigningPackage { header: Header::default(), signing_commitments, + signing_participants: None, + message: message.to_vec(), + } + } + + /// Create a new `SigningPackage` with a set of signing participants. + pub fn new_with_participants( + signing_commitments: BTreeMap, round1::SigningCommitments>, + signing_participants: BTreeSet>, + message: &[u8], + ) -> SigningPackage { + SigningPackage { + header: Header::default(), + signing_commitments, + signing_participants: Some(signing_participants), message: message.to_vec(), } } diff --git a/frost-core/src/round2.rs b/frost-core/src/round2.rs index d3147db..554fcde 100644 --- a/frost-core/src/round2.rs +++ b/frost-core/src/round2.rs @@ -158,7 +158,14 @@ pub fn sign( let group_commitment = compute_group_commitment(&signing_package, &binding_factor_list)?; // Compute Lagrange coefficient. - let lambda_i = frost::derive_interpolating_value(key_package.identifier(), &signing_package)?; + let lambda_i = match signing_package.signing_participants.clone() { + Some(signing_participants) => frost::compute_lagrange_coefficient( + &signing_participants, + None, + *key_package.identifier(), + )?, + None => frost::derive_interpolating_value(key_package.identifier(), &signing_package)?, + }; // Compute the per-message challenge. let challenge = ::challenge( From 5459e1b2199950ae294cad4a1cd89857437ebb1b Mon Sep 17 00:00:00 2001 From: Zhen Lu Date: Wed, 22 Jan 2025 14:30:17 -0800 Subject: [PATCH 2/5] Make verify signature share work with different groups --- frost-core/src/lib.rs | 28 ++++++++++++++++++++++------ frost-core/src/round2.rs | 21 +++++++++++++++------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/frost-core/src/lib.rs b/frost-core/src/lib.rs index 9c751b6..d616d19 100644 --- a/frost-core/src/lib.rs +++ b/frost-core/src/lib.rs @@ -369,7 +369,7 @@ pub struct SigningPackage { signing_commitments: BTreeMap, round1::SigningCommitments>, /// The set of participants that are signing. - signing_participants: Option>>, + signing_participants_groups: Option>>>, /// Message which each participant will sign. /// @@ -399,21 +399,21 @@ where SigningPackage { header: Header::default(), signing_commitments, - signing_participants: None, + signing_participants_groups: None, message: message.to_vec(), } } /// Create a new `SigningPackage` with a set of signing participants. - pub fn new_with_participants( + pub fn new_with_participants_groups( signing_commitments: BTreeMap, round1::SigningCommitments>, - signing_participants: BTreeSet>, + signing_participants_groups: Vec>>, message: &[u8], ) -> SigningPackage { SigningPackage { header: Header::default(), signing_commitments, - signing_participants: Some(signing_participants), + signing_participants_groups: Some(signing_participants_groups), message: message.to_vec(), } } @@ -768,7 +768,23 @@ fn verify_signature_share_precomputed( verifying_share: &keys::VerifyingShare, challenge: Challenge, ) -> Result<(), Error> { - let lambda_i = derive_interpolating_value(&signature_share_identifier, signing_package)?; + let lambda_i = match signing_package.signing_participants_groups.clone() { + Some(signing_participants_groups) => { + let mut result: Result, Error> = Err(Error::UnknownIdentifier); + for signing_participants_group in signing_participants_groups { + if signing_participants_group.contains(&signature_share_identifier) { + result = compute_lagrange_coefficient( + &signing_participants_group, + None, + signature_share_identifier, + ); + break; + } + } + result? + } + None => derive_interpolating_value(&signature_share_identifier, signing_package)?, + }; let binding_factor = binding_factor_list .get(&signature_share_identifier) diff --git a/frost-core/src/round2.rs b/frost-core/src/round2.rs index 554fcde..9d819a6 100644 --- a/frost-core/src/round2.rs +++ b/frost-core/src/round2.rs @@ -158,12 +158,21 @@ pub fn sign( let group_commitment = compute_group_commitment(&signing_package, &binding_factor_list)?; // Compute Lagrange coefficient. - let lambda_i = match signing_package.signing_participants.clone() { - Some(signing_participants) => frost::compute_lagrange_coefficient( - &signing_participants, - None, - *key_package.identifier(), - )?, + let lambda_i = match signing_package.signing_participants_groups.clone() { + Some(signing_participants_groups) => { + let mut result: Result, Error> = Err(Error::UnknownIdentifier); + for signing_participants_group in signing_participants_groups { + if signing_participants_group.contains(&key_package.identifier()) { + result = frost::compute_lagrange_coefficient( + &signing_participants_group, + None, + *key_package.identifier(), + ); + break; + } + } + result? + } None => frost::derive_interpolating_value(key_package.identifier(), &signing_package)?, }; From f5a336bea9e6bc253794fa4f801add7b46a7ce69 Mon Sep 17 00:00:00 2001 From: Zhen Lu Date: Wed, 22 Jan 2025 14:38:46 -0800 Subject: [PATCH 3/5] Make verify_signature_share available in frost-secp256k1-tr --- frost-secp256k1-tr/src/lib.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/frost-secp256k1-tr/src/lib.rs b/frost-secp256k1-tr/src/lib.rs index f566f72..fa93d84 100644 --- a/frost-secp256k1-tr/src/lib.rs +++ b/frost-secp256k1-tr/src/lib.rs @@ -912,3 +912,20 @@ pub type SigningKey = frost_core::SigningKey; /// A valid verifying key for Schnorr signatures on FROST(secp256k1, SHA-256). pub type VerifyingKey = frost_core::VerifyingKey; + +/// Verifies a signature share for the given participant `identifier`, +pub fn verify_signature_share( + identifier: Identifier, + verifying_share: &keys::VerifyingShare, + signature_share: &round2::SignatureShare, + signing_package: &SigningPackage, + verifying_key: &VerifyingKey, +) -> Result<(), Error> { + frost_core::verify_signature_share( + identifier, + verifying_share, + signature_share, + signing_package, + verifying_key, + ) +} From 78d37dad6f024c4b3e2bfb01afcc96179fd43d13 Mon Sep 17 00:00:00 2001 From: Zhen Lu Date: Fri, 24 Jan 2025 17:05:15 -0800 Subject: [PATCH 4/5] Add adaptor signature for signing --- frost-core/src/lib.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/frost-core/src/lib.rs b/frost-core/src/lib.rs index d616d19..b009824 100644 --- a/frost-core/src/lib.rs +++ b/frost-core/src/lib.rs @@ -383,6 +383,9 @@ pub struct SigningPackage { ) )] message: Vec, + + /// The adaptor for the signing operation. + adaptor: Option>, } impl SigningPackage @@ -401,6 +404,7 @@ where signing_commitments, signing_participants_groups: None, message: message.to_vec(), + adaptor: None, } } @@ -415,6 +419,23 @@ where signing_commitments, signing_participants_groups: Some(signing_participants_groups), message: message.to_vec(), + adaptor: None, + } + } + + /// Create a new `SigningPackage` with a set of signing participants and an adaptor. + pub fn new_with_adaptor( + signing_commitments: BTreeMap, round1::SigningCommitments>, + signing_participants_groups: Vec>>, + message: &[u8], + adaptor: VerifyingKey, + ) -> SigningPackage { + SigningPackage { + header: Header::default(), + signing_commitments, + signing_participants_groups: Some(signing_participants_groups), + message: message.to_vec(), + adaptor: Some(adaptor), } } @@ -555,6 +576,10 @@ where group_commitment = group_commitment + accumulated_binding_commitment; + if let Some(adaptor) = signing_package.adaptor { + group_commitment = group_commitment + adaptor.to_element(); + } + Ok(GroupCommitment(group_commitment)) } @@ -630,6 +655,11 @@ where z, }; + if signing_package.adaptor.is_some() { + // If there is an adaptor, we skip the verification step. + return Ok(signature); + } + // Verify the aggregate signature let verification_result = pubkeys .verifying_key From 9aaf1b6b9fa3c2c3c2c7c70da83061deda1a9180 Mon Sep 17 00:00:00 2001 From: Zhen Lu Date: Fri, 24 Jan 2025 20:10:29 -0800 Subject: [PATCH 5/5] Make the params optional --- frost-core/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frost-core/src/lib.rs b/frost-core/src/lib.rs index b009824..4727545 100644 --- a/frost-core/src/lib.rs +++ b/frost-core/src/lib.rs @@ -411,13 +411,13 @@ where /// Create a new `SigningPackage` with a set of signing participants. pub fn new_with_participants_groups( signing_commitments: BTreeMap, round1::SigningCommitments>, - signing_participants_groups: Vec>>, + signing_participants_groups: Option>>>, message: &[u8], ) -> SigningPackage { SigningPackage { header: Header::default(), signing_commitments, - signing_participants_groups: Some(signing_participants_groups), + signing_participants_groups: signing_participants_groups, message: message.to_vec(), adaptor: None, } @@ -426,16 +426,16 @@ where /// Create a new `SigningPackage` with a set of signing participants and an adaptor. pub fn new_with_adaptor( signing_commitments: BTreeMap, round1::SigningCommitments>, - signing_participants_groups: Vec>>, + signing_participants_groups: Option>>>, message: &[u8], - adaptor: VerifyingKey, + adaptor: Option>, ) -> SigningPackage { SigningPackage { header: Header::default(), signing_commitments, - signing_participants_groups: Some(signing_participants_groups), + signing_participants_groups: signing_participants_groups, message: message.to_vec(), - adaptor: Some(adaptor), + adaptor: adaptor, } }