hopr_crypto_sphinx/
lib.rs

1//! This Rust crate contains an implementation of the Sphinx packet format for the HOPR protocol.
2//!
3//! ## SPHINX shared keys derivation
4//! The architecture of the SPHINX shared key derivation is done generically, so it can work with any
5//! elliptic curve group for which the CDH problem is hard. The generic Sphinx implementation only
6//! requires one to implement the `SphinxSuite` trait.
7//!
8//! The trait requires having the following building blocks:
9//! - elliptic curve group ([GroupElement](shared_keys::GroupElement)) and corresponding the scalar type
10//!   ([Scalar](shared_keys::Scalar))
11//! - type representing public and private keypair and their conversion to [Scalar](shared_keys::Scalar) and
12//!   [GroupElement](shared_keys::GroupElement) (by the means of the corresponding `From` trait implementation)
13//!
14//! Currently, there are the following [SphinxSuite](crate::shared_keys::SphinxSuite) implementations:
15//! - `Secp256k1Suite`: deprecated, used in previous HOPR versions
16//! - `Ed25519Suite`: simple implementation using Ed25519, used for testing
17//! - [X25519Suite](crate::ec_groups::X25519Suite) currently used, implemented using the Curve25519 Montgomery curve for
18//!   faster computation
19//!
20//! The implementation can be easily extended for different elliptic curves (or even arithmetic multiplicative groups).
21//! In particular, as soon as there is a way to represent `Ed448` PeerIDs, it would be easy to create e.g., an
22//! `X448Suite`.
23
24/// Contains simple key derivation functions for different purposes
25mod derivation;
26/// Implementations of the ` SphinxSuite ` trait for different elliptic curve groups
27mod ec_groups;
28/// Contains various errors returned from this crate.
29pub mod errors;
30/// Contains the main implementation of a SPHINX packet.
31mod packet;
32/// Implementation of the SPHINX header format
33mod routing;
34/// Derivation of shared keys for SPHINX header
35mod shared_keys;
36/// Contains Return Path and SURB-related types
37mod surb;
38
39pub mod prelude {
40    pub use crate::{
41        ec_groups::*,
42        packet::{ForwardedMetaPacket, KeyIdMapper, MetaPacket, MetaPacketRouting, PaddedPayload, PartialPacket},
43        routing::SphinxHeaderSpec,
44        shared_keys::{SharedKeys, SharedSecret, SphinxSuite},
45        surb::*,
46    };
47}
48
49#[cfg(test)]
50pub(crate) mod tests {
51    use std::{
52        marker::PhantomData,
53        num::{NonZero, NonZeroUsize},
54    };
55
56    use hopr_crypto_types::prelude::*;
57    use hopr_primitive_types::{errors::GeneralError, prelude::*};
58
59    use crate::routing::SphinxHeaderSpec;
60
61    #[derive(Debug, Clone, Copy, PartialEq)]
62    pub(crate) struct WrappedBytes<const N: usize>(pub [u8; N]);
63
64    impl<const N: usize> Default for WrappedBytes<N> {
65        fn default() -> Self {
66            Self([0u8; N])
67        }
68    }
69
70    impl<'a, const N: usize> TryFrom<&'a [u8]> for WrappedBytes<N> {
71        type Error = GeneralError;
72
73        fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
74            value
75                .try_into()
76                .map(Self)
77                .map_err(|_| GeneralError::ParseError("WrappedBytes".into()))
78        }
79    }
80
81    impl<const N: usize> AsRef<[u8]> for WrappedBytes<N> {
82        fn as_ref(&self) -> &[u8] {
83            &self.0
84        }
85    }
86
87    impl<const N: usize> BytesRepresentable for WrappedBytes<N> {
88        const SIZE: usize = N;
89    }
90
91    pub(crate) struct TestSpec<K, const HOPS: usize, const RELAYER_DATA: usize>(PhantomData<K>);
92    impl<K, const HOPS: usize, const RELAYER_DATA: usize> SphinxHeaderSpec for TestSpec<K, HOPS, RELAYER_DATA>
93    where
94        K: AsRef<[u8]> + for<'a> TryFrom<&'a [u8], Error = GeneralError> + BytesRepresentable + Clone,
95    {
96        type KeyId = K;
97        type PRG = ChaCha20;
98        type PacketReceiverData = SimplePseudonym;
99        type Pseudonym = SimplePseudonym;
100        type RelayerData = WrappedBytes<RELAYER_DATA>;
101        type SurbReceiverData = WrappedBytes<53>;
102        type UH = Poly1305;
103
104        const MAX_HOPS: NonZeroUsize = NonZero::new(HOPS).unwrap();
105    }
106}