p2p/identity/
public_key.rs

1use 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; // 'P'
18
19    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}