Skip to main content

emissary_core/primitives/
destination.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
19//! Destination
20//!
21//! https://geti2p.net/spec/common-structures#destination
22
23use crate::{
24    crypto::{
25        base64_decode, base64_encode, sha256::Sha256, PrivateKeyKind, SigningKeyKind,
26        SigningPublicKey,
27    },
28    error::parser::DestinationParseError,
29    runtime::Runtime,
30};
31
32use bytes::{BufMut, Bytes, BytesMut};
33use nom::{
34    bytes::complete::take,
35    number::complete::{be_u16, be_u8},
36    sequence::tuple,
37    Err, IResult,
38};
39use rand_core::RngCore;
40
41use alloc::{string::String, sync::Arc, vec::Vec};
42use core::fmt;
43
44/// Null certificate.
45const NULL_CERTIFICATE: u8 = 0x00;
46
47/// Key certificate.
48const KEY_CERTIFICATE: u8 = 0x05;
49
50/// Key certificate length.
51const KEY_CERTIFICATE_LEN: u16 = 0x04;
52
53/// Padding length.
54///
55/// Consists of padding and an empty public key.
56const PADDING_LEN: usize = 320usize + 32usize;
57
58/// Key kind for `EdDSA_SHA512_Ed25519`.
59///
60/// https://geti2p.net/spec/common-structures#key-certificates
61const KEY_KIND_EDDSA_SHA512_ED25519: u16 = 0x0007;
62
63/// Serialized [`Destination`] length with key certificate
64const DESTINATION_WITH_KEY_CERT_LEN: usize = 391usize;
65
66/// Serialized [`Destination`] length with NULL certificate.
67const DESTINATION_WITH_NULL_CERT_LEN: usize = 387usize;
68
69/// Minimum serialized length of [`Destination`].
70const DESTINATION_MINIMUM_LEN: usize = 387usize;
71
72/// Serialized [`Destination`] length without certificate.
73const DESTINATION_LEN_NO_CERTIFICATE: usize = 384usize;
74
75/// Short destination identity hash.
76#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
77pub struct DestinationId(Arc<String>);
78
79impl DestinationId {
80    #[cfg(test)]
81    pub fn random() -> DestinationId {
82        use rand::Rng;
83
84        DestinationId::from(rand::thread_rng().gen::<[u8; 32]>())
85    }
86
87    /// Copy [`DestinationId`] into a byte vector.
88    pub fn to_vec(&self) -> Vec<u8> {
89        base64_decode(self.0.as_bytes()).expect("to succeed")
90    }
91}
92
93impl fmt::Display for DestinationId {
94    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95        write!(f, "{}", &self.0[..8])
96    }
97}
98
99impl<T: AsRef<[u8]>> From<T> for DestinationId {
100    fn from(value: T) -> Self {
101        DestinationId(Arc::new(base64_encode(value)))
102    }
103}
104
105/// Destination.
106#[derive(Debug, Clone, PartialEq, Eq)]
107pub struct Destination {
108    /// Destination ID.
109    destination_id: DestinationId,
110
111    /// Destinations' identity hash.
112    identity_hash: Bytes,
113
114    /// Private key length.
115    private_key_len: usize,
116
117    /// Serialized destination.
118    serialized: Bytes,
119
120    /// Signing key length.
121    signing_key_len: usize,
122
123    /// Destination's verifying key.
124    verifying_key: SigningPublicKey,
125}
126
127impl Destination {
128    /// Create new [`Destination`] from `verifying_key`.
129    pub fn new<R: Runtime>(verifying_key: SigningPublicKey) -> Self {
130        let serialized = {
131            let serialized_len = PADDING_LEN
132                .saturating_add(32usize) // signing public key
133                .saturating_add(1usize) // certificate type
134                .saturating_add(2usize) // certificate length
135                .saturating_add(4usize); // certificate payload length
136
137            let mut out = BytesMut::with_capacity(serialized_len);
138            let mut padding = [0u8; PADDING_LEN];
139            R::rng().fill_bytes(&mut padding);
140
141            out.put_slice(&padding);
142            out.put_slice(verifying_key.as_ref());
143            out.put_u8(KEY_CERTIFICATE);
144            out.put_u16(KEY_CERTIFICATE_LEN);
145            out.put_u16(KEY_KIND_EDDSA_SHA512_ED25519);
146
147            // public key type for elgamal
148            //
149            // setting this to 4 (which is the correct key type) causes issues with java
150            //
151            // more specifically, streaming SYN signature cannot be read
152            out.put_u16(0u16);
153
154            out.freeze()
155        };
156        let identity_hash = Sha256::new().update(&serialized).finalize();
157
158        Self {
159            destination_id: DestinationId::from(identity_hash.clone()),
160            identity_hash: Bytes::from(identity_hash),
161            private_key_len: 32, // x25519
162            serialized,
163            signing_key_len: 32, // ed25519
164            verifying_key,
165        }
166    }
167
168    /// Parse [`Destination`] from `input`, returning rest of `input` and parsed [`Destination`].
169    pub fn parse_frame(input: &[u8]) -> IResult<&[u8], Destination, DestinationParseError> {
170        if input.len() < DESTINATION_MINIMUM_LEN {
171            return Err(Err::Error(DestinationParseError::InvalidLength));
172        }
173
174        let (_, (initial_bytes, rest)) = tuple((
175            take(DESTINATION_LEN_NO_CERTIFICATE),
176            take(input.len() - DESTINATION_LEN_NO_CERTIFICATE),
177        ))(input)?;
178
179        let (rest, certificate_kind) = be_u8(rest)?;
180        let (rest, certificate_len) = be_u16(rest)?;
181
182        let (rest, verifying_key, signing_key_len, private_key_len, destination_len) =
183            match (certificate_kind, certificate_len) {
184                (NULL_CERTIFICATE, _) => (
185                    rest,
186                    SigningPublicKey::dsa_sha1(&initial_bytes[384 - 128..384])
187                        .ok_or(Err::Error(DestinationParseError::InvalidBitstream))?,
188                    256, // elgamal
189                    128, // dsa-sha1
190                    DESTINATION_WITH_NULL_CERT_LEN,
191                ),
192                (KEY_CERTIFICATE, KEY_CERTIFICATE_LEN) => {
193                    let (rest, signing_key_kind) = be_u16(rest)?;
194                    let (rest, private_key_kind) = be_u16(rest)?;
195
196                    let (verifying_key, signing_key_len) =
197                        match SigningKeyKind::try_from(signing_key_kind) {
198                            Ok(SigningKeyKind::DsaSha1(_)) =>
199                                return Err(Err::Error(DestinationParseError::NotANullCertificate)),
200                            Ok(SigningKeyKind::EcDsaSha256P256(size)) => (
201                                SigningPublicKey::p256(&initial_bytes[384 - 64..384])
202                                    .ok_or(Err::Error(DestinationParseError::InvalidBitstream))?,
203                                size,
204                            ),
205                            Ok(SigningKeyKind::EdDsaSha512Ed25519(size)) => {
206                                // call must succeed as the slice into `initial_bytes`
207                                // and `public_key` are the same size
208                                let public_key = TryInto::<[u8; 32]>::try_into(
209                                    initial_bytes[384 - 32..384].to_vec(),
210                                )
211                                .expect("to succeed");
212
213                                (
214                                    SigningPublicKey::from_bytes(&public_key).ok_or({
215                                        Err::Error(DestinationParseError::InvalidBitstream)
216                                    })?,
217                                    size,
218                                )
219                            }
220                            Err(()) =>
221                                return Err(Err::Error(
222                                    DestinationParseError::UnsupportedSigningKey(signing_key_kind),
223                                )),
224                        };
225
226                    let public_key_len = match PrivateKeyKind::try_from(private_key_kind) {
227                        Ok(PrivateKeyKind::ElGamal(size)) => size,
228                        Ok(PrivateKeyKind::P256(size)) => size,
229                        Ok(PrivateKeyKind::X25519(size)) => size,
230                        Err(()) =>
231                            return Err(Err::Error(DestinationParseError::UnsupportedPrivateKey(
232                                private_key_kind,
233                            ))),
234                    };
235
236                    (
237                        rest,
238                        verifying_key,
239                        signing_key_len,
240                        public_key_len,
241                        DESTINATION_WITH_KEY_CERT_LEN,
242                    )
243                }
244                (certificate_kind, _certificate_len) =>
245                    return Err(Err::Error(DestinationParseError::UnsupportedCertificate(
246                        certificate_kind,
247                    ))),
248            };
249
250        let identity_hash = Bytes::from(Sha256::new().update(&input[..destination_len]).finalize());
251        let serialized = Bytes::from(input[..destination_len].to_vec());
252
253        Ok((
254            rest,
255            Destination {
256                destination_id: DestinationId::from(identity_hash.clone()),
257                identity_hash,
258                serialized,
259                verifying_key,
260                private_key_len,
261                signing_key_len,
262            },
263        ))
264    }
265
266    /// Try to parse router information from `input`.
267    pub fn parse(input: impl AsRef<[u8]>) -> Result<Self, DestinationParseError> {
268        Ok(Self::parse_frame(input.as_ref())?.1)
269    }
270
271    /// Serialize [`Destination`] into a byte vector.
272    pub fn serialize(&self) -> Bytes {
273        self.serialized.clone()
274    }
275
276    /// Get serialized length of [`Destination`].
277    pub fn serialized_len(&self) -> usize {
278        let certificate_payload_len = match self.verifying_key {
279            SigningPublicKey::DsaSha1(_) => 0usize,
280            _ => 4usize,
281        };
282
283        32usize // all zeros public key
284            .saturating_add(320usize) // padding
285            .saturating_add(32usize) // signing public key
286            .saturating_add(1usize) // certificate type
287            .saturating_add(2usize) // certificate length
288            .saturating_add(certificate_payload_len)
289    }
290
291    /// Get [`DestinationId`].
292    pub fn id(&self) -> DestinationId {
293        self.destination_id.clone()
294    }
295
296    /// Get reference to `SigningPublicKey` of the [`Destination`].
297    pub fn verifying_key(&self) -> &SigningPublicKey {
298        &self.verifying_key
299    }
300
301    // Get length of the private key.
302    pub fn private_key_length(&self) -> usize {
303        self.private_key_len
304    }
305
306    // Get length of the signing key.
307    pub fn signing_key_length(&self) -> usize {
308        self.signing_key_len
309    }
310
311    /// Get reference to serialized [`Destination`].
312    pub fn serialized(&self) -> &Bytes {
313        &self.serialized
314    }
315
316    /// Create random [`Destination`] for testing.
317    #[cfg(test)]
318    pub fn random() -> (Self, crate::crypto::SigningPrivateKey) {
319        let signing_key = crate::crypto::SigningPrivateKey::random(rand::thread_rng());
320        (
321            Self::new::<crate::runtime::mock::MockRuntime>(signing_key.public()),
322            signing_key,
323        )
324    }
325}
326
327impl core::ops::Deref for Destination {
328    type Target = [u8];
329
330    fn deref(&self) -> &Self::Target {
331        &self.serialized
332    }
333}
334
335#[cfg(test)]
336mod tests {
337    use super::*;
338    use crate::{crypto::SigningPrivateKey, runtime::mock::MockRuntime};
339
340    #[test]
341    fn serialize_and_parse_destination() {
342        let signing_key = SigningPrivateKey::from_bytes(&[0xa; 32]).unwrap().public();
343        let destination = Destination::new::<MockRuntime>(signing_key.clone());
344
345        let serialized = destination.clone().serialize();
346        let parsed = Destination::parse(&serialized).unwrap();
347
348        assert_eq!(parsed.destination_id, destination.destination_id);
349        assert_eq!(
350            parsed.verifying_key.as_ref(),
351            destination.verifying_key.as_ref()
352        );
353    }
354
355    #[test]
356    fn too_small_input() {
357        assert_eq!(
358            Destination::parse(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).unwrap_err(),
359            DestinationParseError::InvalidLength
360        );
361    }
362
363    #[test]
364    fn deserialize_valid_destination() {
365        let input = vec![
366            216, 194, 83, 151, 200, 24, 84, 242, 184, 222, 34, 89, 37, 175, 254, 228, 173, 78, 114,
367            24, 15, 104, 241, 215, 166, 166, 102, 40, 136, 138, 22, 252, 114, 203, 192, 101, 32,
368            156, 212, 74, 177, 120, 153, 172, 221, 181, 175, 190, 178, 17, 71, 33, 39, 211, 208,
369            241, 30, 35, 222, 99, 215, 32, 242, 40, 202, 70, 197, 171, 84, 202, 52, 173, 221, 153,
370            242, 77, 240, 30, 133, 4, 126, 31, 105, 24, 87, 209, 111, 140, 122, 58, 242, 224, 61,
371            95, 144, 26, 25, 129, 202, 69, 130, 238, 88, 201, 34, 132, 197, 242, 129, 223, 50, 194,
372            130, 227, 102, 209, 79, 209, 70, 202, 48, 248, 32, 124, 230, 90, 90, 104, 199, 23, 141,
373            60, 213, 122, 20, 94, 223, 251, 48, 64, 30, 97, 36, 40, 194, 119, 98, 83, 29, 0, 31,
374            113, 241, 52, 72, 175, 208, 221, 251, 220, 146, 82, 235, 83, 172, 33, 118, 249, 114,
375            218, 149, 42, 76, 8, 137, 125, 81, 209, 156, 68, 75, 58, 79, 245, 124, 41, 243, 228,
376            244, 162, 239, 31, 176, 185, 44, 202, 6, 202, 200, 127, 247, 43, 80, 178, 76, 120, 211,
377            75, 157, 84, 199, 229, 62, 10, 51, 143, 31, 218, 237, 8, 232, 227, 1, 168, 159, 119,
378            35, 41, 43, 67, 241, 91, 87, 213, 118, 129, 172, 192, 92, 176, 79, 63, 80, 251, 160,
379            212, 50, 194, 46, 229, 59, 15, 48, 93, 62, 80, 237, 86, 159, 203, 194, 165, 80, 22,
380            108, 18, 64, 58, 210, 130, 124, 26, 198, 206, 159, 132, 252, 96, 155, 124, 35, 108,
381            231, 22, 53, 246, 114, 232, 108, 192, 249, 122, 24, 236, 5, 210, 53, 149, 124, 6, 12,
382            36, 59, 144, 19, 176, 11, 159, 46, 184, 45, 193, 58, 134, 179, 130, 176, 122, 34, 177,
383            172, 147, 35, 19, 123, 22, 176, 182, 216, 78, 246, 104, 110, 62, 111, 117, 110, 174,
384            49, 132, 214, 130, 96, 112, 30, 211, 159, 113, 131, 151, 166, 156, 206, 227, 20, 21,
385            115, 66, 8, 218, 103, 153, 78, 46, 127, 199, 169, 197, 168, 124, 158, 232, 115, 71,
386            104, 19, 165, 200, 234, 67, 168, 253, 137, 220, 5, 0, 4, 0, 7, 0, 0,
387        ];
388
389        let destination = Destination::parse(&input).unwrap();
390        let serialized = destination.serialize();
391
392        assert_eq!(input, *serialized);
393    }
394
395    #[test]
396    fn null_certificate_works() {
397        let input = vec![
398            89, 215, 97, 216, 78, 133, 203, 37, 193, 23, 180, 175, 81, 129, 202, 116, 223, 175,
399            141, 253, 255, 55, 171, 170, 65, 99, 94, 4, 52, 204, 208, 253, 247, 98, 56, 144, 8,
400            235, 50, 121, 218, 227, 152, 54, 102, 88, 90, 215, 80, 151, 201, 45, 105, 194, 111,
401            150, 231, 41, 236, 223, 147, 139, 131, 104, 204, 163, 254, 235, 195, 27, 252, 175, 45,
402            87, 5, 129, 195, 214, 73, 71, 123, 5, 241, 160, 202, 111, 179, 169, 193, 181, 171, 80,
403            220, 51, 203, 223, 186, 127, 148, 75, 182, 26, 152, 25, 102, 180, 46, 140, 103, 104,
404            254, 252, 136, 42, 206, 104, 44, 134, 43, 90, 241, 162, 207, 9, 243, 64, 3, 164, 186,
405            123, 101, 12, 142, 59, 70, 237, 2, 23, 151, 26, 76, 121, 206, 249, 118, 65, 221, 38,
406            85, 86, 111, 58, 228, 247, 63, 16, 130, 187, 183, 96, 137, 52, 83, 59, 88, 128, 76, 3,
407            52, 22, 230, 247, 2, 39, 177, 177, 225, 175, 113, 237, 1, 246, 180, 217, 7, 32, 69, 90,
408            145, 55, 99, 231, 65, 123, 170, 80, 155, 59, 71, 191, 244, 244, 86, 79, 18, 248, 162,
409            33, 197, 41, 145, 141, 197, 123, 34, 229, 95, 91, 32, 64, 80, 94, 25, 224, 61, 233,
410            185, 90, 62, 246, 77, 25, 222, 138, 156, 215, 96, 124, 184, 12, 121, 188, 121, 73, 44,
411            66, 248, 222, 10, 100, 196, 140, 7, 62, 92, 130, 137, 208, 23, 127, 230, 216, 113, 197,
412            69, 34, 60, 231, 58, 153, 52, 110, 87, 245, 178, 77, 243, 155, 124, 210, 91, 98, 191,
413            85, 181, 122, 207, 25, 157, 5, 184, 122, 205, 117, 175, 179, 43, 188, 147, 87, 207,
414            150, 230, 72, 126, 184, 215, 34, 72, 189, 46, 170, 35, 195, 137, 36, 218, 69, 84, 18,
415            16, 73, 114, 195, 251, 222, 147, 107, 42, 203, 64, 246, 152, 195, 251, 141, 103, 231,
416            151, 104, 78, 134, 229, 214, 33, 138, 227, 124, 196, 123, 5, 35, 84, 36, 117, 165, 26,
417            85, 153, 239, 12, 103, 236, 69, 186, 82, 228, 107, 105, 81, 176, 67, 111, 34, 228, 116,
418            251, 171, 27, 72, 187, 116, 221, 112, 0, 0, 0, 0, 0, 2, 6, 31, 139, 8, 0, 0, 1, 0, 0,
419            2, 17, 1, 239, 1, 16, 254, 186, 2, 0, 215, 250, 169, 148, 79, 97,
420        ];
421
422        let destination = Destination::parse(&input[..387]).unwrap();
423        let serialized = destination.serialize();
424
425        assert_eq!(&input[..387], &*serialized);
426    }
427}