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