casper_types/crypto/
asymmetric_key.rs

1//! Asymmetric key types and methods on them
2
3use alloc::{
4    format,
5    string::{String, ToString},
6    vec::Vec,
7};
8use core::{
9    cmp::Ordering,
10    convert::TryFrom,
11    fmt::{self, Debug, Display, Formatter},
12    hash::{Hash, Hasher},
13    iter,
14    marker::Copy,
15};
16#[cfg(any(feature = "testing", test))]
17use rand::distributions::{Distribution, Standard};
18#[cfg(any(feature = "std-fs-io", test))]
19use std::path::Path;
20
21#[cfg(feature = "datasize")]
22use datasize::DataSize;
23#[cfg(any(feature = "std", test))]
24use derp::{Der, Tag};
25use ed25519_dalek::{
26    Signature as Ed25519Signature, SigningKey as Ed25519SecretKey,
27    VerifyingKey as Ed25519PublicKey, PUBLIC_KEY_LENGTH as ED25519_PUBLIC_KEY_LENGTH,
28    SECRET_KEY_LENGTH as ED25519_SECRET_KEY_LENGTH, SIGNATURE_LENGTH as ED25519_SIGNATURE_LENGTH,
29};
30use hex_fmt::HexFmt;
31use k256::ecdsa::{
32    signature::{Signer, Verifier},
33    RecoveryId, Signature as Secp256k1Signature, SigningKey as Secp256k1SecretKey, VerifyingKey,
34    VerifyingKey as Secp256k1PublicKey,
35};
36#[cfg(feature = "json-schema")]
37use once_cell::sync::Lazy;
38#[cfg(any(feature = "std", test))]
39use pem::Pem;
40#[cfg(any(feature = "testing", test))]
41use rand::{Rng, RngCore};
42#[cfg(feature = "json-schema")]
43use schemars::{gen::SchemaGenerator, schema::Schema, JsonSchema};
44use serde::{Deserialize, Deserializer, Serialize, Serializer};
45#[cfg(feature = "json-schema")]
46use serde_json::json;
47#[cfg(any(feature = "std", test))]
48use untrusted::Input;
49
50#[cfg(any(feature = "std", feature = "testing", test))]
51use crate::crypto::ErrorExt;
52#[cfg(any(feature = "std-fs-io", test))]
53use crate::file_utils::{read_file, write_file, write_private_file};
54#[cfg(any(feature = "testing", test))]
55use crate::testing::TestRng;
56use crate::{
57    account::AccountHash,
58    bytesrepr,
59    bytesrepr::{FromBytes, ToBytes, U8_SERIALIZED_LENGTH},
60    checksummed_hex,
61    crypto::Error,
62    CLType, CLTyped, Tagged,
63};
64
65#[cfg(any(feature = "testing", test))]
66pub mod gens;
67#[cfg(test)]
68mod tests;
69
70const TAG_LENGTH: usize = U8_SERIALIZED_LENGTH;
71
72/// Tag for system variant.
73pub const SYSTEM_TAG: u8 = 0;
74const SYSTEM: &str = "System";
75
76/// Tag for ed25519 variant.
77pub const ED25519_TAG: u8 = 1;
78const ED25519: &str = "Ed25519";
79
80/// Tag for secp256k1 variant.
81pub const SECP256K1_TAG: u8 = 2;
82const SECP256K1: &str = "Secp256k1";
83
84const SECP256K1_SECRET_KEY_LENGTH: usize = 32;
85const SECP256K1_COMPRESSED_PUBLIC_KEY_LENGTH: usize = 33;
86const SECP256K1_SIGNATURE_LENGTH: usize = 64;
87
88/// Public key for system account.
89pub const SYSTEM_ACCOUNT: PublicKey = PublicKey::System;
90
91// See https://www.secg.org/sec1-v2.pdf#subsection.C.4
92#[cfg(any(feature = "std", test))]
93const EC_PUBLIC_KEY_OBJECT_IDENTIFIER: [u8; 7] = [42, 134, 72, 206, 61, 2, 1];
94
95// See https://tools.ietf.org/html/rfc8410#section-10.3
96#[cfg(any(feature = "std", test))]
97const ED25519_OBJECT_IDENTIFIER: [u8; 3] = [43, 101, 112];
98#[cfg(any(feature = "std", test))]
99const ED25519_PEM_SECRET_KEY_TAG: &str = "PRIVATE KEY";
100#[cfg(any(feature = "std", test))]
101const ED25519_PEM_PUBLIC_KEY_TAG: &str = "PUBLIC KEY";
102
103// Ref?
104#[cfg(any(feature = "std", test))]
105const SECP256K1_OBJECT_IDENTIFIER: [u8; 5] = [43, 129, 4, 0, 10];
106#[cfg(any(feature = "std", test))]
107const SECP256K1_PEM_SECRET_KEY_TAG: &str = "EC PRIVATE KEY";
108#[cfg(any(feature = "std", test))]
109const SECP256K1_PEM_PUBLIC_KEY_TAG: &str = "PUBLIC KEY";
110
111#[cfg(feature = "json-schema")]
112static ED25519_SECRET_KEY: Lazy<SecretKey> = Lazy::new(|| {
113    let bytes = [15u8; SecretKey::ED25519_LENGTH];
114    SecretKey::ed25519_from_bytes(bytes).unwrap()
115});
116
117#[cfg(feature = "json-schema")]
118static ED25519_PUBLIC_KEY: Lazy<PublicKey> = Lazy::new(|| {
119    let bytes = [15u8; SecretKey::ED25519_LENGTH];
120    let secret_key = SecretKey::ed25519_from_bytes(bytes).unwrap();
121    PublicKey::from(&secret_key)
122});
123
124/// Operations on asymmetric cryptographic type.
125pub trait AsymmetricType<'a>
126where
127    Self: 'a + Sized + Tagged<u8>,
128    Vec<u8>: From<&'a Self>,
129{
130    /// Converts `self` to hex, where the first byte represents the algorithm tag.
131    fn to_hex(&'a self) -> String {
132        let bytes = iter::once(self.tag())
133            .chain(Vec::<u8>::from(self))
134            .collect::<Vec<u8>>();
135        base16::encode_lower(&bytes)
136    }
137
138    /// Tries to decode `Self` from its hex-representation.  The hex format should be as produced
139    /// by `AsymmetricType::to_hex()`.
140    fn from_hex<A: AsRef<[u8]>>(input: A) -> Result<Self, Error> {
141        if input.as_ref().len() < 2 {
142            return Err(Error::AsymmetricKey(
143                "failed to decode from hex: too short".to_string(),
144            ));
145        }
146
147        let (tag_hex, key_hex) = input.as_ref().split_at(2);
148
149        let tag = checksummed_hex::decode(tag_hex)?;
150        let key_bytes = checksummed_hex::decode(key_hex)?;
151
152        match tag[0] {
153            SYSTEM_TAG => {
154                if key_bytes.is_empty() {
155                    Ok(Self::system())
156                } else {
157                    Err(Error::AsymmetricKey(
158                        "failed to decode from hex: invalid system variant".to_string(),
159                    ))
160                }
161            }
162            ED25519_TAG => Self::ed25519_from_bytes(&key_bytes),
163            SECP256K1_TAG => Self::secp256k1_from_bytes(&key_bytes),
164            _ => Err(Error::AsymmetricKey(format!(
165                "failed to decode from hex: invalid tag.  Expected {}, {} or {}, got {}",
166                SYSTEM_TAG, ED25519_TAG, SECP256K1_TAG, tag[0]
167            ))),
168        }
169    }
170
171    /// Constructs a new system variant.
172    fn system() -> Self;
173
174    /// Constructs a new ed25519 variant from a byte slice.
175    fn ed25519_from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, Error>;
176
177    /// Constructs a new secp256k1 variant from a byte slice.
178    fn secp256k1_from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, Error>;
179}
180
181/// A secret or private asymmetric key.
182#[cfg_attr(feature = "datasize", derive(DataSize))]
183#[non_exhaustive]
184pub enum SecretKey {
185    /// System secret key.
186    System,
187    /// Ed25519 secret key.
188    #[cfg_attr(feature = "datasize", data_size(skip))]
189    // Manually verified to have no data on the heap.
190    Ed25519(Ed25519SecretKey),
191    /// secp256k1 secret key.
192    #[cfg_attr(feature = "datasize", data_size(skip))]
193    Secp256k1(Secp256k1SecretKey),
194}
195
196impl SecretKey {
197    /// The length in bytes of a system secret key.
198    pub const SYSTEM_LENGTH: usize = 0;
199
200    /// The length in bytes of an Ed25519 secret key.
201    pub const ED25519_LENGTH: usize = ED25519_SECRET_KEY_LENGTH;
202
203    /// The length in bytes of a secp256k1 secret key.
204    pub const SECP256K1_LENGTH: usize = SECP256K1_SECRET_KEY_LENGTH;
205
206    /// Constructs a new system variant.
207    pub fn system() -> Self {
208        SecretKey::System
209    }
210
211    /// Constructs a new ed25519 variant from a byte slice.
212    pub fn ed25519_from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, Error> {
213        Ok(SecretKey::Ed25519(Ed25519SecretKey::try_from(
214            bytes.as_ref(),
215        )?))
216    }
217
218    /// Constructs a new secp256k1 variant from a byte slice.
219    pub fn secp256k1_from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, Error> {
220        Ok(SecretKey::Secp256k1(Secp256k1SecretKey::from_slice(
221            bytes.as_ref(),
222        )?))
223    }
224
225    /// Generates a new ed25519 variant using the system's secure random number generator.
226    #[cfg(any(feature = "std", feature = "testing", test))]
227    pub fn generate_ed25519() -> Result<Self, ErrorExt> {
228        let mut bytes = [0u8; Self::ED25519_LENGTH];
229        getrandom::getrandom(&mut bytes[..])?;
230        SecretKey::ed25519_from_bytes(bytes).map_err(Into::into)
231    }
232
233    /// Generates a new secp256k1 variant using the system's secure random number generator.
234    #[cfg(any(feature = "std", feature = "testing", test))]
235    pub fn generate_secp256k1() -> Result<Self, ErrorExt> {
236        let mut bytes = [0u8; Self::SECP256K1_LENGTH];
237        getrandom::getrandom(&mut bytes[..])?;
238        SecretKey::secp256k1_from_bytes(bytes).map_err(Into::into)
239    }
240
241    /// Attempts to write the key bytes to the configured file path.
242    #[cfg(any(feature = "std-fs-io", test))]
243    pub fn to_file<P: AsRef<Path>>(&self, file: P) -> Result<(), ErrorExt> {
244        write_private_file(file, self.to_pem()?).map_err(ErrorExt::SecretKeySave)
245    }
246
247    /// Attempts to read the key bytes from configured file path.
248    #[cfg(any(feature = "std-fs-io", test))]
249    pub fn from_file<P: AsRef<Path>>(file: P) -> Result<Self, ErrorExt> {
250        let data = read_file(file).map_err(ErrorExt::SecretKeyLoad)?;
251        Self::from_pem(data)
252    }
253
254    /// DER encodes a key.
255    #[cfg(any(feature = "std", test))]
256    pub fn to_der(&self) -> Result<Vec<u8>, ErrorExt> {
257        match self {
258            SecretKey::System => Err(Error::System(String::from("to_der")).into()),
259            SecretKey::Ed25519(secret_key) => {
260                // See https://tools.ietf.org/html/rfc8410#section-10.3
261                let mut key_bytes = vec![];
262                let mut der = Der::new(&mut key_bytes);
263                der.octet_string(&secret_key.to_bytes())?;
264
265                let mut encoded = vec![];
266                der = Der::new(&mut encoded);
267                der.sequence(|der| {
268                    der.integer(&[0])?;
269                    der.sequence(|der| der.oid(&ED25519_OBJECT_IDENTIFIER))?;
270                    der.octet_string(&key_bytes)
271                })?;
272                Ok(encoded)
273            }
274            SecretKey::Secp256k1(secret_key) => {
275                // See https://www.secg.org/sec1-v2.pdf#subsection.C.4
276                let mut oid_bytes = vec![];
277                let mut der = Der::new(&mut oid_bytes);
278                der.oid(&SECP256K1_OBJECT_IDENTIFIER)?;
279
280                let mut encoded = vec![];
281                der = Der::new(&mut encoded);
282                der.sequence(|der| {
283                    der.integer(&[1])?;
284                    der.octet_string(secret_key.to_bytes().as_slice())?;
285                    der.element(Tag::ContextSpecificConstructed0, &oid_bytes)
286                })?;
287                Ok(encoded)
288            }
289        }
290    }
291
292    /// Decodes a key from a DER-encoded slice.
293    #[cfg(any(feature = "std", test))]
294    pub fn from_der<T: AsRef<[u8]>>(input: T) -> Result<Self, ErrorExt> {
295        let input = Input::from(input.as_ref());
296
297        let (key_type_tag, raw_bytes) = input.read_all(derp::Error::Read, |input| {
298            derp::nested(input, Tag::Sequence, |input| {
299                // Safe to ignore the first value which should be an integer.
300                let version_slice =
301                    derp::expect_tag_and_get_value(input, Tag::Integer)?.as_slice_less_safe();
302                if version_slice.len() != 1 {
303                    return Err(derp::Error::NonZeroUnusedBits);
304                }
305                let version = version_slice[0];
306
307                // Read the next value.
308                let (tag, value) = derp::read_tag_and_get_value(input)?;
309                if tag == Tag::Sequence as u8 {
310                    // Expecting an Ed25519 key.
311                    if version != 0 {
312                        return Err(derp::Error::WrongValue);
313                    }
314
315                    // The sequence should have one element: an object identifier defining Ed25519.
316                    let object_identifier = value.read_all(derp::Error::Read, |input| {
317                        derp::expect_tag_and_get_value(input, Tag::Oid)
318                    })?;
319                    if object_identifier.as_slice_less_safe() != ED25519_OBJECT_IDENTIFIER {
320                        return Err(derp::Error::WrongValue);
321                    }
322
323                    // The third and final value should be the raw bytes of the secret key as an
324                    // octet string in an octet string.
325                    let raw_bytes = derp::nested(input, Tag::OctetString, |input| {
326                        derp::expect_tag_and_get_value(input, Tag::OctetString)
327                    })?
328                    .as_slice_less_safe();
329
330                    return Ok((ED25519_TAG, raw_bytes));
331                } else if tag == Tag::OctetString as u8 {
332                    // Expecting a secp256k1 key.
333                    if version != 1 {
334                        return Err(derp::Error::WrongValue);
335                    }
336
337                    // The octet string is the secret key.
338                    let raw_bytes = value.as_slice_less_safe();
339
340                    // The object identifier is next.
341                    let parameter0 =
342                        derp::expect_tag_and_get_value(input, Tag::ContextSpecificConstructed0)?;
343                    let object_identifier = parameter0.read_all(derp::Error::Read, |input| {
344                        derp::expect_tag_and_get_value(input, Tag::Oid)
345                    })?;
346                    if object_identifier.as_slice_less_safe() != SECP256K1_OBJECT_IDENTIFIER {
347                        return Err(derp::Error::WrongValue);
348                    }
349
350                    // There might be an optional public key as the final value, but we're not
351                    // interested in parsing that.  Read it to ensure `input.read_all` doesn't fail
352                    // with unused bytes error.
353                    let _ = derp::read_tag_and_get_value(input);
354
355                    return Ok((SECP256K1_TAG, raw_bytes));
356                }
357
358                Err(derp::Error::WrongValue)
359            })
360        })?;
361
362        match key_type_tag {
363            SYSTEM_TAG => Err(Error::AsymmetricKey("cannot construct variant".to_string()).into()),
364            ED25519_TAG => SecretKey::ed25519_from_bytes(raw_bytes).map_err(Into::into),
365            SECP256K1_TAG => SecretKey::secp256k1_from_bytes(raw_bytes).map_err(Into::into),
366            _ => Err(Error::AsymmetricKey("unknown type tag".to_string()).into()),
367        }
368    }
369
370    /// PEM encodes a key.
371    #[cfg(any(feature = "std", test))]
372    pub fn to_pem(&self) -> Result<String, ErrorExt> {
373        let tag = match self {
374            SecretKey::System => return Err(Error::System(String::from("to_pem")).into()),
375            SecretKey::Ed25519(_) => ED25519_PEM_SECRET_KEY_TAG.to_string(),
376            SecretKey::Secp256k1(_) => SECP256K1_PEM_SECRET_KEY_TAG.to_string(),
377        };
378        let contents = self.to_der()?;
379        let pem = Pem { tag, contents };
380        Ok(pem::encode(&pem))
381    }
382
383    /// Decodes a key from a PEM-encoded slice.
384    #[cfg(any(feature = "std", test))]
385    pub fn from_pem<T: AsRef<[u8]>>(input: T) -> Result<Self, ErrorExt> {
386        let pem = pem::parse(input)?;
387
388        let secret_key = Self::from_der(&pem.contents)?;
389
390        let bad_tag = |expected_tag: &str| {
391            ErrorExt::FromPem(format!(
392                "invalid tag: expected {}, got {}",
393                expected_tag, pem.tag
394            ))
395        };
396
397        match secret_key {
398            SecretKey::System => return Err(Error::System(String::from("from_pem")).into()),
399            SecretKey::Ed25519(_) => {
400                if pem.tag != ED25519_PEM_SECRET_KEY_TAG {
401                    return Err(bad_tag(ED25519_PEM_SECRET_KEY_TAG));
402                }
403            }
404            SecretKey::Secp256k1(_) => {
405                if pem.tag != SECP256K1_PEM_SECRET_KEY_TAG {
406                    return Err(bad_tag(SECP256K1_PEM_SECRET_KEY_TAG));
407                }
408            }
409        }
410
411        Ok(secret_key)
412    }
413
414    /// Returns a random `SecretKey`.
415    #[cfg(any(feature = "testing", test))]
416    pub fn random(rng: &mut TestRng) -> Self {
417        if rng.gen() {
418            Self::random_ed25519(rng)
419        } else {
420            Self::random_secp256k1(rng)
421        }
422    }
423
424    /// Returns a random Ed25519 variant of `SecretKey`.
425    #[cfg(any(feature = "testing", test))]
426    pub fn random_ed25519(rng: &mut TestRng) -> Self {
427        let mut bytes = [0u8; Self::ED25519_LENGTH];
428        rng.fill_bytes(&mut bytes[..]);
429        SecretKey::ed25519_from_bytes(bytes).unwrap()
430    }
431
432    /// Returns a random secp256k1 variant of `SecretKey`.
433    #[cfg(any(feature = "testing", test))]
434    pub fn random_secp256k1(rng: &mut TestRng) -> Self {
435        let mut bytes = [0u8; Self::SECP256K1_LENGTH];
436        rng.fill_bytes(&mut bytes[..]);
437        SecretKey::secp256k1_from_bytes(bytes).unwrap()
438    }
439
440    // This method is not intended to be used by third party crates.
441    #[doc(hidden)]
442    #[cfg(feature = "json-schema")]
443    pub fn example() -> &'static Self {
444        &ED25519_SECRET_KEY
445    }
446
447    fn variant_name(&self) -> &str {
448        match self {
449            SecretKey::System => SYSTEM,
450            SecretKey::Ed25519(_) => ED25519,
451            SecretKey::Secp256k1(_) => SECP256K1,
452        }
453    }
454}
455
456impl Debug for SecretKey {
457    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
458        write!(formatter, "SecretKey::{}", self.variant_name())
459    }
460}
461
462impl Display for SecretKey {
463    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
464        <Self as Debug>::fmt(self, formatter)
465    }
466}
467
468impl Tagged<u8> for SecretKey {
469    fn tag(&self) -> u8 {
470        match self {
471            SecretKey::System => SYSTEM_TAG,
472            SecretKey::Ed25519(_) => ED25519_TAG,
473            SecretKey::Secp256k1(_) => SECP256K1_TAG,
474        }
475    }
476}
477
478/// A public asymmetric key.
479#[derive(Clone, Eq, PartialEq)]
480#[cfg_attr(feature = "datasize", derive(DataSize))]
481#[non_exhaustive]
482pub enum PublicKey {
483    /// System public key.
484    System,
485    /// Ed25519 public key.
486    #[cfg_attr(feature = "datasize", data_size(skip))]
487    Ed25519(Ed25519PublicKey),
488    /// secp256k1 public key.
489    #[cfg_attr(feature = "datasize", data_size(skip))]
490    Secp256k1(Secp256k1PublicKey),
491}
492
493impl PublicKey {
494    /// The length in bytes of a system public key.
495    pub const SYSTEM_LENGTH: usize = 0;
496
497    /// The length in bytes of an Ed25519 public key.
498    pub const ED25519_LENGTH: usize = ED25519_PUBLIC_KEY_LENGTH;
499
500    /// The length in bytes of a secp256k1 public key.
501    pub const SECP256K1_LENGTH: usize = SECP256K1_COMPRESSED_PUBLIC_KEY_LENGTH;
502
503    /// Creates an `AccountHash` from a given `PublicKey` instance.
504    pub fn to_account_hash(&self) -> AccountHash {
505        AccountHash::from(self)
506    }
507
508    /// Hexadecimal representation of the key.
509    pub fn to_hex_string(&self) -> String {
510        self.to_hex()
511    }
512
513    /// Returns `true` if this public key is of the `System` variant.
514    pub fn is_system(&self) -> bool {
515        matches!(self, PublicKey::System)
516    }
517
518    /// Attempts to write the key bytes to the configured file path.
519    #[cfg(any(feature = "std-fs-io", test))]
520    pub fn to_file<P: AsRef<Path>>(&self, file: P) -> Result<(), ErrorExt> {
521        write_file(file, self.to_pem()?).map_err(ErrorExt::PublicKeySave)
522    }
523
524    /// Attempts to read the key bytes from configured file path.
525    #[cfg(any(feature = "std-fs-io", test))]
526    pub fn from_file<P: AsRef<Path>>(file: P) -> Result<Self, ErrorExt> {
527        let data = read_file(file).map_err(ErrorExt::PublicKeyLoad)?;
528        Self::from_pem(data)
529    }
530
531    /// DER encodes a key.
532    #[cfg(any(feature = "std", test))]
533    pub fn to_der(&self) -> Result<Vec<u8>, ErrorExt> {
534        match self {
535            PublicKey::System => Err(Error::System(String::from("to_der")).into()),
536            PublicKey::Ed25519(public_key) => {
537                // See https://tools.ietf.org/html/rfc8410#section-10.1
538                let mut encoded = vec![];
539                let mut der = Der::new(&mut encoded);
540                der.sequence(|der| {
541                    der.sequence(|der| der.oid(&ED25519_OBJECT_IDENTIFIER))?;
542                    der.bit_string(0, public_key.as_ref())
543                })?;
544                Ok(encoded)
545            }
546            PublicKey::Secp256k1(public_key) => {
547                // See https://www.secg.org/sec1-v2.pdf#subsection.C.3
548                let mut encoded = vec![];
549                let mut der = Der::new(&mut encoded);
550                der.sequence(|der| {
551                    der.sequence(|der| {
552                        der.oid(&EC_PUBLIC_KEY_OBJECT_IDENTIFIER)?;
553                        der.oid(&SECP256K1_OBJECT_IDENTIFIER)
554                    })?;
555                    der.bit_string(0, public_key.to_encoded_point(true).as_ref())
556                })?;
557                Ok(encoded)
558            }
559        }
560    }
561
562    /// Decodes a key from a DER-encoded slice.
563    #[cfg(any(feature = "std", test))]
564    pub fn from_der<T: AsRef<[u8]>>(input: T) -> Result<Self, ErrorExt> {
565        let input = Input::from(input.as_ref());
566
567        let mut key_type_tag = ED25519_TAG;
568        let raw_bytes = input.read_all(derp::Error::Read, |input| {
569            derp::nested(input, Tag::Sequence, |input| {
570                derp::nested(input, Tag::Sequence, |input| {
571                    // Read the first value.
572                    let object_identifier =
573                        derp::expect_tag_and_get_value(input, Tag::Oid)?.as_slice_less_safe();
574                    if object_identifier == ED25519_OBJECT_IDENTIFIER {
575                        key_type_tag = ED25519_TAG;
576                        Ok(())
577                    } else if object_identifier == EC_PUBLIC_KEY_OBJECT_IDENTIFIER {
578                        // Assert the next object identifier is the secp256k1 ID.
579                        let next_object_identifier =
580                            derp::expect_tag_and_get_value(input, Tag::Oid)?.as_slice_less_safe();
581                        if next_object_identifier != SECP256K1_OBJECT_IDENTIFIER {
582                            return Err(derp::Error::WrongValue);
583                        }
584
585                        key_type_tag = SECP256K1_TAG;
586                        Ok(())
587                    } else {
588                        Err(derp::Error::WrongValue)
589                    }
590                })?;
591                Ok(derp::bit_string_with_no_unused_bits(input)?.as_slice_less_safe())
592            })
593        })?;
594
595        match key_type_tag {
596            ED25519_TAG => PublicKey::ed25519_from_bytes(raw_bytes).map_err(Into::into),
597            SECP256K1_TAG => PublicKey::secp256k1_from_bytes(raw_bytes).map_err(Into::into),
598            _ => unreachable!(),
599        }
600    }
601
602    /// PEM encodes a key.
603    #[cfg(any(feature = "std", test))]
604    pub fn to_pem(&self) -> Result<String, ErrorExt> {
605        let tag = match self {
606            PublicKey::System => return Err(Error::System(String::from("to_pem")).into()),
607            PublicKey::Ed25519(_) => ED25519_PEM_PUBLIC_KEY_TAG.to_string(),
608            PublicKey::Secp256k1(_) => SECP256K1_PEM_PUBLIC_KEY_TAG.to_string(),
609        };
610        let contents = self.to_der()?;
611        let pem = Pem { tag, contents };
612        Ok(pem::encode(&pem))
613    }
614
615    /// Decodes a key from a PEM-encoded slice.
616    #[cfg(any(feature = "std", test))]
617    pub fn from_pem<T: AsRef<[u8]>>(input: T) -> Result<Self, ErrorExt> {
618        let pem = pem::parse(input)?;
619        let public_key = Self::from_der(&pem.contents)?;
620        let bad_tag = |expected_tag: &str| {
621            ErrorExt::FromPem(format!(
622                "invalid tag: expected {}, got {}",
623                expected_tag, pem.tag
624            ))
625        };
626        match public_key {
627            PublicKey::System => return Err(Error::System(String::from("from_pem")).into()),
628            PublicKey::Ed25519(_) => {
629                if pem.tag != ED25519_PEM_PUBLIC_KEY_TAG {
630                    return Err(bad_tag(ED25519_PEM_PUBLIC_KEY_TAG));
631                }
632            }
633            PublicKey::Secp256k1(_) => {
634                if pem.tag != SECP256K1_PEM_PUBLIC_KEY_TAG {
635                    return Err(bad_tag(SECP256K1_PEM_PUBLIC_KEY_TAG));
636                }
637            }
638        }
639        Ok(public_key)
640    }
641
642    /// Returns a random `PublicKey`.
643    #[cfg(any(feature = "testing", test))]
644    pub fn random(rng: &mut TestRng) -> Self {
645        let secret_key = SecretKey::random(rng);
646        PublicKey::from(&secret_key)
647    }
648
649    /// Returns a random Ed25519 variant of `PublicKey`.
650    #[cfg(any(feature = "testing", test))]
651    pub fn random_ed25519(rng: &mut TestRng) -> Self {
652        let secret_key = SecretKey::random_ed25519(rng);
653        PublicKey::from(&secret_key)
654    }
655
656    /// Returns a random secp256k1 variant of `PublicKey`.
657    #[cfg(any(feature = "testing", test))]
658    pub fn random_secp256k1(rng: &mut TestRng) -> Self {
659        let secret_key = SecretKey::random_secp256k1(rng);
660        PublicKey::from(&secret_key)
661    }
662
663    // This method is not intended to be used by third party crates.
664    #[doc(hidden)]
665    #[cfg(feature = "json-schema")]
666    pub fn example() -> &'static Self {
667        &ED25519_PUBLIC_KEY
668    }
669
670    fn variant_name(&self) -> &str {
671        match self {
672            PublicKey::System => SYSTEM,
673            PublicKey::Ed25519(_) => ED25519,
674            PublicKey::Secp256k1(_) => SECP256K1,
675        }
676    }
677}
678
679impl AsymmetricType<'_> for PublicKey {
680    fn system() -> Self {
681        PublicKey::System
682    }
683
684    fn ed25519_from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, Error> {
685        Ok(PublicKey::Ed25519(Ed25519PublicKey::try_from(
686            bytes.as_ref(),
687        )?))
688    }
689
690    fn secp256k1_from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, Error> {
691        Ok(PublicKey::Secp256k1(
692            Secp256k1PublicKey::from_sec1_bytes(bytes.as_ref())
693                .map_err(|_| Error::SignatureError)?,
694        ))
695    }
696}
697
698impl From<&SecretKey> for PublicKey {
699    fn from(secret_key: &SecretKey) -> PublicKey {
700        match secret_key {
701            SecretKey::System => PublicKey::System,
702            SecretKey::Ed25519(secret_key) => PublicKey::Ed25519(secret_key.into()),
703            SecretKey::Secp256k1(secret_key) => PublicKey::Secp256k1(secret_key.into()),
704        }
705    }
706}
707
708#[cfg(any(feature = "testing", test))]
709impl Distribution<PublicKey> for Standard {
710    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> PublicKey {
711        let secret_key = if rng.gen() {
712            SecretKey::generate_ed25519().unwrap()
713        } else {
714            SecretKey::generate_secp256k1().unwrap()
715        };
716        PublicKey::from(&secret_key)
717    }
718}
719
720#[cfg(any(feature = "testing", test))]
721impl PartialEq for SecretKey {
722    fn eq(&self, other: &Self) -> bool {
723        match (self, other) {
724            (Self::System, Self::System) => true,
725            (Self::Ed25519(k1), Self::Ed25519(k2)) => k1.to_bytes() == k2.to_bytes(),
726            (Self::Secp256k1(k1), Self::Secp256k1(k2)) => k1.to_bytes() == k2.to_bytes(),
727            _ => false,
728        }
729    }
730}
731#[cfg(any(feature = "testing", test))]
732impl Eq for SecretKey {}
733
734#[cfg(any(feature = "testing", test))]
735impl Ord for SecretKey {
736    fn cmp(&self, other: &Self) -> Ordering {
737        match (self, other) {
738            (Self::System, Self::System) => Ordering::Equal,
739            (Self::Ed25519(k1), Self::Ed25519(k2)) => k1.to_bytes().cmp(&k2.to_bytes()),
740            (Self::Secp256k1(k1), Self::Secp256k1(k2)) => k1.to_bytes().cmp(&k2.to_bytes()),
741            (k1, k2) => k1.variant_name().cmp(k2.variant_name()),
742        }
743    }
744}
745#[cfg(any(feature = "testing", test))]
746impl PartialOrd for SecretKey {
747    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
748        Some(self.cmp(other))
749    }
750}
751
752impl From<&PublicKey> for Vec<u8> {
753    fn from(public_key: &PublicKey) -> Self {
754        match public_key {
755            PublicKey::System => Vec::new(),
756            PublicKey::Ed25519(key) => key.to_bytes().into(),
757            PublicKey::Secp256k1(key) => key.to_encoded_point(true).as_ref().into(),
758        }
759    }
760}
761
762impl From<PublicKey> for Vec<u8> {
763    fn from(public_key: PublicKey) -> Self {
764        Vec::<u8>::from(&public_key)
765    }
766}
767
768impl Debug for PublicKey {
769    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
770        write!(
771            formatter,
772            "PublicKey::{}({})",
773            self.variant_name(),
774            base16::encode_lower(&Into::<Vec<u8>>::into(self))
775        )
776    }
777}
778
779impl Display for PublicKey {
780    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
781        write!(
782            formatter,
783            "PubKey::{}({:10})",
784            self.variant_name(),
785            HexFmt(Into::<Vec<u8>>::into(self))
786        )
787    }
788}
789
790impl PartialOrd for PublicKey {
791    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
792        Some(self.cmp(other))
793    }
794}
795
796impl Ord for PublicKey {
797    fn cmp(&self, other: &Self) -> Ordering {
798        let self_tag = self.tag();
799        let other_tag = other.tag();
800        if self_tag == other_tag {
801            Into::<Vec<u8>>::into(self).cmp(&Into::<Vec<u8>>::into(other))
802        } else {
803            self_tag.cmp(&other_tag)
804        }
805    }
806}
807
808// This implementation of `Hash` agrees with the derived `PartialEq`.  It's required since
809// `ed25519_dalek::PublicKey` doesn't implement `Hash`.
810#[allow(clippy::derived_hash_with_manual_eq)]
811impl Hash for PublicKey {
812    fn hash<H: Hasher>(&self, state: &mut H) {
813        self.tag().hash(state);
814        Into::<Vec<u8>>::into(self).hash(state);
815    }
816}
817
818impl Tagged<u8> for PublicKey {
819    fn tag(&self) -> u8 {
820        match self {
821            PublicKey::System => SYSTEM_TAG,
822            PublicKey::Ed25519(_) => ED25519_TAG,
823            PublicKey::Secp256k1(_) => SECP256K1_TAG,
824        }
825    }
826}
827
828impl ToBytes for PublicKey {
829    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
830        let mut buffer = bytesrepr::allocate_buffer(self)?;
831        self.write_bytes(&mut buffer)?;
832        Ok(buffer)
833    }
834
835    fn serialized_length(&self) -> usize {
836        TAG_LENGTH
837            + match self {
838                PublicKey::System => Self::SYSTEM_LENGTH,
839                PublicKey::Ed25519(_) => Self::ED25519_LENGTH,
840                PublicKey::Secp256k1(_) => Self::SECP256K1_LENGTH,
841            }
842    }
843
844    fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
845        match self {
846            PublicKey::System => writer.push(SYSTEM_TAG),
847            PublicKey::Ed25519(public_key) => {
848                writer.push(ED25519_TAG);
849                writer.extend_from_slice(public_key.as_bytes());
850            }
851            PublicKey::Secp256k1(public_key) => {
852                writer.push(SECP256K1_TAG);
853                writer.extend_from_slice(public_key.to_encoded_point(true).as_ref());
854            }
855        }
856        Ok(())
857    }
858}
859
860impl FromBytes for PublicKey {
861    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
862        let (tag, remainder) = u8::from_bytes(bytes)?;
863        match tag {
864            SYSTEM_TAG => Ok((PublicKey::System, remainder)),
865            ED25519_TAG => {
866                let (raw_bytes, remainder): ([u8; Self::ED25519_LENGTH], _) =
867                    FromBytes::from_bytes(remainder)?;
868                let public_key = Self::ed25519_from_bytes(raw_bytes)
869                    .map_err(|_error| bytesrepr::Error::Formatting)?;
870                Ok((public_key, remainder))
871            }
872            SECP256K1_TAG => {
873                let (raw_bytes, remainder): ([u8; Self::SECP256K1_LENGTH], _) =
874                    FromBytes::from_bytes(remainder)?;
875                let public_key = Self::secp256k1_from_bytes(raw_bytes)
876                    .map_err(|_error| bytesrepr::Error::Formatting)?;
877                Ok((public_key, remainder))
878            }
879            _ => Err(bytesrepr::Error::Formatting),
880        }
881    }
882}
883
884impl Serialize for PublicKey {
885    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
886        detail::serialize(self, serializer)
887    }
888}
889
890impl<'de> Deserialize<'de> for PublicKey {
891    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
892        detail::deserialize(deserializer)
893    }
894}
895
896#[cfg(feature = "json-schema")]
897impl JsonSchema for PublicKey {
898    fn schema_name() -> String {
899        String::from("PublicKey")
900    }
901
902    fn json_schema(gen: &mut SchemaGenerator) -> Schema {
903        let schema = gen.subschema_for::<String>();
904        let mut schema_object = schema.into_object();
905        schema_object.metadata().description = Some(
906            "Hex-encoded cryptographic public key, including the algorithm tag prefix.".to_string(),
907        );
908        schema_object.metadata().examples = vec![
909            json!({
910                "name": "SystemPublicKey",
911                "description": "A pseudo public key, used for example when the system proposes an \
912                immediate switch block after a network upgrade rather than a specific validator. \
913                Its hex-encoded value is always '00', as is the corresponding pseudo signature's",
914                "value": "00"
915            }),
916            json!({
917                "name": "Ed25519PublicKey",
918                "description": "An Ed25519 public key. Its hex-encoded value begins '01' and is \
919                followed by 64 characters",
920                "value": "018a88e3dd7409f195fd52db2d3cba5d72ca6709bf1d94121bf3748801b40f6f5c"
921            }),
922            json!({
923                "name": "Secp256k1PublicKey",
924                "description": "A secp256k1 public key. Its hex-encoded value begins '02' and is \
925                followed by 66 characters",
926                "value": "0203408e9526316fd1f8def480dd45b2cc72ffd732771c9ceb5d92ffa4051e6ee084"
927            }),
928        ];
929        schema_object.into()
930    }
931}
932
933impl CLTyped for PublicKey {
934    fn cl_type() -> CLType {
935        CLType::PublicKey
936    }
937}
938
939/// A signature of given data.
940#[derive(Clone, Copy)]
941#[cfg_attr(feature = "datasize", derive(DataSize))]
942#[non_exhaustive]
943pub enum Signature {
944    /// System signature.  Cannot be verified.
945    System,
946    /// Ed25519 signature.
947    #[cfg_attr(feature = "datasize", data_size(skip))]
948    Ed25519(Ed25519Signature),
949    /// Secp256k1 signature.
950    #[cfg_attr(feature = "datasize", data_size(skip))]
951    Secp256k1(Secp256k1Signature),
952}
953
954impl Signature {
955    /// The length in bytes of a system signature,
956    pub const SYSTEM_LENGTH: usize = 0;
957
958    /// The length in bytes of an Ed25519 signature,
959    pub const ED25519_LENGTH: usize = ED25519_SIGNATURE_LENGTH;
960
961    /// The length in bytes of a secp256k1 signature
962    pub const SECP256K1_LENGTH: usize = SECP256K1_SIGNATURE_LENGTH;
963
964    /// Constructs a new Ed25519 variant from a byte array.
965    pub fn ed25519(bytes: [u8; Self::ED25519_LENGTH]) -> Result<Self, Error> {
966        let signature = Ed25519Signature::from_bytes(&bytes);
967        Ok(Signature::Ed25519(signature))
968    }
969
970    /// Constructs a new secp256k1 variant from a byte array.
971    pub fn secp256k1(bytes: [u8; Self::SECP256K1_LENGTH]) -> Result<Self, Error> {
972        let signature = Secp256k1Signature::try_from(&bytes[..]).map_err(|_| {
973            Error::AsymmetricKey(format!(
974                "failed to construct secp256k1 signature from {:?}",
975                &bytes[..]
976            ))
977        })?;
978
979        Ok(Signature::Secp256k1(signature))
980    }
981
982    fn variant_name(&self) -> &str {
983        match self {
984            Signature::System => SYSTEM,
985            Signature::Ed25519(_) => ED25519,
986            Signature::Secp256k1(_) => SECP256K1,
987        }
988    }
989
990    /// Hexadecimal representation of the signature.
991    pub fn to_hex_string(&self) -> String {
992        self.to_hex()
993    }
994}
995
996impl AsymmetricType<'_> for Signature {
997    fn system() -> Self {
998        Signature::System
999    }
1000
1001    fn ed25519_from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, Error> {
1002        let signature = Ed25519Signature::try_from(bytes.as_ref()).map_err(|_| {
1003            Error::AsymmetricKey(format!(
1004                "failed to construct Ed25519 signature from {:?}",
1005                bytes.as_ref()
1006            ))
1007        })?;
1008        Ok(Signature::Ed25519(signature))
1009    }
1010
1011    fn secp256k1_from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, Error> {
1012        let signature = Secp256k1Signature::try_from(bytes.as_ref()).map_err(|_| {
1013            Error::AsymmetricKey(format!(
1014                "failed to construct secp256k1 signature from {:?}",
1015                bytes.as_ref()
1016            ))
1017        })?;
1018        Ok(Signature::Secp256k1(signature))
1019    }
1020}
1021
1022impl Debug for Signature {
1023    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
1024        write!(
1025            formatter,
1026            "Signature::{}({})",
1027            self.variant_name(),
1028            base16::encode_lower(&Into::<Vec<u8>>::into(*self))
1029        )
1030    }
1031}
1032
1033impl Display for Signature {
1034    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
1035        write!(
1036            formatter,
1037            "Sig::{}({:10})",
1038            self.variant_name(),
1039            HexFmt(Into::<Vec<u8>>::into(*self))
1040        )
1041    }
1042}
1043
1044impl PartialOrd for Signature {
1045    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1046        Some(self.cmp(other))
1047    }
1048}
1049
1050impl Ord for Signature {
1051    fn cmp(&self, other: &Self) -> Ordering {
1052        let self_tag = self.tag();
1053        let other_tag = other.tag();
1054        if self_tag == other_tag {
1055            Into::<Vec<u8>>::into(*self).cmp(&Into::<Vec<u8>>::into(*other))
1056        } else {
1057            self_tag.cmp(&other_tag)
1058        }
1059    }
1060}
1061
1062impl PartialEq for Signature {
1063    fn eq(&self, other: &Self) -> bool {
1064        self.tag() == other.tag() && Into::<Vec<u8>>::into(*self) == Into::<Vec<u8>>::into(*other)
1065    }
1066}
1067
1068impl Eq for Signature {}
1069
1070impl Hash for Signature {
1071    fn hash<H: Hasher>(&self, state: &mut H) {
1072        self.tag().hash(state);
1073        Into::<Vec<u8>>::into(*self).hash(state);
1074    }
1075}
1076
1077impl Tagged<u8> for Signature {
1078    fn tag(&self) -> u8 {
1079        match self {
1080            Signature::System => SYSTEM_TAG,
1081            Signature::Ed25519(_) => ED25519_TAG,
1082            Signature::Secp256k1(_) => SECP256K1_TAG,
1083        }
1084    }
1085}
1086
1087impl ToBytes for Signature {
1088    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
1089        let mut buffer = bytesrepr::allocate_buffer(self)?;
1090        self.write_bytes(&mut buffer)?;
1091        Ok(buffer)
1092    }
1093
1094    fn serialized_length(&self) -> usize {
1095        TAG_LENGTH
1096            + match self {
1097                Signature::System => Self::SYSTEM_LENGTH,
1098                Signature::Ed25519(_) => Self::ED25519_LENGTH,
1099                Signature::Secp256k1(_) => Self::SECP256K1_LENGTH,
1100            }
1101    }
1102
1103    fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
1104        match self {
1105            Signature::System => {
1106                writer.push(SYSTEM_TAG);
1107            }
1108            Signature::Ed25519(signature) => {
1109                writer.push(ED25519_TAG);
1110                writer.extend(signature.to_bytes());
1111            }
1112            Signature::Secp256k1(signature) => {
1113                writer.push(SECP256K1_TAG);
1114                writer.extend_from_slice(&signature.to_bytes());
1115            }
1116        }
1117        Ok(())
1118    }
1119}
1120
1121impl FromBytes for Signature {
1122    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
1123        let (tag, remainder) = u8::from_bytes(bytes)?;
1124        match tag {
1125            SYSTEM_TAG => Ok((Signature::System, remainder)),
1126            ED25519_TAG => {
1127                let (raw_bytes, remainder): ([u8; Self::ED25519_LENGTH], _) =
1128                    FromBytes::from_bytes(remainder)?;
1129                let public_key =
1130                    Self::ed25519(raw_bytes).map_err(|_error| bytesrepr::Error::Formatting)?;
1131                Ok((public_key, remainder))
1132            }
1133            SECP256K1_TAG => {
1134                let (raw_bytes, remainder): ([u8; Self::SECP256K1_LENGTH], _) =
1135                    FromBytes::from_bytes(remainder)?;
1136                let public_key =
1137                    Self::secp256k1(raw_bytes).map_err(|_error| bytesrepr::Error::Formatting)?;
1138                Ok((public_key, remainder))
1139            }
1140            _ => Err(bytesrepr::Error::Formatting),
1141        }
1142    }
1143}
1144
1145impl Serialize for Signature {
1146    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1147        detail::serialize(self, serializer)
1148    }
1149}
1150
1151impl<'de> Deserialize<'de> for Signature {
1152    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1153        detail::deserialize(deserializer)
1154    }
1155}
1156
1157impl From<&Signature> for Vec<u8> {
1158    fn from(signature: &Signature) -> Self {
1159        match signature {
1160            Signature::System => Vec::new(),
1161            Signature::Ed25519(signature) => signature.to_bytes().into(),
1162            Signature::Secp256k1(signature) => (*signature.to_bytes()).into(),
1163        }
1164    }
1165}
1166
1167impl From<Signature> for Vec<u8> {
1168    fn from(signature: Signature) -> Self {
1169        Vec::<u8>::from(&signature)
1170    }
1171}
1172
1173#[cfg(feature = "json-schema")]
1174impl JsonSchema for Signature {
1175    fn schema_name() -> String {
1176        String::from("Signature")
1177    }
1178
1179    fn json_schema(gen: &mut SchemaGenerator) -> Schema {
1180        let schema = gen.subschema_for::<String>();
1181        let mut schema_object = schema.into_object();
1182        schema_object.metadata().description = Some(
1183            "Hex-encoded cryptographic signature, including the algorithm tag prefix.".to_string(),
1184        );
1185        schema_object.into()
1186    }
1187}
1188
1189/// Signs the given message using the given key pair.
1190pub fn sign<T: AsRef<[u8]>>(
1191    message: T,
1192    secret_key: &SecretKey,
1193    public_key: &PublicKey,
1194) -> Signature {
1195    match (secret_key, public_key) {
1196        (SecretKey::System, PublicKey::System) => {
1197            panic!("cannot create signature with system keys",)
1198        }
1199        (SecretKey::Ed25519(secret_key), PublicKey::Ed25519(_public_key)) => {
1200            let signature = secret_key.sign(message.as_ref());
1201            Signature::Ed25519(signature)
1202        }
1203        (SecretKey::Secp256k1(secret_key), PublicKey::Secp256k1(_public_key)) => {
1204            let signer = secret_key;
1205            let signature: Secp256k1Signature = signer
1206                .try_sign(message.as_ref())
1207                .expect("should create signature");
1208            Signature::Secp256k1(signature)
1209        }
1210        _ => panic!("secret and public key types must match"),
1211    }
1212}
1213
1214/// Attempts to recover a Secp256k1 [`PublicKey`] from a message and a signature over it.
1215pub fn recover_secp256k1<T: AsRef<[u8]>>(
1216    message: T,
1217    signature: &Signature,
1218    recovery_id: u8,
1219) -> Result<PublicKey, Error> {
1220    let Signature::Secp256k1(signature) = signature else {
1221        return Err(Error::AsymmetricKey(String::from(
1222            "public keys can only be recovered from Secp256k1 signatures",
1223        )));
1224    };
1225
1226    let Ok(key) = VerifyingKey::recover_from_msg(
1227        message.as_ref(),
1228        signature,
1229        RecoveryId::try_from(recovery_id)?,
1230    ) else {
1231        return Err(Error::AsymmetricKey(String::from("Key extraction failed")));
1232    };
1233
1234    Ok(PublicKey::Secp256k1(key))
1235}
1236
1237/// Verifies the signature of the given message against the given public key.
1238pub fn verify<T: AsRef<[u8]>>(
1239    message: T,
1240    signature: &Signature,
1241    public_key: &PublicKey,
1242) -> Result<(), Error> {
1243    match (signature, public_key) {
1244        (Signature::System, _) => Err(Error::AsymmetricKey(String::from(
1245            "signatures based on the system key cannot be verified",
1246        ))),
1247        (Signature::Ed25519(signature), PublicKey::Ed25519(public_key)) => public_key
1248            .verify_strict(message.as_ref(), signature)
1249            .map_err(|_| Error::AsymmetricKey(String::from("failed to verify Ed25519 signature"))),
1250        (Signature::Secp256k1(signature), PublicKey::Secp256k1(public_key)) => {
1251            let verifier: &Secp256k1PublicKey = public_key;
1252            verifier
1253                .verify(message.as_ref(), signature)
1254                .map_err(|error| {
1255                    Error::AsymmetricKey(format!("failed to verify secp256k1 signature: {}", error))
1256                })
1257        }
1258        _ => Err(Error::AsymmetricKey(format!(
1259            "type mismatch between {} and {}",
1260            signature, public_key
1261        ))),
1262    }
1263}
1264
1265/// Generates an Ed25519 keypair using the operating system's cryptographically secure random number
1266/// generator.
1267#[cfg(any(feature = "std", test))]
1268pub fn generate_ed25519_keypair() -> (SecretKey, PublicKey) {
1269    let secret_key = SecretKey::generate_ed25519().unwrap();
1270    let public_key = PublicKey::from(&secret_key);
1271    (secret_key, public_key)
1272}
1273
1274mod detail {
1275    use alloc::{string::String, vec::Vec};
1276
1277    use serde::{de::Error as _deError, Deserialize, Deserializer, Serialize, Serializer};
1278
1279    use super::{PublicKey, Signature};
1280    use crate::AsymmetricType;
1281
1282    /// Used to serialize and deserialize asymmetric key types where the (de)serializer is not a
1283    /// human-readable type.
1284    ///
1285    /// The wrapped contents are the result of calling `t_as_ref()` on the type.
1286    #[derive(Serialize, Deserialize)]
1287    pub(super) enum AsymmetricTypeAsBytes {
1288        System,
1289        Ed25519(Vec<u8>),
1290        Secp256k1(Vec<u8>),
1291    }
1292
1293    impl From<&PublicKey> for AsymmetricTypeAsBytes {
1294        fn from(public_key: &PublicKey) -> Self {
1295            match public_key {
1296                PublicKey::System => AsymmetricTypeAsBytes::System,
1297                key @ PublicKey::Ed25519(_) => AsymmetricTypeAsBytes::Ed25519(key.into()),
1298                key @ PublicKey::Secp256k1(_) => AsymmetricTypeAsBytes::Secp256k1(key.into()),
1299            }
1300        }
1301    }
1302
1303    impl From<&Signature> for AsymmetricTypeAsBytes {
1304        fn from(signature: &Signature) -> Self {
1305            match signature {
1306                Signature::System => AsymmetricTypeAsBytes::System,
1307                key @ Signature::Ed25519(_) => AsymmetricTypeAsBytes::Ed25519(key.into()),
1308                key @ Signature::Secp256k1(_) => AsymmetricTypeAsBytes::Secp256k1(key.into()),
1309            }
1310        }
1311    }
1312
1313    pub(super) fn serialize<'a, T, S>(value: &'a T, serializer: S) -> Result<S::Ok, S::Error>
1314    where
1315        T: AsymmetricType<'a>,
1316        Vec<u8>: From<&'a T>,
1317        S: Serializer,
1318        AsymmetricTypeAsBytes: From<&'a T>,
1319    {
1320        if serializer.is_human_readable() {
1321            return value.to_hex().serialize(serializer);
1322        }
1323
1324        AsymmetricTypeAsBytes::from(value).serialize(serializer)
1325    }
1326
1327    pub(super) fn deserialize<'a, 'de, T, D>(deserializer: D) -> Result<T, D::Error>
1328    where
1329        T: AsymmetricType<'a>,
1330        Vec<u8>: From<&'a T>,
1331        D: Deserializer<'de>,
1332    {
1333        if deserializer.is_human_readable() {
1334            let hex_string = String::deserialize(deserializer)?;
1335            let value = T::from_hex(hex_string.as_bytes()).map_err(D::Error::custom)?;
1336            return Ok(value);
1337        }
1338
1339        let as_bytes = AsymmetricTypeAsBytes::deserialize(deserializer)?;
1340        match as_bytes {
1341            AsymmetricTypeAsBytes::System => Ok(T::system()),
1342            AsymmetricTypeAsBytes::Ed25519(raw_bytes) => {
1343                T::ed25519_from_bytes(raw_bytes).map_err(D::Error::custom)
1344            }
1345            AsymmetricTypeAsBytes::Secp256k1(raw_bytes) => {
1346                T::secp256k1_from_bytes(raw_bytes).map_err(D::Error::custom)
1347            }
1348        }
1349    }
1350}