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}