Skip to content

Commit 2198d9d

Browse files
committed
Use prop args for randomness, and schnorr for pop
1 parent 23774c1 commit 2198d9d

File tree

1 file changed

+138
-141
lines changed

1 file changed

+138
-141
lines changed

Diff for: schnorr_fun/src/frost.rs

+138-141
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ impl<Z> PointPoly<Z> {
174174
#[derive(Clone, Debug)]
175175
pub struct KeyGen {
176176
point_polys: Vec<PointPoly>,
177-
keygen_id: Point<EvenY>,
177+
keygen_id: Scalar,
178178
frost_key: FrostKey,
179179
}
180180

@@ -310,7 +310,7 @@ impl FrostKey {
310310
}
311311
}
312312

313-
impl<H: Digest<OutputSize = U32> + Clone, NG: AddTag> Frost<H, NG> {
313+
impl<H: Digest<OutputSize = U32> + Clone, NG: AddTag + NonceGen> Frost<H, NG> {
314314
/// Create secret shares and our proof-of-possession to be shared with other participants.
315315
///
316316
/// Secret shares are created for every other participant by evaluating our secret polynomial
@@ -322,31 +322,23 @@ impl<H: Digest<OutputSize = U32> + Clone, NG: AddTag> Frost<H, NG> {
322322
///
323323
/// ## Return value
324324
///
325-
/// Returns a vector of secret shares and a proof of possession, as a tupple.
325+
/// Returns a vector of secret shares and a proof of possession Signature
326326
/// The secret shares at index 0 is destined for participant 1.
327327
pub fn create_shares(
328328
&self,
329329
KeyGen: &KeyGen,
330330
scalar_poly: ScalarPoly,
331-
rng: &mut (impl RngCore + CryptoRng),
332-
) -> (Vec<Scalar<Secret, Zero>>, (Point, Scalar<Secret, Zero>)) {
333-
// Create proof of possession
334-
let pop_r = Scalar::random(rng);
335-
let pop_R = g!(pop_r * G).normalize();
336-
let pop_c = Scalar::from_hash(
337-
self.keygen_id_hash
338-
.clone()
339-
.add(g!({ scalar_poly.0[0].clone() } * G).normalize())
340-
.add(KeyGen.keygen_id)
341-
.add(pop_R),
342-
);
343-
let pop_z = s!(pop_c + pop_r);
331+
) -> (Vec<Scalar<Secret, Zero>>, Signature) {
332+
let key_pair = self.schnorr.new_keypair(scalar_poly.0[0].clone());
333+
let pop = self
334+
.schnorr
335+
.sign(&key_pair, Message::<Public>::plain("frost-pop", b""));
344336

345337
let shares = (1..=KeyGen.point_polys.len())
346338
.map(|i| scalar_poly.eval(i as u32))
347339
.collect();
348340

349-
(shares, (pop_R, pop_z))
341+
(shares, pop)
350342
}
351343
}
352344

@@ -356,22 +348,14 @@ impl<H: Digest<OutputSize = U32> + Clone, NG: AddTag> Frost<H, NG> {
356348
/// ## Return value
357349
///
358350
/// Returns `bool` true if the proof of possession matches this point poly,
359-
fn verify_pop(
360-
&self,
361-
keygen_id: Point<secp256kfun::marker::EvenY>,
362-
point_poly: &PointPoly,
363-
pop: (Point, Scalar<Secret, Zero>),
364-
) -> bool {
365-
let first_point = point_poly.0[0];
366-
let (pop_R, pop_z) = pop;
367-
let pop_c = Scalar::from_hash(
368-
self.keygen_id_hash
369-
.clone()
370-
.add(first_point)
371-
.add(keygen_id)
372-
.add(pop_R),
373-
);
374-
!g!(pop_R + pop_c * first_point - pop_z * G).is_zero()
351+
fn verify_pop(&self, point_poly: &PointPoly, pop: Signature) -> bool {
352+
let (even_poly_point, _) = point_poly.0[0].into_point_with_even_y();
353+
354+
self.schnorr.verify(
355+
&even_poly_point,
356+
Message::<Public>::plain("frost-pop", b""),
357+
&pop,
358+
)
375359
}
376360
}
377361

@@ -411,7 +395,7 @@ impl<H: Digest<OutputSize = U32> + Clone, NG: AddTag> Frost<H, NG> {
411395
.into_point_with_even_y();
412396

413397
// TODO set keygen id
414-
let keygen_id = joint_public_key;
398+
let keygen_id = Scalar::from_hash(self.keygen_id_hash.clone().add(joint_public_key));
415399

416400
let verification_shares = (1..=point_polys.len())
417401
.map(|i| joint_poly.eval(i as u32).normalize().mark::<NonZero>())
@@ -447,20 +431,21 @@ impl<H: Digest<OutputSize = U32> + Clone, NG: AddTag> Frost<H, NG> {
447431
KeyGen: KeyGen,
448432
my_index: u32,
449433
secret_shares: Vec<Scalar<Secret, Zero>>,
450-
proofs_of_possession: Vec<(Point, Scalar<Secret, Zero>)>,
434+
proofs_of_possession: Vec<Signature>,
451435
) -> Result<(Scalar, FrostKey), FinishKeyGenError> {
452436
assert_eq!(
453437
secret_shares.len(),
454438
KeyGen.frost_key.verification_shares.len()
455439
);
440+
assert_eq!(secret_shares.len(), proofs_of_possession.len());
456441

457442
for (i, (poly, pop)) in KeyGen
458443
.point_polys
459444
.iter()
460445
.zip(proofs_of_possession)
461446
.enumerate()
462447
{
463-
if !self.verify_pop(KeyGen.keygen_id, poly, pop) {
448+
if !self.verify_pop(poly, pop) {
464449
return Err(FinishKeyGenError::InvalidProofOfPossession(i));
465450
}
466451
}
@@ -711,30 +696,11 @@ impl<H: Digest<OutputSize = U32> + Clone, NG: NonceGen + AddTag> Frost<H, NG> {
711696
}
712697
}
713698

714-
/// Allows getting the FrostKey
715-
// TODO seal this trait
716-
pub trait GetFrostKey {
717-
/// Get Frost key
718-
fn get_frost_key(&self) -> &FrostKey;
719-
}
720-
721-
impl GetFrostKey for KeyGen {
722-
fn get_frost_key(&self) -> &FrostKey {
723-
&self.frost_key
724-
}
725-
}
726-
727-
impl GetFrostKey for FrostKey {
728-
fn get_frost_key(&self) -> &FrostKey {
729-
&self
730-
}
731-
}
732-
733699
#[cfg(test)]
734700
mod test {
701+
use core::num::NonZeroU32;
702+
735703
use super::*;
736-
use rand::{prelude::IteratorRandom, Rng};
737-
// proptest::prelude::*};
738704
use secp256kfun::{
739705
nonce::Deterministic,
740706
proptest::{arbitrary::any, proptest},
@@ -743,95 +709,124 @@ mod test {
743709

744710
proptest! {
745711
#[test]
746-
fn frost_prop_test(n_parties in 3u32..8, something in any::<u32>()) {
747-
let mut rng = rand::thread_rng();
748-
let threshold = rng.gen_range(2..=n_parties);
712+
fn frost_prop_test(n_parties in 3u32..8, threshold in 3u32..8, signers_mask_seed in any::<u32>(), tweak1 in any::<Scalar<Public, Zero>>(), tweak2 in any::<Scalar<Public, Zero>>(), use_tweak2 in any::<bool>()) {
713+
// Two tweaks
749714
let frost = Frost::new(Schnorr::<Sha256, Deterministic<Sha256>>::new(
750715
Deterministic::<Sha256>::default(),
751716
));
752717
dbg!(threshold, n_parties);
753-
754-
let scalar_polys: Vec<ScalarPoly> = (0..n_parties).map(|_| ScalarPoly::random(threshold, &mut rng)).collect();
755-
let point_polys: Vec<PointPoly> = scalar_polys.iter().map(|sp| sp.to_point_poly()).collect();
756-
757-
let KeyGen = frost.new_keygen(point_polys).unwrap();
758-
759-
let mut proofs_of_possession= vec![];
760-
let mut shares_vec = vec![];
761-
for sp in scalar_polys {
762-
let (shares, pop) = frost.create_shares(&KeyGen, sp, &mut rng);
763-
proofs_of_possession.push(pop);
764-
shares_vec.push(shares);
765-
}
766-
767-
// let recieved_shares = signer_indexes.iter().zip(signer_indexes).map(|(i, j)| (i,j)).collect();
768-
let mut recieved_shares: Vec<Vec<_>> = vec![];
769-
for party_index in 0..n_parties {
770-
recieved_shares.push(vec![]);
771-
for share_index in 0..n_parties {
772-
recieved_shares[party_index as usize].push(shares_vec[share_index as usize][party_index as usize].clone());
718+
if n_parties < threshold {
719+
dbg!("too few parties for this threshold");
720+
} else {
721+
// create some scalar poly for each party
722+
let mut scalar_polys = vec![];
723+
for i in 1..=n_parties {
724+
let scalar_poly = (1..=threshold).map(|j| Scalar::from_non_zero_u32(NonZeroU32::new(i*j).expect("starts from 1"))).collect();
725+
scalar_polys.push(ScalarPoly::new(scalar_poly));
773726
}
774-
}
727+
let point_polys: Vec<PointPoly> = scalar_polys.iter().map(|sp| sp.to_point_poly()).collect();
775728

776-
let (secret_shares, frost_keys): (Vec<Scalar>, Vec<FrostKey>) = (0..n_parties).map(|i| {
777-
let (secret_share, frost) = frost.finish_keygen(
778-
KeyGen.clone(),
779-
i,
780-
recieved_shares[i as usize].clone(),
781-
proofs_of_possession.clone(),
782-
)
783-
.unwrap();
784-
(secret_share, frost)
785-
}).unzip();
786-
787-
788-
// Signing coalition of t to n parties
789-
let n_signers = if threshold == n_parties {
790-
threshold
791-
} else {
792-
rng.gen_range(threshold..=n_parties)
793-
};
794-
let signer_indexes = (0..n_parties).choose_multiple(&mut rng, n_signers as usize);
729+
let KeyGen = frost.new_keygen(point_polys).unwrap();
795730

796-
let sid = frost_keys[0].joint_public_key.to_bytes();
731+
let mut proofs_of_possession= vec![];
732+
let mut shares_vec = vec![];
733+
for sp in scalar_polys {
734+
let (shares, pop) = frost.create_shares(&KeyGen, sp);
735+
proofs_of_possession.push(pop);
736+
shares_vec.push(shares);
737+
}
797738

798-
let nonces: Vec<NonceKeyPair> = signer_indexes.iter().map(|i| frost.gen_nonce(&secret_shares[*i as usize], &sid)).collect();
739+
// collect the recieved shares for each party
740+
let mut recieved_shares: Vec<Vec<_>> = vec![];
741+
for party_index in 0..n_parties {
742+
recieved_shares.push(vec![]);
743+
for share_index in 0..n_parties {
744+
recieved_shares[party_index as usize].push(shares_vec[share_index as usize][party_index as usize].clone());
745+
}
746+
}
799747

800-
let mut recieved_nonces: Vec<_> = vec![];
801-
for (i, nonce) in signer_indexes.iter().zip(nonces.clone()) {
802-
recieved_nonces.push((*i, nonce.public()));
803-
}
748+
// finish keygen for each party
749+
let (secret_shares, frost_keys): (Vec<Scalar>, Vec<FrostKey>) = (0..n_parties).map(|i| {
750+
let (secret_share, mut frost_key) = frost.finish_keygen(
751+
KeyGen.clone(),
752+
i,
753+
recieved_shares[i as usize].clone(),
754+
proofs_of_possession.clone(),
755+
)
756+
.unwrap();
757+
frost_key = frost_key.tweak(tweak1.clone()).expect("applying tweak1");
758+
frost_key = if use_tweak2 {
759+
frost_key.tweak(tweak2.clone()).expect("applying tweak2")
760+
} else {
761+
frost_key
762+
};
763+
(secret_share, frost_key)
764+
}).unzip();
765+
766+
// create a mask of signers
767+
// use bytes from random u32 to determine whether a party is a signer or not
768+
let mut signers_mask = vec![true];
769+
while signers_mask.len() < n_parties as usize {
770+
for v in signers_mask_seed.to_be_bytes() {
771+
if v > 128 {
772+
signers_mask.push(true);
773+
} else {
774+
signers_mask.push(false);
775+
}
776+
if signers_mask.len() >= n_parties as usize {
777+
break
778+
}
779+
}
780+
}
781+
let mut signer_indexes = vec![];
782+
for (index, included) in signers_mask.iter().enumerate() {
783+
if *included {
784+
signer_indexes.push(index);
785+
}
786+
}
787+
dbg!(&signer_indexes);
788+
789+
if signer_indexes.len() < threshold as usize {
790+
dbg!("less signers than threshold.. skipping");
791+
} else {
792+
let sid = frost_keys[0].joint_public_key.to_bytes();
793+
let nonces: Vec<NonceKeyPair> = signer_indexes.iter().map(|i| frost.gen_nonce(&secret_shares[*i as usize], &sid)).collect();
794+
// dbg!(&nonces);
795+
796+
let mut recieved_nonces: Vec<_> = vec![];
797+
for (i, nonce) in signer_indexes.iter().zip(nonces.clone()) {
798+
recieved_nonces.push((*i as u32, nonce.public()));
799+
}
800+
801+
// Create Frost signing session
802+
let mut signatures = vec![];
803+
for i in 0..signer_indexes.len() {
804+
let signer_index = signer_indexes[i] as usize;
805+
let session = frost.start_sign_session(&frost_keys[signer_index], recieved_nonces.clone(), Message::plain("test", b"test"));
806+
dbg!(nonces[i].clone());
807+
let sig = frost.sign(&frost_keys[signer_index], &session, signer_index as u32, &secret_shares[signer_index], nonces[i].clone());
808+
assert!(frost.verify_signature_share(&frost_keys[signer_index], &session, signer_index as u32, sig));
809+
signatures.push(sig);
810+
}
811+
812+
// TODO get this session from loop above
813+
// assert same and use one
814+
let session = frost.start_sign_session(&frost_keys[signer_indexes[0] as usize], recieved_nonces.clone(), Message::plain("test", b"test"));
815+
let combined_sig = frost.combine_signature_shares(&frost_keys[signer_indexes[0] as usize], &session, signatures);
816+
817+
assert!(frost.schnorr.verify(
818+
&frost_keys[signer_indexes[0] as usize].joint_public_key,
819+
Message::<Public>::plain("test", b"test"),
820+
&combined_sig
821+
));
804822

805-
dbg!(recieved_nonces.clone());
806-
807-
// Create Frost signing session
808-
let mut signatures = vec![];
809-
for i in 0..signer_indexes.len() {
810-
let signer_index = signer_indexes[i] as usize;
811-
let session = frost.start_sign_session(&frost_keys[signer_index], recieved_nonces.clone(), Message::plain("test", b"test"));
812-
dbg!(nonces[i].clone());
813-
let sig = frost.sign(&frost_keys[signer_index], &session, signer_index as u32, &secret_shares[signer_index], nonces[i].clone());
814-
assert!(frost.verify_signature_share(&frost_keys[signer_index], &session, signer_index as u32, sig));
815-
signatures.push(sig);
823+
}
816824
}
817-
818-
// TODO get this session from loop above
819-
let session = frost.start_sign_session(&frost_keys[signer_indexes[0] as usize], recieved_nonces.clone(), Message::plain("test", b"test"));
820-
let combined_sig = frost.combine_signature_shares(&frost_keys[signer_indexes[0] as usize], &session, signatures);
821-
822-
assert!(frost.schnorr.verify(
823-
&frost_keys[signer_indexes[0] as usize].joint_public_key,
824-
Message::<Public>::plain("test", b"test"),
825-
&combined_sig
826-
));
827-
828-
829825
}
830826
}
831827

832828
#[test]
833829
fn frost_test_end_to_end() {
834-
let mut rng = rand::thread_rng();
835830
// Create a secret polynomial for each participant
836831
let sp1 = ScalarPoly::new(vec![s!(3), s!(7)]);
837832
let sp2 = ScalarPoly::new(vec![s!(11), s!(13)]);
@@ -847,9 +842,9 @@ mod test {
847842
];
848843

849844
let KeyGen = frost.new_keygen(point_polys).unwrap();
850-
let (shares1, pop1) = frost.create_shares(&KeyGen, sp1, &mut rng);
851-
let (shares2, pop2) = frost.create_shares(&KeyGen, sp2, &mut rng);
852-
let (shares3, pop3) = frost.create_shares(&KeyGen, sp3, &mut rng);
845+
let (shares1, pop1) = frost.create_shares(&KeyGen, sp1);
846+
let (shares2, pop2) = frost.create_shares(&KeyGen, sp2);
847+
let (shares3, pop3) = frost.create_shares(&KeyGen, sp3);
853848
let proofs_of_possession = vec![pop1, pop2, pop3];
854849

855850
let (secret_share1, mut frost_key) = frost
@@ -881,18 +876,20 @@ mod test {
881876
assert_eq!(frost_key, jk3);
882877

883878
let use_tweak = true;
884-
if use_tweak {
885-
let tweak = Scalar::from_bytes([
879+
let tweak = if use_tweak {
880+
Scalar::from_bytes([
886881
0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A,
887882
0x72, 0x3D, 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, 0x80, 0x2B, 0x26, 0x3C,
888883
0xDF, 0xCD, 0x83, 0xBB,
889884
])
890-
.unwrap();
891-
// let tweak = Scalar::zero();
892-
frost_key = frost_key.tweak(tweak.clone()).expect("tweak worked");
893-
jk2 = jk2.tweak(tweak.clone()).expect("tweak worked");
894-
jk3 = jk3.tweak(tweak).expect("tweak worked");
895-
}
885+
.unwrap()
886+
} else {
887+
Scalar::zero()
888+
};
889+
890+
frost_key = frost_key.tweak(tweak.clone()).expect("tweak worked");
891+
jk2 = jk2.tweak(tweak.clone()).expect("tweak worked");
892+
jk3 = jk3.tweak(tweak).expect("tweak worked");
896893

897894
// TODO USE PROPER SID
898895
// public => [ b"r2-frost", my_index.to_be_bytes(), frost_key.joint_public_key, &frost_key.verification_shares[..], sid]

0 commit comments

Comments
 (0)