Skip to main content

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