1use 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
72pub const SYSTEM_TAG: u8 = 0;
74const SYSTEM: &str = "System";
75
76pub const ED25519_TAG: u8 = 1;
78const ED25519: &str = "Ed25519";
79
80pub 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
88pub const SYSTEM_ACCOUNT: PublicKey = PublicKey::System;
90
91#[cfg(any(feature = "std", test))]
93const EC_PUBLIC_KEY_OBJECT_IDENTIFIER: [u8; 7] = [42, 134, 72, 206, 61, 2, 1];
94
95#[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#[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
124pub trait AsymmetricType<'a>
126where
127 Self: 'a + Sized + Tagged<u8>,
128 Vec<u8>: From<&'a Self>,
129{
130 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 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 fn system() -> Self;
173
174 fn ed25519_from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, Error>;
176
177 fn secp256k1_from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, Error>;
179}
180
181#[cfg_attr(feature = "datasize", derive(DataSize))]
183#[non_exhaustive]
184pub enum SecretKey {
185 System,
187 #[cfg_attr(feature = "datasize", data_size(skip))]
189 Ed25519(Ed25519SecretKey),
191 #[cfg_attr(feature = "datasize", data_size(skip))]
193 Secp256k1(Secp256k1SecretKey),
194}
195
196impl SecretKey {
197 pub const SYSTEM_LENGTH: usize = 0;
199
200 pub const ED25519_LENGTH: usize = ED25519_SECRET_KEY_LENGTH;
202
203 pub const SECP256K1_LENGTH: usize = SECP256K1_SECRET_KEY_LENGTH;
205
206 pub fn system() -> Self {
208 SecretKey::System
209 }
210
211 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 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 #[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 #[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 #[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 #[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 #[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 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 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 #[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 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 let (tag, value) = derp::read_tag_and_get_value(input)?;
309 if tag == Tag::Sequence as u8 {
310 if version != 0 {
312 return Err(derp::Error::WrongValue);
313 }
314
315 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 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 if version != 1 {
334 return Err(derp::Error::WrongValue);
335 }
336
337 let raw_bytes = value.as_slice_less_safe();
339
340 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 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 #[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 #[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 #[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 #[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 #[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 #[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#[derive(Clone, Eq, PartialEq)]
480#[cfg_attr(feature = "datasize", derive(DataSize))]
481#[non_exhaustive]
482pub enum PublicKey {
483 System,
485 #[cfg_attr(feature = "datasize", data_size(skip))]
487 Ed25519(Ed25519PublicKey),
488 #[cfg_attr(feature = "datasize", data_size(skip))]
490 Secp256k1(Secp256k1PublicKey),
491}
492
493impl PublicKey {
494 pub const SYSTEM_LENGTH: usize = 0;
496
497 pub const ED25519_LENGTH: usize = ED25519_PUBLIC_KEY_LENGTH;
499
500 pub const SECP256K1_LENGTH: usize = SECP256K1_COMPRESSED_PUBLIC_KEY_LENGTH;
502
503 pub fn to_account_hash(&self) -> AccountHash {
505 AccountHash::from(self)
506 }
507
508 pub fn to_hex_string(&self) -> String {
510 self.to_hex()
511 }
512
513 pub fn is_system(&self) -> bool {
515 matches!(self, PublicKey::System)
516 }
517
518 #[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 #[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 #[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 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 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 #[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 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 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 #[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 #[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 #[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 #[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 #[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 #[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#[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#[derive(Clone, Copy)]
941#[cfg_attr(feature = "datasize", derive(DataSize))]
942#[non_exhaustive]
943pub enum Signature {
944 System,
946 #[cfg_attr(feature = "datasize", data_size(skip))]
948 Ed25519(Ed25519Signature),
949 #[cfg_attr(feature = "datasize", data_size(skip))]
951 Secp256k1(Secp256k1Signature),
952}
953
954impl Signature {
955 pub const SYSTEM_LENGTH: usize = 0;
957
958 pub const ED25519_LENGTH: usize = ED25519_SIGNATURE_LENGTH;
960
961 pub const SECP256K1_LENGTH: usize = SECP256K1_SIGNATURE_LENGTH;
963
964 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 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 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
1189pub 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
1214pub 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
1237pub 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#[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 #[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}