Skip to content

Commit 802de7a

Browse files
committed
tweak DKG output to avoid rogue taproot tweaks
1 parent d69a59d commit 802de7a

File tree

4 files changed

+87
-19
lines changed

4 files changed

+87
-19
lines changed

frost-core/src/keys/dkg.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -562,16 +562,12 @@ pub fn part3<C: Ciphersuite>(
562562
&round2_secret_package.commitment,
563563
)))
564564
.collect();
565-
let public_key_package = PublicKeyPackage::from_dkg_commitments(&commitments)?;
566565

567-
let key_package = KeyPackage {
568-
header: Header::default(),
569-
identifier: round2_secret_package.identifier,
566+
C::dkg_output_finalize(
567+
round2_secret_package.identifier,
568+
commitments,
570569
signing_share,
571570
verifying_share,
572-
verifying_key: public_key_package.verifying_key,
573-
min_signers: round2_secret_package.min_signers,
574-
};
575-
576-
Ok((key_package, public_key_package))
571+
round2_secret_package.min_signers,
572+
)
577573
}

frost-core/src/traits.rs

+34-3
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@ use core::{
55
ops::{Add, Mul, Sub},
66
};
77

8-
use alloc::vec::Vec;
8+
use alloc::{collections::BTreeMap, vec::Vec};
99
use rand_core::{CryptoRng, RngCore};
1010

1111
use crate::{
1212
challenge,
13-
keys::{KeyPackage, VerifyingShare},
13+
keys::{
14+
KeyPackage, PublicKeyPackage, SigningShare, VerifiableSecretSharingCommitment,
15+
VerifyingShare,
16+
},
1417
round1, round2, BindingFactor, Challenge, Error, FieldError, GroupCommitment, GroupError,
15-
Signature, SigningTarget, VerifyingKey,
18+
Header, Identifier, Signature, SigningTarget, VerifyingKey,
1619
};
1720

1821
/// A prime order finite field GF(q) over which all scalar values for our prime order group can be
@@ -447,4 +450,32 @@ pub trait Ciphersuite: Copy + Clone + PartialEq + Debug + 'static {
447450
) -> <Self::Group as Group>::Element {
448451
verifying_share.to_element()
449452
}
453+
454+
/// Construct the key packages from the output of a successful DKG execution.
455+
/// The signing share and verifying share have already been verified and the
456+
/// identifier belongs to our signer.
457+
///
458+
/// In frost-sepc256k1-tr, this adds a hash-based tweak to the group key
459+
/// to prevent peers from inserting rogue tapscript tweaks into the group's
460+
/// joint public key.
461+
fn dkg_output_finalize(
462+
identifier: Identifier<Self>,
463+
commitments: BTreeMap<Identifier<Self>, &VerifiableSecretSharingCommitment<Self>>,
464+
signing_share: SigningShare<Self>,
465+
verifying_share: VerifyingShare<Self>,
466+
min_signers: u16,
467+
) -> Result<(KeyPackage<Self>, PublicKeyPackage<Self>), Error<Self>> {
468+
let public_key_package = PublicKeyPackage::from_dkg_commitments(&commitments)?;
469+
470+
let key_package = KeyPackage {
471+
header: Header::default(),
472+
identifier,
473+
signing_share,
474+
verifying_share,
475+
verifying_key: public_key_package.verifying_key,
476+
min_signers,
477+
};
478+
479+
Ok((key_package, public_key_package))
480+
}
450481
}

frost-secp256k1-tr/src/lib.rs

+41
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,47 @@ impl Ciphersuite for Secp256K1Sha256 {
545545
vs
546546
}
547547
}
548+
549+
/// We add an unusable taproot tweak to the group key computed by a DKG run,
550+
/// to prevent peers from inserting rogue tapscript tweaks into the group's
551+
/// joint public key.
552+
fn dkg_output_finalize(
553+
identifier: Identifier,
554+
commitments: BTreeMap<Identifier, &keys::VerifiableSecretSharingCommitment>,
555+
signing_share: keys::SigningShare,
556+
verifying_share: keys::VerifyingShare,
557+
min_signers: u16,
558+
) -> Result<(keys::KeyPackage, keys::PublicKeyPackage), Error> {
559+
let untweaked_public_key_package =
560+
keys::PublicKeyPackage::from_dkg_commitments(&commitments)?;
561+
562+
let untweaked_vk = untweaked_public_key_package.verifying_key().to_element();
563+
let t = tweak(&untweaked_vk, Some(vec![])); // unspendable script path
564+
let tG = ProjectivePoint::GENERATOR * t;
565+
566+
let tweaked_verifying_shares: BTreeMap<Identifier, keys::VerifyingShare> =
567+
untweaked_public_key_package
568+
.verifying_shares()
569+
.clone()
570+
.into_iter()
571+
.map(|(id, share)| (id, keys::VerifyingShare::new(share.to_element() + tG)))
572+
.collect();
573+
574+
let tweaked_verifying_key = VerifyingKey::new(untweaked_vk + tG);
575+
576+
let key_package = keys::KeyPackage::new(
577+
identifier,
578+
keys::SigningShare::new(signing_share.to_scalar() + t),
579+
keys::VerifyingShare::new(verifying_share.to_element() + tG),
580+
tweaked_verifying_key,
581+
min_signers,
582+
);
583+
584+
let public_key_package =
585+
keys::PublicKeyPackage::new(tweaked_verifying_shares, tweaked_verifying_key);
586+
587+
Ok((key_package, public_key_package))
588+
}
548589
}
549590

550591
impl RandomizedCiphersuite for Secp256K1Sha256 {

frost-secp256k1-tr/tests/helpers/vectors_dkg.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"hash": "SHA-256"
88
},
99
"inputs": {
10-
"verifying_key": "034a48daffc43b47b42695611942c481aecffb9137686ad0b3e0ab8e1f1dab0293",
10+
"verifying_key": "02409611d2fd36025b75caa15f1d70f6d5cfea9cc4254d29580075fdf832d934db",
1111
"1": {
1212
"identifier": 1,
1313
"signing_key": "68e3f6904c6043973515a36bf7801a71597da35733f21305d75a5234f06e4529",
@@ -18,8 +18,8 @@
1818
"2": "1dd3cb3e2370e6af22917415f0ad584514807b58b3cc40d2230a26e115f02771",
1919
"3": "dd25ee86acd01f996618aa0d1153f5e8fbc929a8e8a18b8f0a15f91d087217e2"
2020
},
21-
"verifying_share": "03e2eada7cdb20ec24babb687eb633580c977148c70254700f1ad4a931316dc6d9",
22-
"signing_share": "89b08895c083bb6a00de882d0e6ff2a20a1878b5e8c0c5aba5983100e3c45d0c"
21+
"verifying_share": "03487e21b8658bffc7903fa2f6435bdae7a417990a27698c273a14f72bece665f3",
22+
"signing_share": "051f56860fd1225af141494c573ce33da026e1c5f8c5099b73c9ad28675a8389"
2323
},
2424
"2": {
2525
"identifier": 2,
@@ -31,8 +31,8 @@
3131
"1": "b489a711942526abbb5330a8215d2e740f7dbddec3452006993a8cea3ac278cb",
3232
"3": "20255dc07b1fb78bdf90bd85fd2389c988c8250faee11826656a09142fa9fc97"
3333
},
34-
"verifying_share": "0312705f7560a146760034ebdd103277e184ce81d2ba6a67a43f0b3f39410cc396",
35-
"signing_share": "ea3cdccc32746d918c2910295b0a03dfa1c94f01d20f860c6fe8c22fb6c0d831"
34+
"verifying_share": "02aab83a9c57284041ae6add2d5e2ea43d715c6607e03c4c22ca5aae10086076f4",
35+
"signing_share": "65abaabc81c1d4827c8bd148a3d6f47b37d7b811e213c9fc3e1a3e573a56feae"
3636
},
3737
"3": {
3838
"identifier": 3,
@@ -44,8 +44,8 @@
4444
"1": "da5c7f5238079835fe71f746364bb8756a7dcb228aeea686fa2aaa44dfec929c",
4545
"2": "0d47e4b622ee3804bff8cfe088653efefe865cce0c065aecbf7e318182b89e2d"
4646
},
47-
"verifying_share": "036607b45621ce6840d999980c9c74d69a15fa5a246e852ee2ca6924ce65fa299b",
48-
"signing_share": "4ac93102a4651fb917739825a7a4151e7ecb48670c15a6317a66f4d1b9871215"
47+
"verifying_share": "031f1571625e54d9bb0e58e228abe5430460ab9d414bced42250fd09526476290b",
48+
"signing_share": "c637fef2f3b286aa07d65944f07105b8cf888e5dcb628a5d086acf860d5379d3"
4949
}
5050
}
5151
}

0 commit comments

Comments
 (0)