libp2p_identity/
keypair.rs

1// Copyright 2023 Protocol Labs.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21#[cfg(any(
22    feature = "ecdsa",
23    feature = "secp256k1",
24    feature = "ed25519",
25    feature = "rsa"
26))]
27use quick_protobuf::{BytesReader, Writer};
28
29#[cfg(feature = "ecdsa")]
30use crate::ecdsa;
31#[cfg(any(
32    feature = "ecdsa",
33    feature = "secp256k1",
34    feature = "ed25519",
35    feature = "rsa"
36))]
37#[cfg(feature = "ed25519")]
38use crate::ed25519;
39#[cfg(any(
40    feature = "ecdsa",
41    feature = "secp256k1",
42    feature = "ed25519",
43    feature = "rsa"
44))]
45use crate::error::OtherVariantError;
46#[cfg(any(
47    feature = "ecdsa",
48    feature = "secp256k1",
49    feature = "ed25519",
50    feature = "rsa"
51))]
52use crate::proto;
53#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
54use crate::rsa;
55#[cfg(feature = "secp256k1")]
56use crate::secp256k1;
57use crate::{
58    error::{DecodingError, SigningError},
59    KeyType,
60};
61
62/// Identity keypair of a node.
63///
64/// # Example: Generating RSA keys with OpenSSL
65///
66/// ```text
67/// openssl genrsa -out private.pem 2048
68/// openssl pkcs8 -in private.pem -inform PEM -topk8 -out private.pk8 -outform DER -nocrypt
69/// rm private.pem      # optional
70/// ```
71///
72/// Loading the keys:
73///
74/// ```text
75/// let mut bytes = std::fs::read("private.pk8").unwrap();
76/// let keypair = Keypair::rsa_from_pkcs8(&mut bytes);
77/// ```
78#[derive(Debug, Clone)]
79pub struct Keypair {
80    keypair: KeyPairInner,
81}
82
83#[derive(Debug, Clone)]
84#[allow(clippy::large_enum_variant)]
85enum KeyPairInner {
86    /// An Ed25519 keypair.
87    #[cfg(feature = "ed25519")]
88    Ed25519(ed25519::Keypair),
89    /// An RSA keypair.
90    #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
91    Rsa(rsa::Keypair),
92    /// A Secp256k1 keypair.
93    #[cfg(feature = "secp256k1")]
94    Secp256k1(secp256k1::Keypair),
95    /// An ECDSA keypair.
96    #[cfg(feature = "ecdsa")]
97    Ecdsa(ecdsa::Keypair),
98}
99
100impl Keypair {
101    /// Generate a new Ed25519 keypair.
102    #[cfg(all(feature = "ed25519", feature = "rand"))]
103    pub fn generate_ed25519() -> Keypair {
104        Keypair {
105            keypair: KeyPairInner::Ed25519(ed25519::Keypair::generate()),
106        }
107    }
108
109    /// Generate a new Secp256k1 keypair.
110    #[cfg(all(feature = "secp256k1", feature = "rand"))]
111    pub fn generate_secp256k1() -> Keypair {
112        Keypair {
113            keypair: KeyPairInner::Secp256k1(secp256k1::Keypair::generate()),
114        }
115    }
116
117    /// Generate a new ECDSA keypair.
118    #[cfg(all(feature = "ecdsa", feature = "rand"))]
119    pub fn generate_ecdsa() -> Keypair {
120        Keypair {
121            keypair: KeyPairInner::Ecdsa(ecdsa::Keypair::generate()),
122        }
123    }
124
125    #[cfg(feature = "ed25519")]
126    pub fn try_into_ed25519(self) -> Result<ed25519::Keypair, OtherVariantError> {
127        self.try_into()
128    }
129
130    #[cfg(feature = "secp256k1")]
131    pub fn try_into_secp256k1(self) -> Result<secp256k1::Keypair, OtherVariantError> {
132        self.try_into()
133    }
134
135    #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
136    pub fn try_into_rsa(self) -> Result<rsa::Keypair, OtherVariantError> {
137        self.try_into()
138    }
139
140    #[cfg(feature = "ecdsa")]
141    pub fn try_into_ecdsa(self) -> Result<ecdsa::Keypair, OtherVariantError> {
142        self.try_into()
143    }
144
145    /// Decode an keypair from a DER-encoded secret key in PKCS#8 PrivateKeyInfo
146    /// format (i.e. unencrypted) as defined in [RFC5208].
147    ///
148    /// [RFC5208]: https://tools.ietf.org/html/rfc5208#section-5
149    #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
150    pub fn rsa_from_pkcs8(pkcs8_der: &mut [u8]) -> Result<Keypair, DecodingError> {
151        rsa::Keypair::try_decode_pkcs8(pkcs8_der).map(|kp| Keypair {
152            keypair: KeyPairInner::Rsa(kp),
153        })
154    }
155
156    /// Decode a keypair from a DER-encoded Secp256k1 secret key in an ECPrivateKey
157    /// structure as defined in [RFC5915].
158    ///
159    /// [RFC5915]: https://tools.ietf.org/html/rfc5915
160    #[cfg(feature = "secp256k1")]
161    pub fn secp256k1_from_der(der: &mut [u8]) -> Result<Keypair, DecodingError> {
162        secp256k1::SecretKey::from_der(der).map(|sk| Keypair {
163            keypair: KeyPairInner::Secp256k1(secp256k1::Keypair::from(sk)),
164        })
165    }
166
167    #[cfg(feature = "ed25519")]
168    pub fn ed25519_from_bytes(bytes: impl AsMut<[u8]>) -> Result<Keypair, DecodingError> {
169        Ok(Keypair {
170            keypair: KeyPairInner::Ed25519(ed25519::Keypair::from(
171                ed25519::SecretKey::try_from_bytes(bytes)?,
172            )),
173        })
174    }
175
176    /// Sign a message using the private key of this keypair, producing
177    /// a signature that can be verified using the corresponding public key.
178    #[allow(unused_variables)]
179    pub fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
180        match self.keypair {
181            #[cfg(feature = "ed25519")]
182            KeyPairInner::Ed25519(ref pair) => Ok(pair.sign(msg)),
183            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
184            KeyPairInner::Rsa(ref pair) => pair.sign(msg),
185            #[cfg(feature = "secp256k1")]
186            KeyPairInner::Secp256k1(ref pair) => Ok(pair.secret().sign(msg)),
187            #[cfg(feature = "ecdsa")]
188            KeyPairInner::Ecdsa(ref pair) => Ok(pair.secret().sign(msg)),
189        }
190    }
191
192    /// Get the public key of this keypair.
193    pub fn public(&self) -> PublicKey {
194        match self.keypair {
195            #[cfg(feature = "ed25519")]
196            KeyPairInner::Ed25519(ref pair) => PublicKey {
197                publickey: PublicKeyInner::Ed25519(pair.public()),
198            },
199            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
200            KeyPairInner::Rsa(ref pair) => PublicKey {
201                publickey: PublicKeyInner::Rsa(pair.public()),
202            },
203            #[cfg(feature = "secp256k1")]
204            KeyPairInner::Secp256k1(ref pair) => PublicKey {
205                publickey: PublicKeyInner::Secp256k1(pair.public().clone()),
206            },
207            #[cfg(feature = "ecdsa")]
208            KeyPairInner::Ecdsa(ref pair) => PublicKey {
209                publickey: PublicKeyInner::Ecdsa(pair.public().clone()),
210            },
211        }
212    }
213
214    /// Encode a private key as protobuf structure.
215    pub fn to_protobuf_encoding(&self) -> Result<Vec<u8>, DecodingError> {
216        #[cfg(any(
217            feature = "ecdsa",
218            feature = "secp256k1",
219            feature = "ed25519",
220            feature = "rsa"
221        ))]
222        {
223            use quick_protobuf::MessageWrite;
224            let pk: proto::PrivateKey = match self.keypair {
225                #[cfg(feature = "ed25519")]
226                KeyPairInner::Ed25519(ref data) => proto::PrivateKey {
227                    Type: proto::KeyType::Ed25519,
228                    Data: data.to_bytes().to_vec(),
229                },
230                #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
231                KeyPairInner::Rsa(_) => return Err(DecodingError::encoding_unsupported("RSA")),
232                #[cfg(feature = "secp256k1")]
233                KeyPairInner::Secp256k1(ref data) => proto::PrivateKey {
234                    Type: proto::KeyType::Secp256k1,
235                    Data: data.secret().to_bytes().to_vec(),
236                },
237                #[cfg(feature = "ecdsa")]
238                KeyPairInner::Ecdsa(ref data) => proto::PrivateKey {
239                    Type: proto::KeyType::ECDSA,
240                    Data: data.secret().encode_der(),
241                },
242            };
243
244            let mut buf = Vec::with_capacity(pk.get_size());
245            let mut writer = Writer::new(&mut buf);
246            pk.write_message(&mut writer).expect("Encoding to succeed");
247
248            Ok(buf)
249        }
250
251        #[cfg(not(any(
252            feature = "ecdsa",
253            feature = "secp256k1",
254            feature = "ed25519",
255            feature = "rsa"
256        )))]
257        unreachable!()
258    }
259
260    /// Decode a private key from a protobuf structure and parse it as a [`Keypair`].
261    #[allow(unused_variables)]
262    pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<Keypair, DecodingError> {
263        #[cfg(any(
264            feature = "ecdsa",
265            feature = "secp256k1",
266            feature = "ed25519",
267            feature = "rsa"
268        ))]
269        {
270            use quick_protobuf::MessageRead;
271
272            let mut reader = BytesReader::from_bytes(bytes);
273            let mut private_key = proto::PrivateKey::from_reader(&mut reader, bytes)
274                .map_err(|e| DecodingError::bad_protobuf("private key bytes", e))
275                .map(zeroize::Zeroizing::new)?;
276
277            #[allow(unreachable_code)]
278            match private_key.Type {
279                proto::KeyType::Ed25519 => {
280                    #[cfg(feature = "ed25519")]
281                    return ed25519::Keypair::try_from_bytes(&mut private_key.Data).map(|sk| {
282                        Keypair {
283                            keypair: KeyPairInner::Ed25519(sk),
284                        }
285                    });
286                    Err(DecodingError::missing_feature("ed25519"))
287                }
288                proto::KeyType::RSA => {
289                    #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
290                    return rsa::Keypair::try_decode_pkcs1(&mut private_key.Data).map(|sk| {
291                        Keypair {
292                            keypair: KeyPairInner::Rsa(sk),
293                        }
294                    });
295                    Err(DecodingError::missing_feature("rsa"))
296                }
297                proto::KeyType::Secp256k1 => {
298                    #[cfg(feature = "secp256k1")]
299                    return secp256k1::SecretKey::try_from_bytes(&mut private_key.Data).map(
300                        |key| Keypair {
301                            keypair: KeyPairInner::Secp256k1(key.into()),
302                        },
303                    );
304
305                    Err(DecodingError::missing_feature("secp256k1"))
306                }
307                proto::KeyType::ECDSA => {
308                    #[cfg(feature = "ecdsa")]
309                    return ecdsa::SecretKey::try_decode_der(&mut private_key.Data).map(|key| {
310                        Keypair {
311                            keypair: KeyPairInner::Ecdsa(key.into()),
312                        }
313                    });
314
315                    Err(DecodingError::missing_feature("ecdsa"))
316                }
317            }
318        }
319
320        #[cfg(not(any(
321            feature = "ecdsa",
322            feature = "secp256k1",
323            feature = "ed25519",
324            feature = "rsa"
325        )))]
326        unreachable!()
327    }
328
329    /// Return a [`KeyType`] of the [`Keypair`].
330    pub fn key_type(&self) -> KeyType {
331        match self.keypair {
332            #[cfg(feature = "ed25519")]
333            KeyPairInner::Ed25519(_) => KeyType::Ed25519,
334            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
335            KeyPairInner::Rsa(_) => KeyType::RSA,
336            #[cfg(feature = "secp256k1")]
337            KeyPairInner::Secp256k1(_) => KeyType::Secp256k1,
338            #[cfg(feature = "ecdsa")]
339            KeyPairInner::Ecdsa(_) => KeyType::Ecdsa,
340        }
341    }
342
343    /// Deterministically derive a new secret from this [`Keypair`],
344    /// taking into account the provided domain.
345    ///
346    /// This works for all key types except RSA where it returns `None`.
347    ///
348    /// # Example
349    ///
350    /// ```
351    /// # fn main() {
352    /// # use libp2p_identity as identity;
353    /// let key = identity::Keypair::generate_ed25519();
354    ///
355    /// let new_key = key
356    ///     .derive_secret(b"my encryption key")
357    ///     .expect("can derive secret for ed25519");
358    /// # }
359    /// ```
360    #[cfg(any(
361        feature = "ecdsa",
362        feature = "secp256k1",
363        feature = "ed25519",
364        feature = "rsa"
365    ))]
366    pub fn derive_secret(&self, domain: &[u8]) -> Option<[u8; 32]> {
367        let mut okm = [0u8; 32];
368        hkdf::Hkdf::<sha2::Sha256>::new(None, &self.secret()?)
369            .expand(domain, &mut okm)
370            .expect("okm.len() == 32");
371
372        Some(okm)
373    }
374
375    // We build docs with all features so this doesn't need to have any docs.
376    #[cfg(not(any(
377        feature = "ecdsa",
378        feature = "secp256k1",
379        feature = "ed25519",
380        feature = "rsa"
381    )))]
382    pub fn derive_secret(&self, _: &[u8]) -> Option<[u8; 32]> {
383        None
384    }
385
386    /// Return the secret key of the [`Keypair`].
387    #[allow(dead_code)]
388    pub(crate) fn secret(&self) -> Option<[u8; 32]> {
389        match self.keypair {
390            #[cfg(feature = "ed25519")]
391            KeyPairInner::Ed25519(ref inner) => Some(inner.secret().to_bytes()),
392            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
393            KeyPairInner::Rsa(_) => None,
394            #[cfg(feature = "secp256k1")]
395            KeyPairInner::Secp256k1(ref inner) => Some(inner.secret().to_bytes()),
396            #[cfg(feature = "ecdsa")]
397            KeyPairInner::Ecdsa(ref inner) => Some(
398                inner
399                    .secret()
400                    .to_bytes()
401                    .try_into()
402                    .expect("Ecdsa's private key should be 32 bytes"),
403            ),
404        }
405    }
406}
407
408#[cfg(feature = "ecdsa")]
409impl From<ecdsa::Keypair> for Keypair {
410    fn from(kp: ecdsa::Keypair) -> Self {
411        Keypair {
412            keypair: KeyPairInner::Ecdsa(kp),
413        }
414    }
415}
416
417#[cfg(feature = "ed25519")]
418impl From<ed25519::Keypair> for Keypair {
419    fn from(kp: ed25519::Keypair) -> Self {
420        Keypair {
421            keypair: KeyPairInner::Ed25519(kp),
422        }
423    }
424}
425
426#[cfg(feature = "secp256k1")]
427impl From<secp256k1::Keypair> for Keypair {
428    fn from(kp: secp256k1::Keypair) -> Self {
429        Keypair {
430            keypair: KeyPairInner::Secp256k1(kp),
431        }
432    }
433}
434
435#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
436impl From<rsa::Keypair> for Keypair {
437    fn from(kp: rsa::Keypair) -> Self {
438        Keypair {
439            keypair: KeyPairInner::Rsa(kp),
440        }
441    }
442}
443
444#[cfg(feature = "ed25519")]
445impl TryInto<ed25519::Keypair> for Keypair {
446    type Error = OtherVariantError;
447
448    fn try_into(self) -> Result<ed25519::Keypair, Self::Error> {
449        match self.keypair {
450            KeyPairInner::Ed25519(inner) => Ok(inner),
451            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
452            KeyPairInner::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
453            #[cfg(feature = "secp256k1")]
454            KeyPairInner::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
455            #[cfg(feature = "ecdsa")]
456            KeyPairInner::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
457        }
458    }
459}
460
461#[cfg(feature = "ecdsa")]
462impl TryInto<ecdsa::Keypair> for Keypair {
463    type Error = OtherVariantError;
464
465    fn try_into(self) -> Result<ecdsa::Keypair, Self::Error> {
466        match self.keypair {
467            KeyPairInner::Ecdsa(inner) => Ok(inner),
468            #[cfg(feature = "ed25519")]
469            KeyPairInner::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
470            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
471            KeyPairInner::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
472            #[cfg(feature = "secp256k1")]
473            KeyPairInner::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
474        }
475    }
476}
477
478#[cfg(feature = "secp256k1")]
479impl TryInto<secp256k1::Keypair> for Keypair {
480    type Error = OtherVariantError;
481
482    fn try_into(self) -> Result<secp256k1::Keypair, Self::Error> {
483        match self.keypair {
484            KeyPairInner::Secp256k1(inner) => Ok(inner),
485            #[cfg(feature = "ed25519")]
486            KeyPairInner::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
487            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
488            KeyPairInner::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
489            #[cfg(feature = "ecdsa")]
490            KeyPairInner::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
491        }
492    }
493}
494
495#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
496impl TryInto<rsa::Keypair> for Keypair {
497    type Error = OtherVariantError;
498
499    fn try_into(self) -> Result<rsa::Keypair, Self::Error> {
500        match self.keypair {
501            KeyPairInner::Rsa(inner) => Ok(inner),
502            #[cfg(feature = "ed25519")]
503            KeyPairInner::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
504            #[cfg(feature = "secp256k1")]
505            KeyPairInner::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
506            #[cfg(feature = "ecdsa")]
507            KeyPairInner::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
508        }
509    }
510}
511
512#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
513pub(crate) enum PublicKeyInner {
514    /// A public Ed25519 key.
515    #[cfg(feature = "ed25519")]
516    Ed25519(ed25519::PublicKey),
517    #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
518    /// A public RSA key.
519    Rsa(rsa::PublicKey),
520    #[cfg(feature = "secp256k1")]
521    /// A public Secp256k1 key.
522    Secp256k1(secp256k1::PublicKey),
523    /// A public ECDSA key.
524    #[cfg(feature = "ecdsa")]
525    Ecdsa(ecdsa::PublicKey),
526}
527
528/// The public key of a node's identity keypair.
529#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
530pub struct PublicKey {
531    pub(crate) publickey: PublicKeyInner,
532}
533
534impl PublicKey {
535    /// Verify a signature for a message using this public key, i.e. check
536    /// that the signature has been produced by the corresponding
537    /// private key (authenticity), and that the message has not been
538    /// tampered with (integrity).
539    #[must_use]
540    #[allow(unused_variables)]
541    pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
542        match self.publickey {
543            #[cfg(feature = "ed25519")]
544            PublicKeyInner::Ed25519(ref pk) => pk.verify(msg, sig),
545            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
546            PublicKeyInner::Rsa(ref pk) => pk.verify(msg, sig),
547            #[cfg(feature = "secp256k1")]
548            PublicKeyInner::Secp256k1(ref pk) => pk.verify(msg, sig),
549            #[cfg(feature = "ecdsa")]
550            PublicKeyInner::Ecdsa(ref pk) => pk.verify(msg, sig),
551        }
552    }
553
554    #[cfg(feature = "ed25519")]
555    pub fn try_into_ed25519(self) -> Result<ed25519::PublicKey, OtherVariantError> {
556        self.try_into()
557    }
558
559    #[cfg(feature = "secp256k1")]
560    pub fn try_into_secp256k1(self) -> Result<secp256k1::PublicKey, OtherVariantError> {
561        self.try_into()
562    }
563
564    #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
565    pub fn try_into_rsa(self) -> Result<rsa::PublicKey, OtherVariantError> {
566        self.try_into()
567    }
568
569    #[cfg(feature = "ecdsa")]
570    pub fn try_into_ecdsa(self) -> Result<ecdsa::PublicKey, OtherVariantError> {
571        self.try_into()
572    }
573
574    /// Encode the public key into a protobuf structure for storage or
575    /// exchange with other nodes.
576    pub fn encode_protobuf(&self) -> Vec<u8> {
577        #[cfg(any(
578            feature = "ecdsa",
579            feature = "secp256k1",
580            feature = "ed25519",
581            feature = "rsa"
582        ))]
583        {
584            use quick_protobuf::MessageWrite;
585            let public_key = proto::PublicKey::from(self);
586
587            let mut buf = Vec::with_capacity(public_key.get_size());
588            let mut writer = Writer::new(&mut buf);
589            public_key
590                .write_message(&mut writer)
591                .expect("Encoding to succeed");
592
593            buf
594        }
595
596        #[cfg(not(any(
597            feature = "ecdsa",
598            feature = "secp256k1",
599            feature = "ed25519",
600            feature = "rsa"
601        )))]
602        unreachable!()
603    }
604
605    /// Decode a public key from a protobuf structure, e.g. read from storage
606    /// or received from another node.
607    #[allow(unused_variables)]
608    pub fn try_decode_protobuf(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
609        #[cfg(any(
610            feature = "ecdsa",
611            feature = "secp256k1",
612            feature = "ed25519",
613            feature = "rsa"
614        ))]
615        {
616            use quick_protobuf::MessageRead;
617            let mut reader = BytesReader::from_bytes(bytes);
618
619            let pubkey = proto::PublicKey::from_reader(&mut reader, bytes)
620                .map_err(|e| DecodingError::bad_protobuf("public key bytes", e))?;
621
622            pubkey.try_into()
623        }
624
625        #[cfg(not(any(
626            feature = "ecdsa",
627            feature = "secp256k1",
628            feature = "ed25519",
629            feature = "rsa"
630        )))]
631        unreachable!()
632    }
633
634    /// Convert the `PublicKey` into the corresponding `PeerId`.
635    #[cfg(feature = "peerid")]
636    pub fn to_peer_id(&self) -> crate::PeerId {
637        self.into()
638    }
639
640    /// Return a [`KeyType`] of the [`PublicKey`].
641    pub fn key_type(&self) -> KeyType {
642        match self.publickey {
643            #[cfg(feature = "ed25519")]
644            PublicKeyInner::Ed25519(_) => KeyType::Ed25519,
645            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
646            PublicKeyInner::Rsa(_) => KeyType::RSA,
647            #[cfg(feature = "secp256k1")]
648            PublicKeyInner::Secp256k1(_) => KeyType::Secp256k1,
649            #[cfg(feature = "ecdsa")]
650            PublicKeyInner::Ecdsa(_) => KeyType::Ecdsa,
651        }
652    }
653}
654
655#[cfg(any(
656    feature = "ecdsa",
657    feature = "secp256k1",
658    feature = "ed25519",
659    feature = "rsa"
660))]
661impl TryFrom<proto::PublicKey> for PublicKey {
662    type Error = DecodingError;
663
664    fn try_from(pubkey: proto::PublicKey) -> Result<Self, Self::Error> {
665        match pubkey.Type {
666            #[cfg(feature = "ed25519")]
667            proto::KeyType::Ed25519 => Ok(ed25519::PublicKey::try_from_bytes(&pubkey.Data).map(
668                |kp| PublicKey {
669                    publickey: PublicKeyInner::Ed25519(kp),
670                },
671            )?),
672            #[cfg(not(feature = "ed25519"))]
673            proto::KeyType::Ed25519 => {
674                tracing::debug!("support for ed25519 was disabled at compile-time");
675                Err(DecodingError::missing_feature("ed25519"))
676            }
677            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
678            proto::KeyType::RSA => {
679                Ok(
680                    rsa::PublicKey::try_decode_x509(&pubkey.Data).map(|kp| PublicKey {
681                        publickey: PublicKeyInner::Rsa(kp),
682                    })?,
683                )
684            }
685            #[cfg(any(not(feature = "rsa"), target_arch = "wasm32"))]
686            proto::KeyType::RSA => {
687                tracing::debug!("support for RSA was disabled at compile-time");
688                Err(DecodingError::missing_feature("rsa"))
689            }
690            #[cfg(feature = "secp256k1")]
691            proto::KeyType::Secp256k1 => Ok(secp256k1::PublicKey::try_from_bytes(&pubkey.Data)
692                .map(|kp| PublicKey {
693                    publickey: PublicKeyInner::Secp256k1(kp),
694                })?),
695            #[cfg(not(feature = "secp256k1"))]
696            proto::KeyType::Secp256k1 => {
697                tracing::debug!("support for secp256k1 was disabled at compile-time");
698                Err(DecodingError::missing_feature("secp256k1"))
699            }
700            #[cfg(feature = "ecdsa")]
701            proto::KeyType::ECDSA => Ok(ecdsa::PublicKey::try_decode_der(&pubkey.Data).map(
702                |kp| PublicKey {
703                    publickey: PublicKeyInner::Ecdsa(kp),
704                },
705            )?),
706            #[cfg(not(feature = "ecdsa"))]
707            proto::KeyType::ECDSA => {
708                tracing::debug!("support for ECDSA was disabled at compile-time");
709                Err(DecodingError::missing_feature("ecdsa"))
710            }
711        }
712    }
713}
714
715#[cfg(feature = "ed25519")]
716impl TryInto<ed25519::PublicKey> for PublicKey {
717    type Error = OtherVariantError;
718
719    fn try_into(self) -> Result<ed25519::PublicKey, Self::Error> {
720        match self.publickey {
721            PublicKeyInner::Ed25519(inner) => Ok(inner),
722            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
723            PublicKeyInner::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
724            #[cfg(feature = "secp256k1")]
725            PublicKeyInner::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
726            #[cfg(feature = "ecdsa")]
727            PublicKeyInner::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
728        }
729    }
730}
731
732#[cfg(feature = "ecdsa")]
733impl TryInto<ecdsa::PublicKey> for PublicKey {
734    type Error = OtherVariantError;
735
736    fn try_into(self) -> Result<ecdsa::PublicKey, Self::Error> {
737        match self.publickey {
738            PublicKeyInner::Ecdsa(inner) => Ok(inner),
739            #[cfg(feature = "ed25519")]
740            PublicKeyInner::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
741            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
742            PublicKeyInner::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
743            #[cfg(feature = "secp256k1")]
744            PublicKeyInner::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
745        }
746    }
747}
748
749#[cfg(feature = "secp256k1")]
750impl TryInto<secp256k1::PublicKey> for PublicKey {
751    type Error = OtherVariantError;
752
753    fn try_into(self) -> Result<secp256k1::PublicKey, Self::Error> {
754        match self.publickey {
755            PublicKeyInner::Secp256k1(inner) => Ok(inner),
756            #[cfg(feature = "ed25519")]
757            PublicKeyInner::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
758            #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
759            PublicKeyInner::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
760            #[cfg(feature = "ecdsa")]
761            PublicKeyInner::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
762        }
763    }
764}
765
766#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
767impl TryInto<rsa::PublicKey> for PublicKey {
768    type Error = OtherVariantError;
769
770    fn try_into(self) -> Result<rsa::PublicKey, Self::Error> {
771        match self.publickey {
772            PublicKeyInner::Rsa(inner) => Ok(inner),
773            #[cfg(feature = "ed25519")]
774            PublicKeyInner::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
775            #[cfg(feature = "secp256k1")]
776            PublicKeyInner::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
777            #[cfg(feature = "ecdsa")]
778            PublicKeyInner::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
779        }
780    }
781}
782
783#[cfg(feature = "ed25519")]
784impl From<ed25519::PublicKey> for PublicKey {
785    fn from(key: ed25519::PublicKey) -> Self {
786        PublicKey {
787            publickey: PublicKeyInner::Ed25519(key),
788        }
789    }
790}
791
792#[cfg(feature = "secp256k1")]
793impl From<secp256k1::PublicKey> for PublicKey {
794    fn from(key: secp256k1::PublicKey) -> Self {
795        PublicKey {
796            publickey: PublicKeyInner::Secp256k1(key),
797        }
798    }
799}
800
801#[cfg(feature = "ecdsa")]
802impl From<ecdsa::PublicKey> for PublicKey {
803    fn from(key: ecdsa::PublicKey) -> Self {
804        PublicKey {
805            publickey: PublicKeyInner::Ecdsa(key),
806        }
807    }
808}
809
810#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
811impl From<rsa::PublicKey> for PublicKey {
812    fn from(key: rsa::PublicKey) -> Self {
813        PublicKey {
814            publickey: PublicKeyInner::Rsa(key),
815        }
816    }
817}
818
819#[cfg(test)]
820mod tests {
821    use super::*;
822
823    #[test]
824    #[cfg(feature = "ed25519")]
825    #[cfg(feature = "peerid")]
826    fn keypair_protobuf_roundtrip_ed25519() {
827        let priv_key = Keypair::from_protobuf_encoding(&hex_literal::hex!(
828            "080112407e0830617c4a7de83925dfb2694556b12936c477a0e1feb2e148ec9da60fee7d1ed1e8fae2c4a144b8be8fd4b47bf3d3b34b871c3cacf6010f0e42d474fce27e"
829        ))
830            .unwrap();
831
832        let pub_key = PublicKey::try_decode_protobuf(&hex_literal::hex!(
833            "080112201ed1e8fae2c4a144b8be8fd4b47bf3d3b34b871c3cacf6010f0e42d474fce27e"
834        ))
835        .unwrap();
836
837        roundtrip_protobuf_encoding(&priv_key, &pub_key, KeyType::Ed25519);
838    }
839
840    #[test]
841    #[cfg(all(feature = "ecdsa", feature = "peerid"))]
842    fn keypair_protobuf_roundtrip_ecdsa() {
843        let priv_key = Keypair::from_protobuf_encoding(&hex_literal::hex!(
844            "08031279307702010104203E5B1FE9712E6C314942A750BD67485DE3C1EFE85B1BFB520AE8F9AE3DFA4A4CA00A06082A8648CE3D030107A14403420004DE3D300FA36AE0E8F5D530899D83ABAB44ABF3161F162A4BC901D8E6ECDA020E8B6D5F8DA30525E71D6851510C098E5C47C646A597FB4DCEC034E9F77C409E62"
845        ))
846        .unwrap();
847        let pub_key = PublicKey::try_decode_protobuf(&hex_literal::hex!("0803125b3059301306072a8648ce3d020106082a8648ce3d03010703420004de3d300fa36ae0e8f5d530899d83abab44abf3161f162a4bc901d8e6ecda020e8b6d5f8da30525e71d6851510c098e5c47c646a597fb4dcec034e9f77c409e62")).unwrap();
848
849        roundtrip_protobuf_encoding(&priv_key, &pub_key, KeyType::Ecdsa);
850    }
851
852    #[test]
853    #[cfg(all(feature = "secp256k1", feature = "peerid"))]
854    fn keypair_protobuf_roundtrip_secp256k1() {
855        let priv_key = Keypair::from_protobuf_encoding(&hex_literal::hex!(
856            "0802122053DADF1D5A164D6B4ACDB15E24AA4C5B1D3461BDBD42ABEDB0A4404D56CED8FB"
857        ))
858        .unwrap();
859        let pub_key = PublicKey::try_decode_protobuf(&hex_literal::hex!(
860            "08021221037777e994e452c21604f91de093ce415f5432f701dd8cd1a7a6fea0e630bfca99"
861        ))
862        .unwrap();
863
864        roundtrip_protobuf_encoding(&priv_key, &pub_key, KeyType::Secp256k1);
865    }
866
867    #[cfg(feature = "peerid")]
868    fn roundtrip_protobuf_encoding(private_key: &Keypair, public_key: &PublicKey, tpe: KeyType) {
869        assert_eq!(&private_key.public(), public_key);
870
871        let encoded_priv = private_key.to_protobuf_encoding().unwrap();
872        let decoded_priv = Keypair::from_protobuf_encoding(&encoded_priv).unwrap();
873
874        assert_eq!(
875            private_key.public().to_peer_id(),
876            decoded_priv.public().to_peer_id(),
877            "PeerId from roundtripped private key should be the same"
878        );
879
880        let encoded_public = private_key.public().encode_protobuf();
881        let decoded_public = PublicKey::try_decode_protobuf(&encoded_public).unwrap();
882
883        assert_eq!(
884            private_key.public().to_peer_id(),
885            decoded_public.to_peer_id(),
886            "PeerId from roundtripped public key should be the same"
887        );
888        assert_eq!(private_key.key_type(), tpe)
889    }
890
891    #[test]
892    #[cfg(feature = "peerid")]
893    fn keypair_from_protobuf_encoding() {
894        let priv_key = Keypair::from_protobuf_encoding(&hex_literal::hex!(
895            "080012ae123082092a0201000282020100e1beab071d08200bde24eef00d049449b07770ff9910257b2d7d5dda242ce8f0e2f12e1af4b32d9efd2c090f66b0f29986dbb645dae9880089704a94e5066d594162ae6ee8892e6ec70701db0a6c445c04778eb3de1293aa1a23c3825b85c6620a2bc3f82f9b0c309bc0ab3aeb1873282bebd3da03c33e76c21e9beb172fd44c9e43be32e2c99827033cf8d0f0c606f4579326c930eb4e854395ad941256542c793902185153c474bed109d6ff5141ebf9cd256cf58893a37f83729f97e7cb435ec679d2e33901d27bb35aa0d7e20561da08885ef0abbf8e2fb48d6a5487047a9ecb1ad41fa7ed84f6e3e8ecd5d98b3982d2a901b4454991766da295ab78822add5612a2df83bcee814cf50973e80d7ef38111b1bd87da2ae92438a2c8cbcc70b31ee319939a3b9c761dbc13b5c086d6b64bf7ae7dacc14622375d92a8ff9af7eb962162bbddebf90acb32adb5e4e4029f1c96019949ecfbfeffd7ac1e3fbcc6b6168c34be3d5a2e5999fcbb39bba7adbca78eab09b9bc39f7fa4b93411f4cc175e70c0a083e96bfaefb04a9580b4753c1738a6a760ae1afd851a1a4bdad231cf56e9284d832483df215a46c1c21bdf0c6cfe951c18f1ee4078c79c13d63edb6e14feaeffabc90ad317e4875fe648101b0864097e998f0ca3025ef9638cd2b0caecd3770ab54a1d9c6ca959b0f5dcbc90caeefc4135baca6fd475224269bbe1b02030100010282020100a472ffa858efd8588ce59ee264b957452f3673acdf5631d7bfd5ba0ef59779c231b0bc838a8b14cae367b6d9ef572c03c7883b0a3c652f5c24c316b1ccfd979f13d0cd7da20c7d34d9ec32dfdc81ee7292167e706d705efde5b8f3edfcba41409e642f8897357df5d320d21c43b33600a7ae4e505db957c1afbc189d73f0b5d972d9aaaeeb232ca20eebd5de6fe7f29d01470354413cc9a0af1154b7af7c1029adcd67c74b4798afeb69e09f2cb387305e73a1b5f450202d54f0ef096fe1bde340219a1194d1ac9026e90b366cce0c59b239d10e4888f52ca1780824d39ae01a6b9f4dd6059191a7f12b2a3d8db3c2868cd4e5a5862b8b625a4197d52c6ac77710116ebd3ced81c4d91ad5fdfbed68312ebce7eea45c1833ca3acf7da2052820eacf5c6b07d086dabeb893391c71417fd8a4b1829ae2cf60d1749d0e25da19530d889461c21da3492a8dc6ccac7de83ac1c2185262c7473c8cc42f547cc9864b02a8073b6aa54a037d8c0de3914784e6205e83d97918b944f11b877b12084c0dd1d36592f8a4f8b8da5bb404c3d2c079b22b6ceabfbcb637c0dbe0201f0909d533f8bf308ada47aee641a012a494d31b54c974e58b87f140258258bb82f31692659db7aa07e17a5b2a0832c24e122d3a8babcc9ee74cbb07d3058bb85b15f6f6b2674aba9fd34367be9782d444335fbed31e3c4086c652597c27104938b47fa10282010100e9fdf843c1550070ca711cb8ff28411466198f0e212511c3186623890c0071bf6561219682fe7dbdfd81176eba7c4faba21614a20721e0fcd63768e6d925688ecc90992059ac89256e0524de90bf3d8a052ce6a9f6adafa712f3107a016e20c80255c9e37d8206d1bc327e06e66eb24288da866b55904fd8b59e6b2ab31bc5eab47e597093c63fab7872102d57b4c589c66077f534a61f5f65127459a33c91f6db61fc431b1ae90be92b4149a3255291baf94304e3efb77b1107b5a3bda911359c40a53c347ff9100baf8f36dc5cd991066b5bdc28b39ed644f404afe9213f4d31c9d4e40f3a5f5e3c39bebeb244e84137544e1a1839c1c8aaebf0c78a7fad590282010100f6fa1f1e6b803742d5490b7441152f500970f46feb0b73a6e4baba2aaf3c0e245ed852fc31d86a8e46eb48e90fac409989dfee45238f97e8f1f8e83a136488c1b04b8a7fb695f37b8616307ff8a8d63e8cfa0b4fb9b9167ffaebabf111aa5a4344afbabd002ae8961c38c02da76a9149abdde93eb389eb32595c29ba30d8283a7885218a5a9d33f7f01dbdf85f3aad016c071395491338ec318d39220e1c7bd69d3d6b520a13a30d745c102b827ad9984b0dd6aed73916ffa82a06c1c111e7047dcd2668f988a0570a71474992eecf416e068f029ec323d5d635fd24694fc9bf96973c255d26c772a95bf8b7f876547a5beabf86f06cd21b67994f944e7a5493028201010095b02fd30069e547426a8bea58e8a2816f33688dac6c6f6974415af8402244a22133baedf34ce499d7036f3f19b38eb00897c18949b0c5a25953c71aeeccfc8f6594173157cc854bd98f16dffe8f28ca13b77eb43a2730585c49fc3f608cd811bb54b03b84bddaa8ef910988567f783012266199667a546a18fd88271fbf63a45ae4fd4884706da8befb9117c0a4d73de5172f8640b1091ed8a4aea3ed4641463f5ff6a5e3401ad7d0c92811f87956d1fd5f9a1d15c7f3839a08698d9f35f9d966e5000f7cb2655d7b6c4adcd8a9d950ea5f61bb7c9a33c17508f9baa313eecfee4ae493249ebe05a5d7770bbd3551b2eeb752e3649e0636de08e3d672e66cb90282010100ad93e4c31072b063fc5ab5fe22afacece775c795d0efdf7c704cfc027bde0d626a7646fc905bb5a80117e3ca49059af14e0160089f9190065be9bfecf12c3b2145b211c8e89e42dd91c38e9aa23ca73697063564f6f6aa6590088a738722df056004d18d7bccac62b3bafef6172fc2a4b071ea37f31eff7a076bcab7dd144e51a9da8754219352aef2c73478971539fa41de4759285ea626fa3c72e7085be47d554d915bbb5149cb6ef835351f231043049cd941506a034bf2f8767f3e1e42ead92f91cb3d75549b57ef7d56ac39c2d80d67f6a2b4ca192974bfc5060e2dd171217971002193dba12e7e4133ab201f07500a90495a38610279b13a48d54f0c99028201003e3a1ac0c2b67d54ed5c4bbe04a7db99103659d33a4f9d35809e1f60c282e5988dddc964527f3b05e6cc890eab3dcb571d66debf3a5527704c87264b3954d7265f4e8d2c637dd89b491b9cf23f264801f804b90454d65af0c4c830d1aef76f597ef61b26ca857ecce9cb78d4f6c2218c00d2975d46c2b013fbf59b750c3b92d8d3ed9e6d1fd0ef1ec091a5c286a3fe2dead292f40f380065731e2079ebb9f2a7ef2c415ecbb488da98f3a12609ca1b6ec8c734032c8bd513292ff842c375d4acd1b02dfb206b24cd815f8e2f9d4af8e7dea0370b19c1b23cc531d78b40e06e1119ee2e08f6f31c6e2e8444c568d13c5d451a291ae0c9f1d4f27d23b3a00d60ad"
896        ))
897            .unwrap();
898        let pub_key = PublicKey::try_decode_protobuf(&hex_literal::hex!(
899            "080012a60430820222300d06092a864886f70d01010105000382020f003082020a0282020100e1beab071d08200bde24eef00d049449b07770ff9910257b2d7d5dda242ce8f0e2f12e1af4b32d9efd2c090f66b0f29986dbb645dae9880089704a94e5066d594162ae6ee8892e6ec70701db0a6c445c04778eb3de1293aa1a23c3825b85c6620a2bc3f82f9b0c309bc0ab3aeb1873282bebd3da03c33e76c21e9beb172fd44c9e43be32e2c99827033cf8d0f0c606f4579326c930eb4e854395ad941256542c793902185153c474bed109d6ff5141ebf9cd256cf58893a37f83729f97e7cb435ec679d2e33901d27bb35aa0d7e20561da08885ef0abbf8e2fb48d6a5487047a9ecb1ad41fa7ed84f6e3e8ecd5d98b3982d2a901b4454991766da295ab78822add5612a2df83bcee814cf50973e80d7ef38111b1bd87da2ae92438a2c8cbcc70b31ee319939a3b9c761dbc13b5c086d6b64bf7ae7dacc14622375d92a8ff9af7eb962162bbddebf90acb32adb5e4e4029f1c96019949ecfbfeffd7ac1e3fbcc6b6168c34be3d5a2e5999fcbb39bba7adbca78eab09b9bc39f7fa4b93411f4cc175e70c0a083e96bfaefb04a9580b4753c1738a6a760ae1afd851a1a4bdad231cf56e9284d832483df215a46c1c21bdf0c6cfe951c18f1ee4078c79c13d63edb6e14feaeffabc90ad317e4875fe648101b0864097e998f0ca3025ef9638cd2b0caecd3770ab54a1d9c6ca959b0f5dcbc90caeefc4135baca6fd475224269bbe1b0203010001"
900        ))
901            .unwrap();
902
903        assert_eq!(priv_key.public(), pub_key);
904    }
905
906    #[test]
907    fn public_key_implements_hash() {
908        use std::hash::Hash;
909
910        use crate::PublicKey;
911
912        fn assert_implements_hash<T: Hash>() {}
913
914        assert_implements_hash::<PublicKey>();
915    }
916
917    #[test]
918    fn public_key_implements_ord() {
919        use std::cmp::Ord;
920
921        use crate::PublicKey;
922
923        fn assert_implements_ord<T: Ord>() {}
924
925        assert_implements_ord::<PublicKey>();
926    }
927
928    #[test]
929    #[cfg(all(feature = "ed25519", feature = "rand"))]
930    fn test_publickey_from_ed25519_public_key() {
931        let pubkey = Keypair::generate_ed25519().public();
932        let ed25519_pubkey = pubkey
933            .clone()
934            .try_into_ed25519()
935            .expect("A ed25519 keypair");
936
937        let converted_pubkey = PublicKey::from(ed25519_pubkey);
938
939        assert_eq!(converted_pubkey, pubkey);
940        assert_eq!(converted_pubkey.key_type(), KeyType::Ed25519)
941    }
942
943    #[test]
944    #[cfg(all(feature = "secp256k1", feature = "rand"))]
945    fn test_publickey_from_secp256k1_public_key() {
946        let pubkey = Keypair::generate_secp256k1().public();
947        let secp256k1_pubkey = pubkey
948            .clone()
949            .try_into_secp256k1()
950            .expect("A secp256k1 keypair");
951        let converted_pubkey = PublicKey::from(secp256k1_pubkey);
952
953        assert_eq!(converted_pubkey, pubkey);
954        assert_eq!(converted_pubkey.key_type(), KeyType::Secp256k1)
955    }
956
957    #[test]
958    #[cfg(all(feature = "ecdsa", feature = "rand"))]
959    fn test_publickey_from_ecdsa_public_key() {
960        let pubkey = Keypair::generate_ecdsa().public();
961        let ecdsa_pubkey = pubkey.clone().try_into_ecdsa().expect("A ecdsa keypair");
962        let converted_pubkey = PublicKey::from(ecdsa_pubkey);
963
964        assert_eq!(converted_pubkey, pubkey);
965        assert_eq!(converted_pubkey.key_type(), KeyType::Ecdsa)
966    }
967
968    #[test]
969    #[cfg(feature = "ecdsa")]
970    fn test_secret_from_ecdsa_private_key() {
971        let keypair = Keypair::generate_ecdsa();
972        assert!(keypair.derive_secret(b"domain separator!").is_some())
973    }
974}