Skip to main content

emissary_core/primitives/
router_identity.rs

1// Permission is hereby granted, free of charge, to any person obtaining a
2// copy of this software and associated documentation files (the "Software"),
3// to deal in the Software without restriction, including without limitation
4// the rights to use, copy, modify, merge, publish, distribute, sublicense,
5// and/or sell copies of the Software, and to permit persons to whom the
6// Software is furnished to do so, subject to the following conditions:
7//
8// The above copyright notice and this permission notice shall be included in
9// all copies or substantial portions of the Software.
10//
11// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19use 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
40/// Length of serialized [`RouterIdentity`].
41const SERIALIZED_LEN: usize = 391usize;
42
43/// Key certificate.
44const KEY_CERTIFICATE: u8 = 0x05;
45
46/// Key certificate length.
47const KEY_CERTIFICATE_LEN: u16 = 0x04;
48
49/// Key kind for `EdDSA_SHA512_Ed25519`.
50///
51/// https://geti2p.net/spec/common-structures#key-certificates
52const KEY_KIND_EDDSA_SHA512_ED25519: u16 = 0x0007;
53
54/// Key kind for `X25519`.
55///
56/// https://geti2p.net/spec/common-structures#key-certificates
57const KEY_KIND_X25519: u16 = 0x0004;
58
59/// Short router identity hash.
60#[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    /// Copy [`RouterId`] into a byte vector.
73    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/// Router identity.
97#[derive(Debug, Clone)]
98pub struct RouterIdentity {
99    /// Identity hash.
100    identity_hash: Bytes,
101
102    /// Padding bytes.
103    padding: Bytes,
104
105    /// Router ID.
106    router: RouterId,
107
108    /// Router's signing key.
109    signing_key: SigningPublicKey,
110
111    /// Router's public key.
112    static_key: StaticPublicKey,
113}
114
115impl RouterIdentity {
116    /// Create new [`RouterIdentity`] from keys.
117    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    /// Parse [`RouterIdentity`] from `input`, returning rest of `input` and parsed router identity.
152    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                // call must succeed as the slice into `initial_bytes`
181                // and `public_key` are the same size
182                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    /// Try to parse router information from `bytes`.
210    #[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    /// Serialize [`RouterIdentity`] into a byte vector.
216    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    /// Get reference to router's static public key.
231    pub fn static_key(&self) -> &StaticPublicKey {
232        &self.static_key
233    }
234
235    /// Get reference to router's signing public key.
236    pub fn signing_key(&self) -> &SigningPublicKey {
237        &self.signing_key
238    }
239
240    /// Router identity hash as bytes.
241    pub fn hash(&self) -> Bytes {
242        self.identity_hash.clone()
243    }
244
245    /// Get [`RouterId`].
246    pub fn id(&self) -> RouterId {
247        self.router.clone()
248    }
249
250    /// Get serialized length of [`RouterIdentity`].
251    pub fn serialized_len(&self) -> usize {
252        SERIALIZED_LEN
253    }
254
255    /// Generate random [`RouterIdentity`].
256    #[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}