primitives/types/identifiers/
peer_id.rs1use std::ops::BitXor;
2
3use derive_more::derive::AsRef;
4use ed25519_dalek::{
5 pkcs8::{DecodePrivateKey, DecodePublicKey},
6 SigningKey,
7 Verifier,
8 VerifyingKey,
9};
10use quinn::rustls::{server::ParsedCertificate, Error as RustlsError};
11pub use rand::Rng;
12#[cfg(any(test, feature = "dev"))]
13use rand::{distributions::Standard, prelude::Distribution};
14use rustls_pki_types::CertificateDer;
15use serde::{Deserialize, Serialize};
16use wincode::{SchemaRead, SchemaWrite};
17
18use crate::{errors::PrimitiveError, izip_eq};
19pub const PEER_ID_LENGTH: usize = ed25519_dalek::PUBLIC_KEY_LENGTH; #[derive(
22 Copy,
23 Clone,
24 Serialize,
25 Deserialize,
26 SchemaRead,
27 SchemaWrite,
28 PartialEq,
29 Eq,
30 Hash,
31 PartialOrd,
32 Ord,
33 AsRef,
34)]
35#[as_ref([u8])]
36#[repr(transparent)]
37pub struct PeerId([u8; PEER_ID_LENGTH]);
40
41impl Verifier<ed25519_dalek::Signature> for PeerId {
42 fn verify(
43 &self,
44 message: &[u8],
45 signature: &ed25519_dalek::Signature,
46 ) -> Result<(), ed25519_dalek::SignatureError> {
47 let public_key =
48 VerifyingKey::try_from(*self).map_err(ed25519_dalek::SignatureError::from_source)?;
49 public_key.verify_strict(message, signature)
50 }
51}
52
53#[cfg(not(any(test, feature = "dev")))]
54impl std::fmt::Display for PeerId {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 write!(f, "{}", hex::encode(self.0))
57 }
58}
59
60#[cfg(not(any(test, feature = "dev")))]
61impl std::fmt::Debug for PeerId {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 write!(f, "{}", hex::encode(self.0))
64 }
65}
66
67#[cfg(any(test, feature = "dev"))]
68impl std::fmt::Display for PeerId {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 write!(f, "{}", &hex::encode(self.0)[0..6])
71 }
72}
73
74#[cfg(any(test, feature = "dev"))]
75impl std::fmt::Debug for PeerId {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 write!(f, "{}", &hex::encode(self.0)[0..6])
78 }
79}
80
81#[cfg(any(test, feature = "dev"))]
84impl From<[u8; PEER_ID_LENGTH]> for PeerId {
85 fn from(bytes: [u8; PEER_ID_LENGTH]) -> Self {
86 Self(bytes)
87 }
88}
89
90impl<'pid> From<&'pid PeerId> for &'pid [u8; PEER_ID_LENGTH] {
91 fn from(peer_id: &'pid PeerId) -> Self {
92 &peer_id.0
93 }
94}
95
96impl From<PeerId> for [u8; PEER_ID_LENGTH] {
97 fn from(peer_id: PeerId) -> Self {
98 peer_id.0
99 }
100}
101
102impl From<&PeerId> for String {
103 fn from(peer_id: &PeerId) -> String {
104 hex::encode(peer_id.0)
105 }
106}
107
108impl From<VerifyingKey> for PeerId {
109 fn from(verifying_key: VerifyingKey) -> PeerId {
110 Self(verifying_key.to_bytes())
111 }
112}
113
114impl TryFrom<PeerId> for VerifyingKey {
115 type Error = PrimitiveError;
116
117 fn try_from(peer_id: PeerId) -> Result<VerifyingKey, PrimitiveError> {
118 VerifyingKey::from_bytes(&peer_id.0).map_err(|_| PrimitiveError::InvalidPeerId(peer_id))
119 }
120}
121
122impl From<&SigningKey> for PeerId {
123 fn from(signing_key: &SigningKey) -> PeerId {
124 Self(signing_key.verifying_key().to_bytes())
125 }
126}
127
128impl TryFrom<&[u8; 32]> for PeerId {
131 type Error = PrimitiveError;
132
133 fn try_from(bytes: &[u8; 32]) -> Result<Self, Self::Error> {
134 let public_key = VerifyingKey::from_bytes(bytes).map_err(|_| {
135 PrimitiveError::InvalidParameters(
136 "Could not convert it to an ed25519 public key".to_string(),
137 )
138 })?;
139 Ok(Self(public_key.to_bytes()))
140 }
141}
142
143impl TryFrom<CertificateDer<'static>> for PeerId {
144 type Error = PrimitiveError;
145
146 fn try_from(certificate: CertificateDer<'static>) -> Result<Self, Self::Error> {
147 Self::from_certificate(certificate)
148 }
149}
150
151impl TryFrom<&quinn::Connection> for PeerId {
152 type Error = PrimitiveError;
153
154 fn try_from(connection: &quinn::Connection) -> Result<Self, Self::Error> {
155 Self::from_connection(connection)
156 }
157}
158
159impl PeerId {
160 pub fn from_keypair(keypair: &rcgen::KeyPair) -> Result<Self, PrimitiveError> {
162 if keypair.algorithm() != &rcgen::PKCS_ED25519 {
163 return Err(PrimitiveError::InvalidParameters(
164 "Keypair is not Ed25519".to_string(),
165 ));
166 }
167 let public_key_bytes: [u8; PEER_ID_LENGTH] =
168 keypair.public_key_raw().to_vec().try_into().unwrap();
169 Ok(Self(public_key_bytes))
170 }
171
172 pub fn from_secret_key_der(bytes: &[u8]) -> Result<Self, PrimitiveError> {
174 let secret_key = SigningKey::from_pkcs8_der(bytes).map_err(|e| {
175 PrimitiveError::InvalidParameters(format!(
176 "Failed to decode secret key in DER format: {e}",
177 ))
178 })?;
179 Ok(Self(*secret_key.verifying_key().as_bytes()))
180 }
181
182 pub fn from_public_key_der(bytes: &[u8]) -> Result<Self, PrimitiveError> {
184 let public_key = VerifyingKey::from_public_key_der(bytes).map_err(|e| {
185 PrimitiveError::InvalidParameters(format!(
186 "Failed to decode public key in DER format: {e}",
187 ))
188 })?;
189 Ok(Self(public_key.to_bytes()))
190 }
191
192 pub(crate) fn from_certificate(
194 certificate: CertificateDer<'static>,
195 ) -> Result<Self, PrimitiveError> {
196 let cert = ParsedCertificate::try_from(&certificate)?;
197 let spki = cert.subject_public_key_info();
198
199 Self::from_public_key_der(spki.as_ref())
201 }
202
203 pub fn from_connection(connection: &quinn::Connection) -> Result<Self, PrimitiveError> {
205 let certificate = connection
206 .peer_identity()
207 .ok_or(RustlsError::NoCertificatesPresented)?
208 .downcast::<Vec<CertificateDer<'static>>>()
209 .map_err(|_| RustlsError::General("Peer identity didn't downcast to a certificate. Check quinn session (should be default rustls).".to_string()))?
210 .into_iter()
211 .next()
212 .ok_or(RustlsError::NoCertificatesPresented)?;
213 Self::from_certificate(certificate)
214 }
215}
216
217#[macros::op_variants(owned, borrowed, flipped_commutative)]
218impl BitXor<&PeerId> for PeerId {
219 type Output = PeerId;
220
221 fn bitxor(mut self, rhs: &Self) -> Self::Output {
222 izip_eq!(self.0.iter_mut(), rhs.0.iter()).for_each(|(a, b)| {
223 *a ^= *b;
224 });
225 self
226 }
227}
228
229#[cfg(any(test, feature = "dev"))]
230impl Distribution<PeerId> for Standard {
231 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> PeerId {
232 let mut secret_key = <[u8; PEER_ID_LENGTH]>::default();
233 rng.fill_bytes(&mut secret_key);
234 let public_key = SigningKey::from_bytes(&secret_key)
235 .verifying_key()
236 .to_bytes();
237 PeerId(public_key)
238 }
239}
240
241#[cfg(test)]
242mod tests {
243 use ed25519_dalek::{pkcs8::DecodePrivateKey, Signer, SigningKey, Verifier};
244 use rand::SeedableRng;
245
246 use super::*;
247 use crate::random::BaseRng;
248
249 const SAMPLE_CERTIFICATE_DER: &str = "3082011d3081d0a00302010202146403206e30248a32e568a26239c434d23df91131300506032b65703021311f301d06035504030c16726367656e2073656c66207369676e656420636572743020170d3735303130313030303030305a180f34303936303130313030303030305a3021311f301d06035504030c16726367656e2073656c66207369676e65642063657274302a300506032b6570032100a965eea43375c9ecff6ac3a324ee77cd3d0ceca3b1a203881bc61a16203593dea318301630140603551d11040d300b82096173796e632d6d7063300506032b657003410014ff443071b7ad0a0f540f3e5a083f5873d045f2a7302a63c171da750dea288b216beb1f599ca5db2696b7236f6d69652ab46a0845a5a6b6aa73608fb439010e";
250 const SAMPLE_SKEY_DER: &str = "3051020101300506032b657004220420c66ea2001a6b5b4e0b4ef51265c74829bb34e1952e9ed399c4158acf8df4521f812100a965eea43375c9ecff6ac3a324ee77cd3d0ceca3b1a203881bc61a16203593de";
251 const SAMPLE_PKEY_DER: &str =
252 "302a300506032b6570032100a965eea43375c9ecff6ac3a324ee77cd3d0ceca3b1a203881bc61a16203593de";
253 const SAMPLE_SKEY_BYTES: &str =
254 "c66ea2001a6b5b4e0b4ef51265c74829bb34e1952e9ed399c4158acf8df4521f";
255 const SAMPLE_PKEY_BYTES: &str =
256 "a965eea43375c9ecff6ac3a324ee77cd3d0ceca3b1a203881bc61a16203593de";
257
258 #[test]
259 fn test_happypath_peer_id_from_keys() {
260 let secret_key =
262 SigningKey::from_bytes(&hex::decode(SAMPLE_SKEY_BYTES).unwrap().try_into().unwrap());
263 let message = b"Hello, world!";
264 let signature = secret_key.sign(message);
265
266 let pkey_bytes: [u8; 32] = hex::decode(SAMPLE_PKEY_BYTES).unwrap().try_into().unwrap();
268 let peer_id = PeerId::try_from(&pkey_bytes).unwrap();
269 peer_id.verify(message, &signature).unwrap();
270 assert_eq!(peer_id.as_ref(), secret_key.verifying_key().as_bytes());
271
272 let pkey =
274 VerifyingKey::from_public_key_der(&hex::decode(SAMPLE_PKEY_DER).unwrap()).unwrap();
275 let peer_id = PeerId::from(pkey);
276 peer_id.verify(message, &signature).unwrap();
277 assert_eq!(secret_key.verifying_key().as_bytes(), peer_id.as_ref());
278 assert_eq!(secret_key.verifying_key(), peer_id.try_into().unwrap());
279
280 let skey = SigningKey::from_pkcs8_der(&hex::decode(SAMPLE_SKEY_DER).unwrap()).unwrap();
282 let peer_id = PeerId::from(&skey);
283 peer_id.verify(message, &signature).unwrap();
284 assert_eq!(peer_id.as_ref(), secret_key.verifying_key().as_bytes());
285 }
286
287 #[test]
288 fn test_happypath_peer_id_from_serialized_keys() {
289 let secret_key =
291 SigningKey::from_bytes(&hex::decode(SAMPLE_SKEY_BYTES).unwrap().try_into().unwrap());
292 let message = b"Hello, serialized keys!";
293 let signature = secret_key.sign(message);
294
295 let peer_id = PeerId::from_secret_key_der(&hex::decode(SAMPLE_SKEY_DER).unwrap()).unwrap();
297 peer_id.verify(message, &signature).unwrap();
298 assert_eq!(peer_id.as_ref(), secret_key.verifying_key().as_bytes());
299
300 let peer_id = PeerId::from_secret_key_der(&hex::decode(SAMPLE_SKEY_DER).unwrap()).unwrap();
302 peer_id.verify(message, &signature).unwrap();
303 assert_eq!(peer_id.as_ref(), secret_key.verifying_key().as_bytes());
304 }
305
306 #[test]
307 fn test_happypath_peer_id_from_certificate() {
308 let secret_key =
310 SigningKey::from_bytes(&hex::decode(SAMPLE_SKEY_BYTES).unwrap().try_into().unwrap());
311 let message = b"Hello, certificate!";
312 let signature = secret_key.sign(message);
313
314 let certificate = CertificateDer::from(hex::decode(SAMPLE_CERTIFICATE_DER).unwrap());
316 let peer_id = PeerId::from_certificate(certificate).unwrap();
317 peer_id.verify(message, &signature).unwrap();
318 assert_eq!(peer_id.as_ref(), secret_key.verifying_key().as_bytes());
319 }
320
321 #[test]
322 fn test_happypath_two_peer_ids_cross_verify() {
323 let mut rng = BaseRng::from_seed(*b"Look Sam, the eagles are coming!");
324 let secret_key_1 = SigningKey::generate(&mut rng);
325 let secret_key_2 = SigningKey::generate(&mut rng);
326
327 let message = b"Hello, cross verify!";
328
329 let signature_1 = secret_key_1.sign(message);
330 let signature_2 = secret_key_2.sign(message);
331
332 let peer_id_1 = PeerId::from(&secret_key_1);
333 let peer_id_2 = PeerId::from(&secret_key_2);
334 assert_eq!(peer_id_1.as_ref(), secret_key_1.verifying_key().as_bytes());
335 assert_eq!(peer_id_2.as_ref(), secret_key_2.verifying_key().as_bytes());
336
337 peer_id_1.verify(message, &signature_1).unwrap();
338 peer_id_2.verify(message, &signature_2).unwrap();
339
340 peer_id_2.verify(message, &signature_1).unwrap_err();
341 peer_id_1.verify(message, &signature_2).unwrap_err();
342 }
343
344 #[test]
345 fn test_invalid_deserialized_peer_id_verify_never_panics() {
346 let mut rng = BaseRng::from_seed(*b"Look Sam, the eagles are coming!");
347 let signing_key = SigningKey::generate(&mut rng);
348 let message = b"Hello, invalid peer id!";
349 let signature = signing_key.sign(message);
350
351 let invalid_peer_id_bytes = [0xFFu8; PEER_ID_LENGTH];
353
354 fn assert_no_panic_verify_error<E>(
355 decoded: Result<PeerId, E>,
356 message: &[u8],
357 signature: &ed25519_dalek::Signature,
358 ) {
359 if let Ok(invalid_peer_id) = decoded {
362 let verify_result =
363 std::panic::catch_unwind(|| invalid_peer_id.verify(message, signature));
364 assert!(
365 verify_result.is_ok(),
366 "verify() must return an error instead of panicking for invalid PeerId bytes"
367 );
368 assert!(verify_result.unwrap().is_err());
369 }
370 }
371
372 let bincode_encoded = bincode::serialize(&invalid_peer_id_bytes).unwrap();
373 let bincode_decoded: Result<PeerId, _> = bincode::deserialize(&bincode_encoded);
374 assert_no_panic_verify_error(bincode_decoded, message, &signature);
375
376 let wincode_encoded = wincode::serialize(&invalid_peer_id_bytes).unwrap();
377 let wincode_decoded: Result<PeerId, _> = wincode::deserialize(&wincode_encoded);
378 assert_no_panic_verify_error(wincode_decoded, message, &signature);
379 }
380}