emissary_core/primitives/
router_identity.rs1use crate::{
20 crypto::{
21 base64_decode, base64_encode, sha256::Sha256, SigningPrivateKey, SigningPublicKey,
22 StaticPrivateKey, StaticPublicKey,
23 },
24 error::parser::RouterIdentityParseError,
25 runtime::Runtime,
26};
27
28use bytes::{BufMut, Bytes, BytesMut};
29use nom::{
30 bytes::complete::take,
31 number::complete::{be_u16, be_u8},
32 sequence::tuple,
33 Err, IResult,
34};
35use rand_core::RngCore;
36
37use alloc::{string::String, sync::Arc, vec::Vec};
38use core::fmt;
39
40const SERIALIZED_LEN: usize = 391usize;
42
43const KEY_CERTIFICATE: u8 = 0x05;
45
46const KEY_CERTIFICATE_LEN: u16 = 0x04;
48
49const KEY_KIND_EDDSA_SHA512_ED25519: u16 = 0x0007;
53
54const KEY_KIND_X25519: u16 = 0x0004;
58
59#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
61pub struct RouterId(Arc<String>);
62
63impl RouterId {
64 #[cfg(test)]
65 pub fn random() -> RouterId {
66 use rand::Rng;
67
68 let bytes = rand::thread_rng().gen::<[u8; 32]>();
69 RouterId::from(bytes)
70 }
71
72 pub fn to_vec(&self) -> Vec<u8> {
74 base64_decode(self.0.as_bytes()).expect("to succeed")
75 }
76}
77
78impl fmt::Display for RouterId {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 write!(f, "{}", &self.0[..8])
81 }
82}
83
84impl<T: AsRef<[u8]>> From<T> for RouterId {
85 fn from(value: T) -> Self {
86 RouterId(Arc::new(base64_encode(value)))
87 }
88}
89
90impl From<RouterId> for Vec<u8> {
91 fn from(value: RouterId) -> Self {
92 base64_decode(value.0.as_bytes()).expect("to succeed")
93 }
94}
95
96#[derive(Debug, Clone)]
98pub struct RouterIdentity {
99 identity_hash: Bytes,
101
102 padding: Bytes,
104
105 router: RouterId,
107
108 signing_key: SigningPublicKey,
110
111 static_key: StaticPublicKey,
113}
114
115impl RouterIdentity {
116 pub fn from_keys<R: Runtime>(
118 static_key: &StaticPrivateKey,
119 signing_key: &SigningPrivateKey,
120 ) -> crate::Result<Self> {
121 let padding = {
122 let mut padding = [0u8; 320];
123 R::rng().fill_bytes(&mut padding);
124
125 padding
126 };
127
128 let identity_hash = {
129 let mut out = BytesMut::with_capacity(SERIALIZED_LEN);
130
131 out.put_slice(static_key.public().as_ref());
132 out.put_slice(&padding);
133 out.put_slice(signing_key.public().as_ref());
134 out.put_u8(KEY_CERTIFICATE);
135 out.put_u16(KEY_CERTIFICATE_LEN);
136 out.put_u16(KEY_KIND_EDDSA_SHA512_ED25519);
137 out.put_u16(KEY_KIND_X25519);
138
139 Sha256::new().update(&out).finalize()
140 };
141
142 Ok(Self {
143 identity_hash: Bytes::from(identity_hash.clone()),
144 padding: Bytes::from(padding.to_vec()),
145 router: RouterId::from(identity_hash),
146 signing_key: signing_key.public(),
147 static_key: static_key.public(),
148 })
149 }
150
151 pub fn parse_frame(input: &[u8]) -> IResult<&[u8], RouterIdentity, RouterIdentityParseError> {
153 if input.len() < SERIALIZED_LEN {
154 return Err(Err::Error(RouterIdentityParseError::InvalidLength(
155 input.len(),
156 )));
157 }
158
159 let (_, (initial_bytes, rest)) = tuple((take(384usize), take(input.len() - 384)))(input)?;
160
161 let (rest, cert_type) = be_u8(rest)?;
162 let (rest, cert_len) = be_u16(rest)?;
163 let (rest, sig_key_type) = be_u16(rest)?;
164 let (rest, pub_key_type) = be_u16(rest)?;
165
166 let (KEY_CERTIFICATE, KEY_CERTIFICATE_LEN) = (cert_type, cert_len) else {
167 return Err(Err::Error(RouterIdentityParseError::InvalidCertificate((
168 cert_type, cert_len,
169 ))));
170 };
171
172 let static_key = match pub_key_type {
173 KEY_KIND_X25519 => StaticPublicKey::from_bytes(&initial_bytes[..32])
174 .ok_or(Err::Error(RouterIdentityParseError::InvalidBitstream)),
175 kind => Err(Err::Error(RouterIdentityParseError::InvalidPublicKey(kind))),
176 }?;
177
178 let signing_key = match sig_key_type {
179 KEY_KIND_EDDSA_SHA512_ED25519 => Some({
180 let public_key =
183 TryInto::<[u8; 32]>::try_into(initial_bytes[384 - 32..384].to_vec())
184 .expect("to succeed");
185
186 SigningPublicKey::from_bytes(&public_key)
187 .ok_or(Err::Error(RouterIdentityParseError::InvalidBitstream))?
188 }),
189 _ => None,
190 }
191 .ok_or(Err::Error(RouterIdentityParseError::InvalidSigningKey(
192 sig_key_type,
193 )))?;
194
195 let identity_hash = Bytes::from(Sha256::new().update(&input[..391]).finalize());
196
197 Ok((
198 rest,
199 RouterIdentity {
200 static_key,
201 padding: Bytes::from(initial_bytes[32..352].to_vec()),
202 signing_key,
203 identity_hash: identity_hash.clone(),
204 router: RouterId::from(identity_hash),
205 },
206 ))
207 }
208
209 #[allow(unused)]
211 pub fn parse(bytes: impl AsRef<[u8]>) -> Result<Self, RouterIdentityParseError> {
212 Ok(Self::parse_frame(bytes.as_ref())?.1)
213 }
214
215 pub fn serialize(&self) -> BytesMut {
217 let mut out = BytesMut::with_capacity(SERIALIZED_LEN);
218
219 out.put_slice(self.static_key.as_ref());
220 out.put_slice(&self.padding);
221 out.put_slice(self.signing_key.as_ref());
222 out.put_u8(KEY_CERTIFICATE);
223 out.put_u16(KEY_CERTIFICATE_LEN);
224 out.put_u16(KEY_KIND_EDDSA_SHA512_ED25519);
225 out.put_u16(KEY_KIND_X25519);
226
227 out
228 }
229
230 pub fn static_key(&self) -> &StaticPublicKey {
232 &self.static_key
233 }
234
235 pub fn signing_key(&self) -> &SigningPublicKey {
237 &self.signing_key
238 }
239
240 pub fn hash(&self) -> Bytes {
242 self.identity_hash.clone()
243 }
244
245 pub fn id(&self) -> RouterId {
247 self.router.clone()
248 }
249
250 pub fn serialized_len(&self) -> usize {
252 SERIALIZED_LEN
253 }
254
255 #[cfg(test)]
257 pub fn random() -> (Self, StaticPrivateKey, SigningPrivateKey) {
258 use crate::runtime::mock::MockRuntime;
259 use rand::{thread_rng, RngCore};
260
261 let sk = {
262 let mut out = [0u8; 32];
263 thread_rng().fill_bytes(&mut out);
264
265 StaticPrivateKey::from(out)
266 };
267 let sgk = {
268 let mut out = [0u8; 32];
269 thread_rng().fill_bytes(&mut out);
270
271 SigningPrivateKey::from(out)
272 };
273
274 let identity = RouterIdentity::from_keys::<MockRuntime>(&sk, &sgk).unwrap();
275
276 (identity, sk, sgk)
277 }
278}
279
280#[cfg(test)]
281mod tests {
282 use super::*;
283 use crate::crypto::base64_encode;
284
285 #[test]
286 fn expected_router_hash() {
287 let router = include_bytes!("../../test-vectors/router5.dat");
288 let identity = RouterIdentity::parse(router).unwrap();
289
290 assert_eq!(
291 base64_encode(&identity.identity_hash),
292 "u9QdTy~qBwh8Mrcfrcqvea8MOiNmavLv8Io4XQsMDHg="
293 );
294
295 let serialized = identity.serialize();
296 let parsed = RouterIdentity::parse(&serialized).unwrap();
297 assert_eq!(
298 base64_encode(&parsed.identity_hash),
299 "u9QdTy~qBwh8Mrcfrcqvea8MOiNmavLv8Io4XQsMDHg="
300 );
301 }
302
303 #[test]
304 fn too_short_router_identity() {
305 assert_eq!(
306 RouterIdentity::parse(vec![1, 2, 3, 4]).unwrap_err(),
307 RouterIdentityParseError::InvalidLength(4)
308 );
309 }
310
311 #[test]
312 fn serialize_deserialize() {
313 let (identity, _, _) = RouterIdentity::random();
314 let id = identity.id();
315
316 let serialized = identity.serialize();
317 let parsed = RouterIdentity::parse(&serialized).unwrap();
318 assert_eq!(parsed.id(), id);
319 }
320}