p2p/identity/
public_key.rs1use std::{
2 fmt,
3 io::{Read, Write},
4 str::FromStr,
5};
6
7use binprot::{BinProtRead, BinProtWrite};
8use ed25519_dalek::VerifyingKey as Ed25519PublicKey;
9use serde::{Deserialize, Serialize};
10
11use crate::PeerId;
12
13#[derive(Eq, PartialEq, Clone)]
14pub struct PublicKey(pub(super) Ed25519PublicKey);
15
16impl PublicKey {
17 const BASE58_CHECK_VERSION: u8 = 0x16; pub fn from_bytes(bytes: [u8; 32]) -> Result<Self, ed25519_dalek::SignatureError> {
20 Ed25519PublicKey::from_bytes(&bytes).map(Self)
21 }
22
23 pub fn to_bytes(&self) -> [u8; 32] {
24 self.0.to_bytes()
25 }
26
27 pub fn peer_id(&self) -> PeerId {
28 PeerId::from_bytes(self.to_bytes())
29 }
30
31 pub fn to_x25519(&self) -> x25519_dalek::PublicKey {
32 self.0.to_montgomery().to_bytes().into()
33 }
34}
35
36impl fmt::Display for PublicKey {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 let s = bs58::encode(&self.to_bytes())
39 .with_check_version(Self::BASE58_CHECK_VERSION)
40 .into_string();
41 write!(f, "{}", s)
42 }
43}
44
45impl fmt::Debug for PublicKey {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(f, "PublicKey({})", self)
48 }
49}
50
51#[derive(thiserror::Error, Serialize, Deserialize, Debug, Clone)]
52pub enum PublicKeyFromStrError {
53 #[error("Base58 decode error: {0}")]
54 Bs58(String),
55 #[error("Ed25519 key uncompress error: {0}")]
56 Ed25519(String),
57}
58
59impl FromStr for PublicKey {
60 type Err = PublicKeyFromStrError;
61
62 fn from_str(s: &str) -> Result<Self, Self::Err> {
63 let mut bytes = [0u8; 37];
64 let size = bs58::decode(s)
65 .with_check(Some(Self::BASE58_CHECK_VERSION))
66 .into(&mut bytes)
67 .map_err(|err| PublicKeyFromStrError::Bs58(err.to_string()))?;
68 if size != 33 {
69 return Err(PublicKeyFromStrError::Bs58(
70 bs58::decode::Error::BufferTooSmall.to_string(),
71 ));
72 }
73 Self::from_bytes(bytes[1..33].try_into().expect("Size checked above"))
74 .map_err(|err| PublicKeyFromStrError::Ed25519(err.to_string()))
75 }
76}
77
78impl From<PublicKey> for [u8; 32] {
79 fn from(value: PublicKey) -> Self {
80 value.to_bytes()
81 }
82}
83
84impl Serialize for PublicKey {
85 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86 where
87 S: serde::Serializer,
88 {
89 if serializer.is_human_readable() {
90 serializer.serialize_str(&self.to_string())
91 } else {
92 self.0.serialize(serializer)
93 }
94 }
95}
96
97impl<'de> serde::Deserialize<'de> for PublicKey {
98 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
99 where
100 D: serde::Deserializer<'de>,
101 {
102 if deserializer.is_human_readable() {
103 let b58: String = Deserialize::deserialize(deserializer)?;
104 Ok(b58.parse().map_err(serde::de::Error::custom)?)
105 } else {
106 Ok(Self(Deserialize::deserialize(deserializer)?))
107 }
108 }
109}
110
111impl BinProtWrite for PublicKey {
112 fn binprot_write<W: Write>(&self, w: &mut W) -> std::io::Result<()> {
113 w.write_all(&self.to_bytes())
114 }
115}
116
117impl BinProtRead for PublicKey {
118 fn binprot_read<R: Read + ?Sized>(r: &mut R) -> Result<Self, binprot::Error>
119 where
120 Self: Sized,
121 {
122 let mut buf = [0; 32];
123 r.read_exact(&mut buf)?;
124 Self::from_bytes(buf).map_err(|err| binprot::Error::CustomError(Box::new(err)))
125 }
126}