cometbft_p2p/
public_key.rs1use crate::{Error, IdentitySecret, PeerId, Result, ed25519, proto};
4use ed25519_dalek::Verifier;
5use prost::DecodeError;
6use sha2::{Sha256, digest::Digest};
7use std::fmt::{self, Debug, Display};
8
9#[derive(Clone, Copy, Eq, Hash, PartialEq)]
11pub enum PublicKey {
12 Ed25519(ed25519::VerifyingKey),
14}
15
16impl PublicKey {
17 pub fn from_raw_ed25519(bytes: &[u8]) -> Result<Self> {
22 Ok(ed25519::VerifyingKey::try_from(bytes).map(Self::Ed25519)?)
23 }
24
25 #[must_use]
27 pub fn ed25519(self) -> Option<ed25519::VerifyingKey> {
28 match self {
29 Self::Ed25519(pk) => Some(pk),
30 }
31 }
32
33 #[must_use]
37 pub fn peer_id(self) -> PeerId {
38 match self {
39 Self::Ed25519(pk) => {
40 let digest = Sha256::digest(pk.as_bytes());
41 PeerId(digest[..20].try_into().expect("should be 20 bytes"))
42 }
43 }
44 }
45
46 pub fn to_proto(&self) -> proto::crypto::PublicKey {
48 let pk = match self {
49 Self::Ed25519(pk) => proto::crypto::public_key::Sum::Ed25519(pk.as_ref().to_vec()),
50 };
51
52 proto::crypto::PublicKey { sum: Some(pk) }
53 }
54
55 pub(crate) fn verify(&self, msg: &[u8], sig: &[u8]) -> Result<()> {
57 match self {
58 Self::Ed25519(ed25519_vk) => {
59 let sig = ed25519::Signature::try_from(sig)?;
60 Ok(ed25519_vk.verify(msg, &sig)?)
61 }
62 }
63 }
64}
65
66impl Display for PublicKey {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 match self {
69 Self::Ed25519(ed25519_key) => {
70 write!(f, "PublicKey::Ed25519(")?;
71 for byte in ed25519_key.to_bytes() {
72 write!(f, "{byte:02x}")?;
73 }
74 write!(f, ")")?;
75 }
76 }
77
78 Ok(())
79 }
80}
81
82impl Debug for PublicKey {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 match self {
85 PublicKey::Ed25519(_) => write!(f, "PublicKey::Ed25519({self})"),
86 }
87 }
88}
89
90impl From<ed25519::VerifyingKey> for PublicKey {
91 fn from(pk: ed25519::VerifyingKey) -> Self {
92 Self::Ed25519(pk)
93 }
94}
95
96impl From<&ed25519::VerifyingKey> for PublicKey {
97 fn from(pk: &ed25519::VerifyingKey) -> Self {
98 Self::from(*pk)
99 }
100}
101
102impl From<&IdentitySecret> for PublicKey {
103 fn from(sk: &IdentitySecret) -> Self {
104 Self::Ed25519(sk.verifying_key())
105 }
106}
107
108impl From<PublicKey> for proto::crypto::PublicKey {
109 fn from(pk: PublicKey) -> Self {
110 pk.to_proto()
111 }
112}
113
114impl From<&PublicKey> for proto::crypto::PublicKey {
115 fn from(pk: &PublicKey) -> Self {
116 pk.to_proto()
117 }
118}
119
120impl TryFrom<proto::crypto::PublicKey> for PublicKey {
121 type Error = Error;
122
123 fn try_from(pk: proto::crypto::PublicKey) -> Result<Self> {
124 Self::try_from(&pk)
125 }
126}
127
128impl TryFrom<&proto::crypto::PublicKey> for PublicKey {
129 type Error = Error;
130
131 fn try_from(pk: &proto::crypto::PublicKey) -> Result<Self> {
132 match &pk.sum {
133 Some(proto::crypto::public_key::Sum::Ed25519(bytes)) => {
134 ed25519::VerifyingKey::try_from(&bytes[..])
135 .map(Self::Ed25519)
136 .map_err(|_| {
137 DecodeError::new("malformed PublicKey proto with invalid Ed25519 key")
138 .into()
139 })
140 }
141 _ => Err(DecodeError::new(
142 "malformed PublicKey proto or unsupported public key algorithm",
143 )
144 .into()),
145 }
146 }
147}