From 1153fee4ef68d042f46885aac2aee5ed4077b69f 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 364beab..62bb36c 100644 --- a/frost-core/src/lib.rs +++ b/frost-core/src/lib.rs @@ -365,6 +365,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 @@ -393,6 +397,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 b7a1e90..2b1aec1 100644 --- a/frost-core/src/round2.rs +++ b/frost-core/src/round2.rs @@ -160,7 +160,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 d81445c15c5c72d0e7c74da3d1c9b67aad83e1c2 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 62bb36c..9f0f4eb 100644 --- a/frost-core/src/lib.rs +++ b/frost-core/src/lib.rs @@ -367,7 +367,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. /// @@ -397,21 +397,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(), } } @@ -844,7 +844,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 2b1aec1..cfdfef2 100644 --- a/frost-core/src/round2.rs +++ b/frost-core/src/round2.rs @@ -160,12 +160,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 2180ca440a05b64fa5a718cbe35b759240d1330b 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 daa1960..8a1b596 100644 --- a/frost-secp256k1-tr/src/lib.rs +++ b/frost-secp256k1-tr/src/lib.rs @@ -915,3 +915,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 924fe21874ad794a5c390b1e7a432457054822b2 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 9f0f4eb..6604b35 100644 --- a/frost-core/src/lib.rs +++ b/frost-core/src/lib.rs @@ -381,6 +381,9 @@ pub struct SigningPackage { ) )] message: Vec, + + /// The adaptor for the signing operation. + adaptor: Option>, } impl SigningPackage @@ -399,6 +402,7 @@ where signing_commitments, signing_participants_groups: None, message: message.to_vec(), + adaptor: None, } } @@ -413,6 +417,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), } } @@ -553,6 +574,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)) } @@ -675,6 +700,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 20585f111a1702eaa0fe10601fca10c5d3e7a1f4 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 6604b35..fe6d581 100644 --- a/frost-core/src/lib.rs +++ b/frost-core/src/lib.rs @@ -409,13 +409,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, } @@ -424,16 +424,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, } }