primitives/types/identifiers/
peer_id.rs1use derive_more::derive::AsRef;
2use ed25519_dalek::{
3 pkcs8::{DecodePrivateKey, DecodePublicKey},
4 SigningKey,
5 Verifier,
6 VerifyingKey,
7};
8use quinn::rustls::{server::ParsedCertificate, Error as RustlsError};
9pub use rand::Rng;
10#[cfg(any(test, feature = "dev"))]
11use rand::{distributions::Standard, prelude::Distribution};
12use rustls_pki_types::CertificateDer;
13use serde::{Deserialize, Serialize};
14
15use crate::errors::PrimitiveError;
16pub const PEER_ID_LENGTH: usize = ed25519_dalek::PUBLIC_KEY_LENGTH; #[derive(Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord, AsRef)]
19#[as_ref([u8])]
20pub struct PeerId([u8; PEER_ID_LENGTH]);
23
24impl Verifier<ed25519_dalek::Signature> for PeerId {
25 fn verify(
26 &self,
27 message: &[u8],
28 signature: &ed25519_dalek::Signature,
29 ) -> Result<(), ed25519_dalek::SignatureError> {
30 let public_key = VerifyingKey::from(*self); public_key.verify_strict(message, signature)
32 }
33}
34
35#[cfg(not(any(test, feature = "dev")))]
36impl std::fmt::Display for PeerId {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 write!(f, "{}", hex::encode(self.0))
39 }
40}
41
42#[cfg(not(any(test, feature = "dev")))]
43impl std::fmt::Debug for PeerId {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 write!(f, "{}", hex::encode(self.0))
46 }
47}
48
49#[cfg(any(test, feature = "dev"))]
50impl std::fmt::Display for PeerId {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(f, "{}", &hex::encode(self.0)[0..6])
53 }
54}
55
56#[cfg(any(test, feature = "dev"))]
57impl std::fmt::Debug for PeerId {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 write!(f, "{}", &hex::encode(self.0)[0..6])
60 }
61}
62
63#[cfg(any(test, feature = "dev"))]
66impl From<[u8; PEER_ID_LENGTH]> for PeerId {
67 fn from(bytes: [u8; PEER_ID_LENGTH]) -> Self {
68 Self(bytes)
69 }
70}
71
72impl<'pid> From<&'pid PeerId> for &'pid [u8; PEER_ID_LENGTH] {
73 fn from(peer_id: &'pid PeerId) -> Self {
74 &peer_id.0
75 }
76}
77
78impl From<PeerId> for [u8; PEER_ID_LENGTH] {
79 fn from(peer_id: PeerId) -> Self {
80 peer_id.0
81 }
82}
83
84impl From<&PeerId> for String {
85 fn from(peer_id: &PeerId) -> String {
86 hex::encode(peer_id.0)
87 }
88}
89
90impl From<VerifyingKey> for PeerId {
91 fn from(verifying_key: VerifyingKey) -> PeerId {
92 Self(verifying_key.to_bytes())
93 }
94}
95
96impl From<PeerId> for VerifyingKey {
97 fn from(peer_id: PeerId) -> VerifyingKey {
98 VerifyingKey::from_bytes(&peer_id.0).unwrap() }
100}
101
102impl From<&SigningKey> for PeerId {
103 fn from(signing_key: &SigningKey) -> PeerId {
104 Self(signing_key.verifying_key().to_bytes())
105 }
106}
107
108impl TryFrom<&[u8; 32]> for PeerId {
111 type Error = PrimitiveError;
112
113 fn try_from(bytes: &[u8; 32]) -> Result<Self, Self::Error> {
114 let public_key = VerifyingKey::from_bytes(bytes).map_err(|_| {
115 PrimitiveError::InvalidParameters(
116 "Could not convert it to an ed25519 public key".to_string(),
117 )
118 })?;
119 Ok(Self(public_key.to_bytes()))
120 }
121}
122
123impl TryFrom<CertificateDer<'static>> for PeerId {
124 type Error = PrimitiveError;
125
126 fn try_from(certificate: CertificateDer<'static>) -> Result<Self, Self::Error> {
127 Self::from_certificate(certificate)
128 }
129}
130
131impl TryFrom<&quinn::Connection> for PeerId {
132 type Error = PrimitiveError;
133
134 fn try_from(connection: &quinn::Connection) -> Result<Self, Self::Error> {
135 Self::from_connection(connection)
136 }
137}
138
139impl PeerId {
140 pub fn from_keypair(keypair: &rcgen::KeyPair) -> Result<Self, PrimitiveError> {
142 if keypair.algorithm() != &rcgen::PKCS_ED25519 {
143 return Err(PrimitiveError::InvalidParameters(
144 "Keypair is not Ed25519".to_string(),
145 ));
146 }
147 let public_key_bytes: [u8; PEER_ID_LENGTH] =
148 keypair.public_key_raw().to_vec().try_into().unwrap();
149 Ok(Self(public_key_bytes))
150 }
151
152 pub fn from_secret_key_der(bytes: &[u8]) -> Result<Self, PrimitiveError> {
154 let secret_key = SigningKey::from_pkcs8_der(bytes).map_err(|e| {
155 PrimitiveError::InvalidParameters(format!(
156 "Failed to decode secret key in DER format: {e}",
157 ))
158 })?;
159 Ok(Self(*secret_key.verifying_key().as_bytes()))
160 }
161
162 pub fn from_public_key_der(bytes: &[u8]) -> Result<Self, PrimitiveError> {
164 let public_key = VerifyingKey::from_public_key_der(bytes).map_err(|e| {
165 PrimitiveError::InvalidParameters(format!(
166 "Failed to decode public key in DER format: {e}",
167 ))
168 })?;
169 Ok(Self(public_key.to_bytes()))
170 }
171
172 pub(crate) fn from_certificate(
174 certificate: CertificateDer<'static>,
175 ) -> Result<Self, PrimitiveError> {
176 let cert = ParsedCertificate::try_from(&certificate)?;
177 let spki = cert.subject_public_key_info();
178
179 Self::from_public_key_der(spki.as_ref())
181 }
182
183 pub fn from_connection(connection: &quinn::Connection) -> Result<Self, PrimitiveError> {
185 let certificate = connection
186 .peer_identity()
187 .ok_or(RustlsError::NoCertificatesPresented)?
188 .downcast::<Vec<CertificateDer<'static>>>()
189 .map_err(|_| RustlsError::General("Peer identity didn't downcast to a certificate. Check quinn session (should be default rustls).".to_string()))?
190 .into_iter()
191 .next()
192 .ok_or(RustlsError::NoCertificatesPresented)?;
193 Self::from_certificate(certificate)
194 }
195}
196
197#[cfg(any(test, feature = "dev"))]
198impl Distribution<PeerId> for Standard {
199 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> PeerId {
200 let mut secret_key = <[u8; PEER_ID_LENGTH]>::default();
201 rng.fill_bytes(&mut secret_key);
202 let public_key = SigningKey::from_bytes(&secret_key)
203 .verifying_key()
204 .to_bytes();
205 PeerId(public_key)
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use ed25519_dalek::{pkcs8::DecodePrivateKey, Signer, SigningKey, Verifier};
212 use rand::SeedableRng;
213
214 use super::*;
215 use crate::random::BaseRng;
216
217 const SAMPLE_CERTIFICATE_DER: &str = "3082011d3081d0a00302010202146403206e30248a32e568a26239c434d23df91131300506032b65703021311f301d06035504030c16726367656e2073656c66207369676e656420636572743020170d3735303130313030303030305a180f34303936303130313030303030305a3021311f301d06035504030c16726367656e2073656c66207369676e65642063657274302a300506032b6570032100a965eea43375c9ecff6ac3a324ee77cd3d0ceca3b1a203881bc61a16203593dea318301630140603551d11040d300b82096173796e632d6d7063300506032b657003410014ff443071b7ad0a0f540f3e5a083f5873d045f2a7302a63c171da750dea288b216beb1f599ca5db2696b7236f6d69652ab46a0845a5a6b6aa73608fb439010e";
218 const SAMPLE_SKEY_DER: &str = "3051020101300506032b657004220420c66ea2001a6b5b4e0b4ef51265c74829bb34e1952e9ed399c4158acf8df4521f812100a965eea43375c9ecff6ac3a324ee77cd3d0ceca3b1a203881bc61a16203593de";
219 const SAMPLE_PKEY_DER: &str =
220 "302a300506032b6570032100a965eea43375c9ecff6ac3a324ee77cd3d0ceca3b1a203881bc61a16203593de";
221 const SAMPLE_SKEY_BYTES: &str =
222 "c66ea2001a6b5b4e0b4ef51265c74829bb34e1952e9ed399c4158acf8df4521f";
223 const SAMPLE_PKEY_BYTES: &str =
224 "a965eea43375c9ecff6ac3a324ee77cd3d0ceca3b1a203881bc61a16203593de";
225
226 #[test]
227 fn test_happypath_peer_id_from_keys() {
228 let secret_key =
230 SigningKey::from_bytes(&hex::decode(SAMPLE_SKEY_BYTES).unwrap().try_into().unwrap());
231 let message = b"Hello, world!";
232 let signature = secret_key.sign(message);
233
234 let pkey_bytes: [u8; 32] = hex::decode(SAMPLE_PKEY_BYTES).unwrap().try_into().unwrap();
236 let peer_id = PeerId::try_from(&pkey_bytes).unwrap();
237 peer_id.verify(message, &signature).unwrap();
238 assert_eq!(peer_id.as_ref(), secret_key.verifying_key().as_bytes());
239
240 let pkey =
242 VerifyingKey::from_public_key_der(&hex::decode(SAMPLE_PKEY_DER).unwrap()).unwrap();
243 let peer_id = PeerId::from(pkey);
244 peer_id.verify(message, &signature).unwrap();
245 assert_eq!(secret_key.verifying_key().as_bytes(), peer_id.as_ref());
246 assert_eq!(secret_key.verifying_key(), peer_id.into());
247
248 let skey = SigningKey::from_pkcs8_der(&hex::decode(SAMPLE_SKEY_DER).unwrap()).unwrap();
250 let peer_id = PeerId::from(&skey);
251 peer_id.verify(message, &signature).unwrap();
252 assert_eq!(peer_id.as_ref(), secret_key.verifying_key().as_bytes());
253 }
254
255 #[test]
256 fn test_happypath_peer_id_from_serialized_keys() {
257 let secret_key =
259 SigningKey::from_bytes(&hex::decode(SAMPLE_SKEY_BYTES).unwrap().try_into().unwrap());
260 let message = b"Hello, serialized keys!";
261 let signature = secret_key.sign(message);
262
263 let peer_id = PeerId::from_secret_key_der(&hex::decode(SAMPLE_SKEY_DER).unwrap()).unwrap();
265 peer_id.verify(message, &signature).unwrap();
266 assert_eq!(peer_id.as_ref(), secret_key.verifying_key().as_bytes());
267
268 let peer_id = PeerId::from_secret_key_der(&hex::decode(SAMPLE_SKEY_DER).unwrap()).unwrap();
270 peer_id.verify(message, &signature).unwrap();
271 assert_eq!(peer_id.as_ref(), secret_key.verifying_key().as_bytes());
272 }
273
274 #[test]
275 fn test_happypath_peer_id_from_certificate() {
276 let secret_key =
278 SigningKey::from_bytes(&hex::decode(SAMPLE_SKEY_BYTES).unwrap().try_into().unwrap());
279 let message = b"Hello, certificate!";
280 let signature = secret_key.sign(message);
281
282 let certificate = CertificateDer::from(hex::decode(SAMPLE_CERTIFICATE_DER).unwrap());
284 let peer_id = PeerId::from_certificate(certificate).unwrap();
285 peer_id.verify(message, &signature).unwrap();
286 assert_eq!(peer_id.as_ref(), secret_key.verifying_key().as_bytes());
287 }
288
289 #[test]
290 fn test_happypath_two_peer_ids_cross_verify() {
291 let mut rng = BaseRng::from_seed(*b"Look Sam, the eagles are coming!");
292 let secret_key_1 = SigningKey::generate(&mut rng);
293 let secret_key_2 = SigningKey::generate(&mut rng);
294
295 let message = b"Hello, cross verify!";
296
297 let signature_1 = secret_key_1.sign(message);
298 let signature_2 = secret_key_2.sign(message);
299
300 let peer_id_1 = PeerId::from(&secret_key_1);
301 let peer_id_2 = PeerId::from(&secret_key_2);
302 assert_eq!(peer_id_1.as_ref(), secret_key_1.verifying_key().as_bytes());
303 assert_eq!(peer_id_2.as_ref(), secret_key_2.verifying_key().as_bytes());
304
305 peer_id_1.verify(message, &signature_1).unwrap();
306 peer_id_2.verify(message, &signature_2).unwrap();
307
308 peer_id_2.verify(message, &signature_1).unwrap_err();
309 peer_id_1.verify(message, &signature_2).unwrap_err();
310 }
311}