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}