wsts/
net.rs

1use rand_core::{CryptoRng, RngCore};
2use std::fmt::Debug;
3
4use hashbrown::{HashMap, HashSet};
5use serde::{Deserialize, Serialize};
6use sha2::{Digest, Sha256};
7use tracing::warn;
8
9use crate::{
10    common::{MerkleRoot, PolyCommitment, PublicNonce, SignatureShare, TupleProof},
11    curve::{
12        ecdsa,
13        point::{Point, G},
14        scalar::Scalar,
15    },
16    schnorr,
17    state_machine::PublicKeys,
18    util::hash_to_scalar,
19};
20
21/// Trait to encapsulate sign/verify, users only need to impl hash
22pub trait Signable {
23    /// Hash this object in a consistent way so it can be signed/verified
24    fn hash(&self, hasher: &mut Sha256);
25
26    /// Sign a hash of this object using the passed private key
27    fn sign(&self, private_key: &Scalar) -> Result<Vec<u8>, ecdsa::Error> {
28        let mut hasher = Sha256::new();
29
30        self.hash(&mut hasher);
31
32        let hash = hasher.finalize();
33        match ecdsa::Signature::new(hash.as_slice(), private_key) {
34            Ok(sig) => Ok(sig.to_bytes().to_vec()),
35            Err(e) => Err(e),
36        }
37    }
38
39    /// Verify a hash of this object using the passed public key
40    fn verify(&self, signature: &[u8], public_key: &ecdsa::PublicKey) -> bool {
41        let mut hasher = Sha256::new();
42
43        self.hash(&mut hasher);
44
45        let hash = hasher.finalize();
46        let sig = match ecdsa::Signature::try_from(signature) {
47            Ok(sig) => sig,
48            Err(_) => return false,
49        };
50
51        sig.verify(hash.as_slice(), public_key)
52    }
53}
54
55#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
56/// A bad private share
57pub struct BadPrivateShare {
58    /// the DH shared key between these participants
59    pub shared_key: Point,
60    /// prooof that the shared key is a valid DH tuple as per chaum-pedersen
61    pub tuple_proof: TupleProof,
62}
63
64#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
65/// Final DKG status after receiving public and private shares
66pub enum DkgFailure {
67    /// DKG threshold not met
68    Threshold,
69    /// Signer was in the wrong internal state to complete DKG
70    BadState,
71    /// DKG public shares were missing from these signer_ids
72    MissingPublicShares(HashSet<u32>),
73    /// DKG public shares were bad from these signer_ids
74    BadPublicShares(HashSet<u32>),
75    /// DKG private shares were missing from these signer_ids
76    MissingPrivateShares(HashSet<u32>),
77    /// DKG private shares were bad from these signer_ids
78    BadPrivateShares(HashMap<u32, BadPrivateShare>),
79}
80
81#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
82/// Final DKG status after receiving public and private shares
83pub enum DkgStatus {
84    /// DKG completed successfully
85    Success,
86    /// DKG failed
87    Failure(DkgFailure),
88}
89
90#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
91#[allow(clippy::large_enum_variant)]
92/// Encapsulation of all possible network message types
93pub enum Message {
94    /// Tell signers to begin DKG by sending DKG public shares
95    DkgBegin(DkgBegin),
96    /// Send DKG public shares
97    DkgPublicShares(DkgPublicShares),
98    /// Tell signers to send DKG private shares
99    DkgPrivateBegin(DkgPrivateBegin),
100    /// Send DKG private shares
101    DkgPrivateShares(DkgPrivateShares),
102    /// Tell signers to compute shares and send DKG end
103    DkgEndBegin(DkgEndBegin),
104    /// Tell coordinator that DKG is complete
105    DkgEnd(DkgEnd),
106    /// Tell signers to send signing nonces
107    NonceRequest(NonceRequest),
108    /// Tell coordinator signing nonces
109    NonceResponse(NonceResponse),
110    /// Tell signers to construct signature shares
111    SignatureShareRequest(SignatureShareRequest),
112    /// Tell coordinator signature shares
113    SignatureShareResponse(SignatureShareResponse),
114}
115
116impl Signable for Message {
117    fn hash(&self, hasher: &mut Sha256) {
118        match self {
119            Message::DkgBegin(msg) => msg.hash(hasher),
120            Message::DkgPublicShares(msg) => msg.hash(hasher),
121            Message::DkgPrivateBegin(msg) => msg.hash(hasher),
122            Message::DkgPrivateShares(msg) => msg.hash(hasher),
123            Message::DkgEndBegin(msg) => msg.hash(hasher),
124            Message::DkgEnd(msg) => msg.hash(hasher),
125            Message::NonceRequest(msg) => msg.hash(hasher),
126            Message::NonceResponse(msg) => msg.hash(hasher),
127            Message::SignatureShareRequest(msg) => msg.hash(hasher),
128            Message::SignatureShareResponse(msg) => msg.hash(hasher),
129        }
130    }
131}
132
133#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
134/// DKG begin message from coordinator to signers
135pub struct DkgBegin {
136    /// DKG round ID
137    pub dkg_id: u64,
138}
139
140impl Signable for DkgBegin {
141    fn hash(&self, hasher: &mut Sha256) {
142        hasher.update("DKG_BEGIN".as_bytes());
143        hasher.update(self.dkg_id.to_be_bytes());
144    }
145}
146
147#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
148/// DKG public shares message from signer to all signers and coordinator
149pub struct DkgPublicShares {
150    /// DKG round ID
151    pub dkg_id: u64,
152    /// Signer ID
153    pub signer_id: u32,
154    /// List of (party_id, commitment)
155    pub comms: Vec<(u32, PolyCommitment)>,
156    /// Ephemeral public key for key exchange
157    pub kex_public_key: Point,
158    /// Proof of knowledge of kex_private_key
159    pub kex_proof: schnorr::Proof,
160}
161
162#[allow(non_snake_case)]
163impl DkgPublicShares {
164    /// construct a proof of knowledge of kex_private_key
165    pub fn kex_prove<RNG: RngCore + CryptoRng>(
166        dkg_id: u64,
167        signer_id: u32,
168        comms: &Vec<(u32, PolyCommitment)>,
169        kex_private_key: &Scalar,
170        rng: &mut RNG,
171    ) -> schnorr::Proof {
172        let r = Scalar::random(rng);
173        let R = r * G;
174        let kex_public_key = kex_private_key * G;
175        let c = Self::kex_challenge(&R, dkg_id, signer_id, comms, &kex_public_key);
176        let s = r + c * kex_private_key;
177
178        schnorr::Proof { R, s }
179    }
180
181    /// verify a proof of knowledge of kex_private_key
182    pub fn kex_verify(&self) -> bool {
183        let c = Self::kex_challenge(
184            &self.kex_proof.R,
185            self.dkg_id,
186            self.signer_id,
187            &self.comms,
188            &self.kex_public_key,
189        );
190        &self.kex_proof.s * &G == &self.kex_proof.R + c * &self.kex_public_key
191    }
192
193    /// construct a proof of knowledge of kex_private_key
194    pub fn kex_challenge(
195        R: &Point,
196        dkg_id: u64,
197        signer_id: u32,
198        comms: &Vec<(u32, PolyCommitment)>,
199        kex_public_key: &Point,
200    ) -> Scalar {
201        let mut hasher = Sha256::new();
202        let tag = "WSTS/DKG_PUBLIC_SHARES/KEX_SCHNORR_PROOF";
203
204        hasher.update(tag.as_bytes());
205        hasher.update(R.compress().as_bytes());
206        hasher.update(dkg_id.to_be_bytes());
207        hasher.update(signer_id.to_be_bytes());
208        hasher.update(kex_public_key.compress().as_bytes());
209        for (party_id, comm) in comms {
210            hasher.update(party_id.to_be_bytes());
211            for a in &comm.poly {
212                hasher.update(a.compress().as_bytes());
213            }
214        }
215
216        hash_to_scalar(&mut hasher)
217    }
218}
219
220impl Signable for DkgPublicShares {
221    fn hash(&self, hasher: &mut Sha256) {
222        hasher.update("DKG_PUBLIC_SHARES".as_bytes());
223        hasher.update(self.dkg_id.to_be_bytes());
224        hasher.update(self.signer_id.to_be_bytes());
225        hasher.update(self.kex_public_key.compress().as_bytes());
226        hasher.update(self.kex_proof.R.compress().as_bytes());
227        hasher.update(self.kex_proof.s.to_bytes());
228        for (party_id, comm) in &self.comms {
229            hasher.update(party_id.to_be_bytes());
230            for a in &comm.poly {
231                hasher.update(a.compress().as_bytes());
232            }
233        }
234    }
235}
236
237#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
238/// DKG private begin message from signer to all signers and coordinator
239pub struct DkgPrivateBegin {
240    /// DKG round ID
241    pub dkg_id: u64,
242    /// Signer IDs who responded in time for this DKG round
243    pub signer_ids: Vec<u32>,
244    /// Key IDs who responded in time for this DKG round
245    pub key_ids: Vec<u32>,
246}
247
248impl Signable for DkgPrivateBegin {
249    fn hash(&self, hasher: &mut Sha256) {
250        hasher.update("DKG_PRIVATE_BEGIN".as_bytes());
251        hasher.update(self.dkg_id.to_be_bytes());
252        for key_id in &self.key_ids {
253            hasher.update(key_id.to_be_bytes());
254        }
255        for signer_id in &self.signer_ids {
256            hasher.update(signer_id.to_be_bytes());
257        }
258    }
259}
260
261#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
262/// DKG private shares message from signer to all signers and coordinator
263pub struct DkgPrivateShares {
264    /// DKG round ID
265    pub dkg_id: u64,
266    /// Signer ID
267    pub signer_id: u32,
268    /// List of (src_party_id, Map(dst_key_id, encrypted_share))
269    pub shares: Vec<(u32, HashMap<u32, Vec<u8>>)>,
270}
271
272impl Signable for DkgPrivateShares {
273    fn hash(&self, hasher: &mut Sha256) {
274        hasher.update("DKG_PRIVATE_SHARES".as_bytes());
275        hasher.update(self.dkg_id.to_be_bytes());
276        hasher.update(self.signer_id.to_be_bytes());
277        // make sure we hash consistently by sorting the keys
278        for (src_id, share) in &self.shares {
279            hasher.update(src_id.to_be_bytes());
280            let mut dst_ids = share.keys().cloned().collect::<Vec<u32>>();
281            dst_ids.sort();
282            for dst_id in &dst_ids {
283                hasher.update(dst_id.to_be_bytes());
284                hasher.update(&share[dst_id]);
285            }
286        }
287    }
288}
289
290#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
291/// DKG end begin message from signer to all signers and coordinator
292pub struct DkgEndBegin {
293    /// DKG round ID
294    pub dkg_id: u64,
295    /// Signer IDs who responded in time for this DKG round
296    pub signer_ids: Vec<u32>,
297    /// Key IDs who responded in time for this DKG round
298    pub key_ids: Vec<u32>,
299}
300
301impl Signable for DkgEndBegin {
302    fn hash(&self, hasher: &mut Sha256) {
303        hasher.update("DKG_END_BEGIN".as_bytes());
304        hasher.update(self.dkg_id.to_be_bytes());
305        for key_id in &self.key_ids {
306            hasher.update(key_id.to_be_bytes());
307        }
308        for signer_id in &self.signer_ids {
309            hasher.update(signer_id.to_be_bytes());
310        }
311    }
312}
313
314#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
315/// DKG end message from signers to coordinator
316pub struct DkgEnd {
317    /// DKG round ID
318    pub dkg_id: u64,
319    /// Signer ID
320    pub signer_id: u32,
321    /// DKG status for this Signer after receiving public/private shares
322    pub status: DkgStatus,
323}
324
325impl Signable for DkgEnd {
326    fn hash(&self, hasher: &mut Sha256) {
327        hasher.update("DKG_END".as_bytes());
328        hasher.update(self.dkg_id.to_be_bytes());
329        hasher.update(self.signer_id.to_be_bytes());
330    }
331}
332
333#[derive(Clone, Serialize, Deserialize, PartialEq)]
334/// Nonce request message from coordinator to signers
335pub struct NonceRequest {
336    /// DKG round ID
337    pub dkg_id: u64,
338    /// Signing round ID
339    pub sign_id: u64,
340    /// Signing round iteration ID
341    pub sign_iter_id: u64,
342    /// The message to sign
343    pub message: Vec<u8>,
344    /// What type of signature to create
345    pub signature_type: SignatureType,
346}
347
348impl Debug for NonceRequest {
349    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
350        f.debug_struct("NonceRequest")
351            .field("dkg_id", &self.dkg_id)
352            .field("sign_id", &self.sign_id)
353            .field("sign_iter_id", &self.sign_iter_id)
354            .field("message", &hex::encode(&self.message))
355            .field("signature_type", &self.signature_type)
356            .finish()
357    }
358}
359
360impl Signable for NonceRequest {
361    fn hash(&self, hasher: &mut Sha256) {
362        hasher.update("NONCE_REQUEST".as_bytes());
363        hasher.update(self.dkg_id.to_be_bytes());
364        hasher.update(self.sign_id.to_be_bytes());
365        hasher.update(self.sign_iter_id.to_be_bytes());
366        hasher.update(self.message.as_slice());
367        match self.signature_type {
368            SignatureType::Frost => hasher.update("SIGNATURE_TYPE_FROST".as_bytes()),
369            SignatureType::Schnorr => hasher.update("SIGNATURE_TYPE_SCHNORR".as_bytes()),
370            SignatureType::Taproot(merkle_root) => {
371                hasher.update("SIGNATURE_TYPE_TAPROOT".as_bytes());
372                if let Some(merkle_root) = merkle_root {
373                    hasher.update(merkle_root);
374                }
375            }
376        }
377    }
378}
379
380#[derive(Clone, Serialize, Deserialize, PartialEq)]
381/// Nonce response message from signers to coordinator
382pub struct NonceResponse {
383    /// DKG round ID
384    pub dkg_id: u64,
385    /// Signing round ID
386    pub sign_id: u64,
387    /// Signing round iteration ID
388    pub sign_iter_id: u64,
389    /// Signer ID
390    pub signer_id: u32,
391    /// Key IDs
392    pub key_ids: Vec<u32>,
393    /// Public nonces
394    pub nonces: Vec<PublicNonce>,
395    /// Bytes being signed
396    pub message: Vec<u8>,
397}
398
399impl Debug for NonceResponse {
400    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
401        f.debug_struct("NonceResponse")
402            .field("dkg_id", &self.dkg_id)
403            .field("sign_id", &self.sign_id)
404            .field("sign_iter_id", &self.sign_iter_id)
405            .field("signer_id", &self.signer_id)
406            .field("key_ids", &self.key_ids)
407            .field(
408                "nonces",
409                &self
410                    .nonces
411                    .iter()
412                    .map(|x| x.to_string())
413                    .collect::<Vec<_>>(),
414            )
415            .field("message", &hex::encode(&self.message))
416            .finish()
417    }
418}
419
420impl Signable for NonceResponse {
421    fn hash(&self, hasher: &mut Sha256) {
422        hasher.update("NONCE_RESPONSE".as_bytes());
423        hasher.update(self.dkg_id.to_be_bytes());
424        hasher.update(self.sign_id.to_be_bytes());
425        hasher.update(self.sign_iter_id.to_be_bytes());
426        hasher.update(self.signer_id.to_be_bytes());
427
428        for key_id in &self.key_ids {
429            hasher.update(key_id.to_be_bytes());
430        }
431
432        for nonce in &self.nonces {
433            hasher.update(nonce.D.compress().as_bytes());
434            hasher.update(nonce.E.compress().as_bytes());
435        }
436
437        hasher.update(self.message.as_slice());
438    }
439}
440
441#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq)]
442/// Signature type
443pub enum SignatureType {
444    /// FROST signature
445    Frost,
446    /// BIP-340 Schnorr proof
447    Schnorr,
448    /// BIP-341 Taproot style schnorr proof with a merkle root
449    Taproot(Option<MerkleRoot>),
450}
451
452#[derive(Clone, Serialize, Deserialize, PartialEq)]
453/// Signature share request message from coordinator to signers
454pub struct SignatureShareRequest {
455    /// DKG round ID
456    pub dkg_id: u64,
457    /// Signing round ID
458    pub sign_id: u64,
459    /// Signing round iteration ID
460    pub sign_iter_id: u64,
461    /// Nonces responses used for this signature
462    pub nonce_responses: Vec<NonceResponse>,
463    /// Bytes to sign
464    pub message: Vec<u8>,
465    /// What type of signature to create
466    pub signature_type: SignatureType,
467}
468
469impl Debug for SignatureShareRequest {
470    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
471        f.debug_struct("SignatureShareRequest")
472            .field("dkg_id", &self.dkg_id)
473            .field("sign_id", &self.sign_id)
474            .field("sign_iter_id", &self.sign_iter_id)
475            .field("nonce_responses", &self.nonce_responses)
476            .field("message", &hex::encode(&self.message))
477            .field("signature_type", &self.signature_type)
478            .finish()
479    }
480}
481
482impl Signable for SignatureShareRequest {
483    fn hash(&self, hasher: &mut Sha256) {
484        hasher.update("SIGNATURE_SHARE_REQUEST".as_bytes());
485        hasher.update(self.dkg_id.to_be_bytes());
486        hasher.update(self.sign_id.to_be_bytes());
487
488        for nonce_response in &self.nonce_responses {
489            nonce_response.hash(hasher);
490        }
491
492        hasher.update(self.message.as_slice());
493        match self.signature_type {
494            SignatureType::Frost => hasher.update("SIGNATURE_TYPE_FROST".as_bytes()),
495            SignatureType::Schnorr => hasher.update("SIGNATURE_TYPE_SCHNORR".as_bytes()),
496            SignatureType::Taproot(merkle_root) => {
497                hasher.update("SIGNATURE_TYPE_TAPROOT".as_bytes());
498                if let Some(merkle_root) = merkle_root {
499                    hasher.update(merkle_root);
500                }
501            }
502        }
503    }
504}
505
506#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
507/// Signature share response message from signers to coordinator
508pub struct SignatureShareResponse {
509    /// DKG round ID
510    pub dkg_id: u64,
511    /// Signing round ID
512    pub sign_id: u64,
513    /// Signing round iteration ID
514    pub sign_iter_id: u64,
515    /// Signer ID
516    pub signer_id: u32,
517    /// Signature shares from this Signer
518    pub signature_shares: Vec<SignatureShare>,
519}
520
521impl Signable for SignatureShareResponse {
522    fn hash(&self, hasher: &mut Sha256) {
523        hasher.update("SIGNATURE_SHARE_RESPONSE".as_bytes());
524        hasher.update(self.dkg_id.to_be_bytes());
525        hasher.update(self.sign_id.to_be_bytes());
526        hasher.update(self.signer_id.to_be_bytes());
527
528        for signature_share in &self.signature_shares {
529            hasher.update(signature_share.id.to_be_bytes());
530            hasher.update(signature_share.z_i.to_bytes());
531            for key_id in &signature_share.key_ids {
532                hasher.update(key_id.to_be_bytes());
533            }
534        }
535    }
536}
537
538#[derive(Serialize, Deserialize, Clone, PartialEq)]
539/// Network packets need to be signed so they can be verified
540pub struct Packet {
541    /// The message to sign
542    pub msg: Message,
543    /// The bytes of the signature
544    pub sig: Vec<u8>,
545}
546
547impl Debug for Packet {
548    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
549        f.debug_struct("Packet")
550            .field("msg", &self.msg)
551            .field("sig", &hex::encode(&self.sig))
552            .finish()
553    }
554}
555
556impl Packet {
557    /// This function verifies the packet's signature, returning true if the signature is valid,
558    /// i.e. is appropriately signed by either the provided coordinator or one of the provided signer public keys
559    pub fn verify(
560        &self,
561        signers_public_keys: &PublicKeys,
562        coordinator_public_key: &ecdsa::PublicKey,
563    ) -> bool {
564        match &self.msg {
565            Message::DkgBegin(msg) => {
566                if !msg.verify(&self.sig, coordinator_public_key) {
567                    warn!("Received a DkgBegin message with an invalid signature.");
568                    return false;
569                }
570            }
571            Message::DkgPrivateBegin(msg) => {
572                if !msg.verify(&self.sig, coordinator_public_key) {
573                    warn!("Received a DkgPrivateBegin message with an invalid signature.");
574                    return false;
575                }
576            }
577            Message::DkgEndBegin(msg) => {
578                if !msg.verify(&self.sig, coordinator_public_key) {
579                    warn!("Received a DkgEndBegin message with an invalid signature.");
580                    return false;
581                }
582            }
583            Message::DkgEnd(msg) => {
584                if let Some(public_key) = signers_public_keys.signers.get(&msg.signer_id) {
585                    if !msg.verify(&self.sig, public_key) {
586                        warn!("Received a DkgPublicEnd message with an invalid signature.");
587                        return false;
588                    }
589                } else {
590                    warn!(
591                        "Received a DkgPublicEnd message with an unknown id: {}",
592                        msg.signer_id
593                    );
594                    return false;
595                }
596            }
597            Message::DkgPublicShares(msg) => {
598                if let Some(public_key) = signers_public_keys.signers.get(&msg.signer_id) {
599                    if !msg.verify(&self.sig, public_key) {
600                        warn!("Received a DkgPublicShares message with an invalid signature.");
601                        return false;
602                    }
603                } else {
604                    warn!(
605                        "Received a DkgPublicShares message with an unknown id: {}",
606                        msg.signer_id
607                    );
608                    return false;
609                }
610            }
611            Message::DkgPrivateShares(msg) => {
612                // Private shares have key IDs from [0, N) to reference IDs from [1, N]
613                // in Frost V4 to enable easy indexing hence ID + 1
614                // TODO: Once Frost V5 is released, this off by one adjustment will no longer be required
615                if let Some(public_key) = signers_public_keys.signers.get(&msg.signer_id) {
616                    if !msg.verify(&self.sig, public_key) {
617                        warn!("Received a DkgPrivateShares message with an invalid signature from signer_id {} key {}", msg.signer_id, &public_key);
618                        return false;
619                    }
620                } else {
621                    warn!(
622                        "Received a DkgPrivateShares message with an unknown id: {}",
623                        msg.signer_id
624                    );
625                    return false;
626                }
627            }
628            Message::NonceRequest(msg) => {
629                if !msg.verify(&self.sig, coordinator_public_key) {
630                    warn!("Received a NonceRequest message with an invalid signature.");
631                    return false;
632                }
633            }
634            Message::NonceResponse(msg) => {
635                if let Some(public_key) = signers_public_keys.signers.get(&msg.signer_id) {
636                    if !msg.verify(&self.sig, public_key) {
637                        warn!("Received a NonceResponse message with an invalid signature.");
638                        return false;
639                    }
640                } else {
641                    warn!(
642                        "Received a NonceResponse message with an unknown id: {}",
643                        msg.signer_id
644                    );
645                    return false;
646                }
647            }
648            Message::SignatureShareRequest(msg) => {
649                if !msg.verify(&self.sig, coordinator_public_key) {
650                    warn!("Received a SignatureShareRequest message with an invalid signature.");
651                    return false;
652                }
653            }
654            Message::SignatureShareResponse(msg) => {
655                if let Some(public_key) = signers_public_keys.signers.get(&msg.signer_id) {
656                    if !msg.verify(&self.sig, public_key) {
657                        warn!(
658                            "Received a SignatureShareResponse message with an invalid signature."
659                        );
660                        return false;
661                    }
662                } else {
663                    warn!(
664                        "Received a SignatureShareResponse message with an unknown id: {}",
665                        msg.signer_id
666                    );
667                    return false;
668                }
669            }
670        }
671        true
672    }
673}
674
675#[cfg(test)]
676mod test {
677    use super::*;
678    use crate::schnorr::ID;
679    use crate::util::create_rng;
680    use rand_core::{CryptoRng, RngCore};
681
682    #[derive(Clone, Debug)]
683    #[allow(dead_code)]
684    pub struct TestConfig {
685        pub coordinator_private_key: Scalar,
686        pub coordinator_public_key: ecdsa::PublicKey,
687        pub signer_private_key: Scalar,
688        pub signer_public_key: ecdsa::PublicKey,
689        pub public_keys: PublicKeys,
690    }
691
692    impl TestConfig {
693        pub fn new<RNG: RngCore + CryptoRng>(rng: &mut RNG) -> Self {
694            let coordinator_private_key = Scalar::random(rng);
695            let coordinator_public_key = ecdsa::PublicKey::new(&coordinator_private_key).unwrap();
696            let signer_private_key = Scalar::random(rng);
697            let signer_public_key = ecdsa::PublicKey::new(&signer_private_key).unwrap();
698
699            let mut signer_ids_map = HashMap::new();
700            let mut signer_key_ids = HashMap::new();
701            let mut key_ids_map = HashMap::new();
702            let mut key_ids_set = HashSet::new();
703            signer_ids_map.insert(0, signer_public_key);
704            key_ids_map.insert(1, signer_public_key);
705            key_ids_set.insert(1);
706            signer_key_ids.insert(0, key_ids_set);
707
708            let public_keys = PublicKeys {
709                signers: signer_ids_map,
710                key_ids: key_ids_map,
711                signer_key_ids,
712            };
713
714            Self {
715                coordinator_private_key,
716                coordinator_public_key,
717                signer_private_key,
718                signer_public_key,
719                public_keys,
720            }
721        }
722    }
723
724    impl Default for TestConfig {
725        fn default() -> Self {
726            let mut rng = create_rng();
727            Self::new(&mut rng)
728        }
729    }
730
731    #[test]
732    fn dkg_begin_verify_msg() {
733        let test_config = TestConfig::default();
734        let dkg_begin = DkgBegin { dkg_id: 0 };
735        let dkg_private_begin = DkgPrivateBegin {
736            dkg_id: 0,
737            key_ids: Default::default(),
738            signer_ids: Default::default(),
739        };
740        let msg = Message::DkgBegin(dkg_begin.clone());
741        let coordinator_packet_dkg_begin = Packet {
742            sig: dkg_begin
743                .sign(&test_config.coordinator_private_key)
744                .expect("Failed to sign"),
745            msg: msg.clone(),
746        };
747        let signer_packet_dkg_begin = Packet {
748            sig: dkg_begin
749                .sign(&test_config.signer_private_key)
750                .expect("Failed to sign"),
751            msg,
752        };
753
754        assert!(coordinator_packet_dkg_begin.verify(
755            &test_config.public_keys,
756            &test_config.coordinator_public_key
757        ));
758        assert!(!signer_packet_dkg_begin.verify(
759            &test_config.public_keys,
760            &test_config.coordinator_public_key
761        ));
762
763        let msg = Message::DkgPrivateBegin(dkg_private_begin.clone());
764        let coordinator_packet_dkg_private_begin = Packet {
765            sig: dkg_private_begin
766                .sign(&test_config.coordinator_private_key)
767                .expect("Failed to sign"),
768            msg: msg.clone(),
769        };
770        let signer_packet_dkg_private_begin = Packet {
771            sig: dkg_private_begin
772                .sign(&test_config.signer_private_key)
773                .expect("Failed to sign"),
774            msg,
775        };
776
777        assert!(coordinator_packet_dkg_private_begin.verify(
778            &test_config.public_keys,
779            &test_config.coordinator_public_key
780        ));
781        assert!(!signer_packet_dkg_private_begin.verify(
782            &test_config.public_keys,
783            &test_config.coordinator_public_key
784        ));
785    }
786
787    #[test]
788    fn dkg_public_shares_verify_msg() {
789        let ctx = 0u64.to_be_bytes();
790        let mut rng = create_rng();
791        let test_config = TestConfig::default();
792        let public_shares = DkgPublicShares {
793            dkg_id: 0,
794            signer_id: 0,
795            comms: vec![(
796                0,
797                PolyCommitment {
798                    id: ID::new(&Scalar::new(), &Scalar::new(), &ctx, &mut rng),
799                    poly: vec![],
800                },
801            )],
802            kex_public_key: Point::from(Scalar::random(&mut rng)),
803            kex_proof: schnorr::Proof {
804                R: Point::new(),
805                s: Scalar::new(),
806            },
807        };
808        let msg = Message::DkgPublicShares(public_shares.clone());
809        let coordinator_packet_dkg_public_shares = Packet {
810            sig: public_shares
811                .sign(&test_config.coordinator_private_key)
812                .expect("Failed to sign"),
813            msg: msg.clone(),
814        };
815        let signer_packet_dkg_public_shares = Packet {
816            sig: public_shares
817                .sign(&test_config.signer_private_key)
818                .expect("Failed to sign"),
819            msg,
820        };
821
822        assert!(!coordinator_packet_dkg_public_shares.verify(
823            &test_config.public_keys,
824            &test_config.coordinator_public_key
825        ));
826        assert!(signer_packet_dkg_public_shares.verify(
827            &test_config.public_keys,
828            &test_config.coordinator_public_key
829        ));
830
831        // change the kex_public_key but keep the previous signature
832        let mitm_signer_packet_dkg_public_shares = Packet {
833            sig: signer_packet_dkg_public_shares.sig,
834            msg: Message::DkgPublicShares(DkgPublicShares {
835                kex_public_key: Point::from(Scalar::random(&mut rng)),
836                ..public_shares
837            }),
838        };
839        // packet should no longer verify
840        assert!(!mitm_signer_packet_dkg_public_shares.verify(
841            &test_config.public_keys,
842            &test_config.coordinator_public_key
843        ));
844    }
845
846    #[test]
847    fn dkg_private_shares_verify_msg() {
848        let test_config = TestConfig::default();
849        let private_shares = DkgPrivateShares {
850            dkg_id: 0,
851            signer_id: 0,
852            shares: vec![(0, HashMap::new())],
853        };
854        let msg = Message::DkgPrivateShares(private_shares.clone());
855        let coordinator_packet_dkg_private_shares = Packet {
856            sig: private_shares
857                .sign(&test_config.coordinator_private_key)
858                .expect("Failed to sign"),
859            msg: msg.clone(),
860        };
861        let signer_packet_dkg_private_shares = Packet {
862            sig: private_shares
863                .sign(&test_config.signer_private_key)
864                .expect("Failed to sign"),
865            msg,
866        };
867
868        assert!(!coordinator_packet_dkg_private_shares.verify(
869            &test_config.public_keys,
870            &test_config.coordinator_public_key
871        ));
872        assert!(signer_packet_dkg_private_shares.verify(
873            &test_config.public_keys,
874            &test_config.coordinator_public_key
875        ));
876    }
877
878    #[test]
879    fn dkg_end_verify_msg() {
880        let test_config = TestConfig::default();
881        let dkg_end = DkgEnd {
882            dkg_id: 0,
883            signer_id: 0,
884            status: DkgStatus::Success,
885        };
886        let msg = Message::DkgEnd(dkg_end.clone());
887
888        let coordinator_packet_dkg_end = Packet {
889            sig: dkg_end
890                .sign(&test_config.coordinator_private_key)
891                .expect("Failed to sign"),
892            msg: msg.clone(),
893        };
894        let signer_packet_dkg_end = Packet {
895            sig: dkg_end
896                .sign(&test_config.signer_private_key)
897                .expect("Failed to sign"),
898            msg,
899        };
900        assert!(!coordinator_packet_dkg_end.verify(
901            &test_config.public_keys,
902            &test_config.coordinator_public_key
903        ));
904        assert!(signer_packet_dkg_end.verify(
905            &test_config.public_keys,
906            &test_config.coordinator_public_key
907        ));
908    }
909    #[test]
910    fn nonce_request_verify_msg() {
911        let test_config = TestConfig::default();
912        let nonce_request = NonceRequest {
913            dkg_id: 0,
914            sign_id: 0,
915            sign_iter_id: 0,
916            message: vec![],
917            signature_type: SignatureType::Frost,
918        };
919        let msg = Message::NonceRequest(nonce_request.clone());
920        let coordinator_packet_nonce_request = Packet {
921            sig: nonce_request
922                .sign(&test_config.coordinator_private_key)
923                .expect("Failed to sign"),
924            msg: msg.clone(),
925        };
926        let signer_packet_nonce_request = Packet {
927            sig: nonce_request
928                .sign(&test_config.signer_private_key)
929                .expect("Failed to sign"),
930            msg,
931        };
932        assert!(coordinator_packet_nonce_request.verify(
933            &test_config.public_keys,
934            &test_config.coordinator_public_key
935        ));
936        assert!(!signer_packet_nonce_request.verify(
937            &test_config.public_keys,
938            &test_config.coordinator_public_key
939        ));
940    }
941    #[test]
942    fn nonce_response_verify_msg() {
943        let test_config = TestConfig::default();
944
945        let nonce_response = NonceResponse {
946            dkg_id: 0,
947            sign_id: 0,
948            sign_iter_id: 0,
949            signer_id: 0,
950            key_ids: vec![],
951            nonces: vec![],
952            message: vec![],
953        };
954        let msg = Message::NonceResponse(nonce_response.clone());
955        let coordinator_packet_nonce_response = Packet {
956            sig: nonce_response
957                .sign(&test_config.coordinator_private_key)
958                .expect("Failed to sign"),
959            msg: msg.clone(),
960        };
961        let signer_packet_nonce_response = Packet {
962            sig: nonce_response
963                .sign(&test_config.signer_private_key)
964                .expect("Failed to sign"),
965            msg,
966        };
967        assert!(!coordinator_packet_nonce_response.verify(
968            &test_config.public_keys,
969            &test_config.coordinator_public_key
970        ));
971        assert!(signer_packet_nonce_response.verify(
972            &test_config.public_keys,
973            &test_config.coordinator_public_key
974        ));
975    }
976
977    #[test]
978    fn signature_share_request_verify_msg() {
979        let test_config = TestConfig::default();
980        let signature_share_request = SignatureShareRequest {
981            dkg_id: 0,
982            sign_id: 0,
983            sign_iter_id: 0,
984            nonce_responses: vec![],
985            message: vec![],
986            signature_type: SignatureType::Frost,
987        };
988        let msg = Message::SignatureShareRequest(signature_share_request.clone());
989        let coordinator_packet_signature_share_request = Packet {
990            sig: signature_share_request
991                .sign(&test_config.coordinator_private_key)
992                .expect("Failed to sign"),
993            msg: msg.clone(),
994        };
995        let signer_packet_signature_share_request = Packet {
996            sig: signature_share_request
997                .sign(&test_config.signer_private_key)
998                .expect("Failed to sign"),
999            msg,
1000        };
1001        assert!(coordinator_packet_signature_share_request.verify(
1002            &test_config.public_keys,
1003            &test_config.coordinator_public_key
1004        ));
1005        assert!(!signer_packet_signature_share_request.verify(
1006            &test_config.public_keys,
1007            &test_config.coordinator_public_key
1008        ));
1009    }
1010
1011    #[test]
1012    fn signature_share_response_verify_msg() {
1013        let test_config = TestConfig::default();
1014
1015        let signature_share_response = SignatureShareResponse {
1016            dkg_id: 0,
1017            sign_id: 0,
1018            sign_iter_id: 0,
1019            signer_id: 0,
1020            signature_shares: vec![],
1021        };
1022        let msg = Message::SignatureShareResponse(signature_share_response.clone());
1023        let coordinator_packet_signature_share_response = Packet {
1024            sig: signature_share_response
1025                .sign(&test_config.coordinator_private_key)
1026                .expect("Failed to sign"),
1027            msg: msg.clone(),
1028        };
1029        let signer_packet_signature_share_response = Packet {
1030            sig: signature_share_response
1031                .sign(&test_config.signer_private_key)
1032                .expect("Failed to sign"),
1033            msg,
1034        };
1035        assert!(!coordinator_packet_signature_share_response.verify(
1036            &test_config.public_keys,
1037            &test_config.coordinator_public_key
1038        ));
1039        assert!(signer_packet_signature_share_response.verify(
1040            &test_config.public_keys,
1041            &test_config.coordinator_public_key
1042        ));
1043    }
1044
1045    #[test]
1046    fn signature_share_response_wrapped_verify_msg() {
1047        let test_config = TestConfig::default();
1048
1049        let signature_share_response = SignatureShareResponse {
1050            dkg_id: 0,
1051            sign_id: 0,
1052            sign_iter_id: 0,
1053            signer_id: 0,
1054            signature_shares: vec![],
1055        };
1056        let msg = Message::SignatureShareResponse(signature_share_response.clone());
1057        let sig = msg
1058            .sign(&test_config.coordinator_private_key)
1059            .expect("Failed to sign");
1060        assert!(msg.verify(&sig, &test_config.coordinator_public_key));
1061    }
1062}