1use crate::message::{NymMessage, NymMessageError, PaddedMessage, PlainMessage};
5use nym_crypto::aes::cipher::{KeyIvInit, StreamCipher};
6use nym_crypto::asymmetric::x25519;
7use nym_crypto::shared_key::recompute_shared_key;
8use nym_crypto::symmetric::stream_cipher;
9use nym_crypto::symmetric::stream_cipher::CipherKey;
10use nym_sphinx_anonymous_replies::SurbEncryptionKey;
11use nym_sphinx_anonymous_replies::requests::AnonymousSenderTag;
12use nym_sphinx_chunking::ChunkingError;
13use nym_sphinx_chunking::fragment::Fragment;
14use nym_sphinx_chunking::reconstruction::MessageReconstructor;
15use nym_sphinx_params::{
16 PacketEncryptionAlgorithm, PacketHkdfAlgorithm, ReplySurbEncryptionAlgorithm,
17};
18use thiserror::Error;
19
20#[derive(Debug)]
22pub struct ReconstructedMessage {
23 pub message: Vec<u8>,
25
26 pub sender_tag: Option<AnonymousSenderTag>,
29}
30
31impl From<ReconstructedMessage> for (Vec<u8>, Option<AnonymousSenderTag>) {
32 fn from(msg: ReconstructedMessage) -> Self {
33 (msg.message, msg.sender_tag)
34 }
35}
36
37impl ReconstructedMessage {
38 pub fn new(message: Vec<u8>, sender_tag: AnonymousSenderTag) -> Self {
39 Self {
40 message,
41 sender_tag: Some(sender_tag),
42 }
43 }
44
45 pub fn into_inner(self) -> (Vec<u8>, Option<AnonymousSenderTag>) {
46 self.into()
47 }
48}
49
50impl From<PlainMessage> for ReconstructedMessage {
51 fn from(message: PlainMessage) -> Self {
52 ReconstructedMessage {
53 message,
54 sender_tag: None,
55 }
56 }
57}
58
59#[derive(Debug, Error)]
60pub enum MessageRecoveryError {
61 #[error(
62 "The received message did not contain enough bytes to recover the ephemeral public key. Got {provided}. required: {required}"
63 )]
64 NotEnoughBytesForEphemeralKey { provided: usize, required: usize },
65
66 #[error("Recovered remote x25519 public key is invalid - {0}")]
67 InvalidRemoteEphemeralKey(#[from] x25519::KeyRecoveryError),
68
69 #[error("The reconstructed message was malformed - {source}")]
70 MalformedReconstructedMessage {
71 #[source]
72 source: NymMessageError,
73 used_sets: Vec<i32>,
74 },
75
76 #[error("Failed to recover message fragment - {0}")]
77 FragmentRecoveryError(#[from] ChunkingError),
78}
79
80pub trait MessageReceiver {
81 fn new() -> Self;
82 fn reconstructor(&mut self) -> &mut MessageReconstructor;
83
84 fn decrypt_raw_message<C>(
85 &self,
86 message: &mut [u8],
87 key: &CipherKey<C>,
88 ) -> Result<(), MessageRecoveryError>
89 where
90 C: StreamCipher + KeyIvInit;
91
92 fn recover_plaintext_from_reply(
93 &self,
94 reply_ciphertext: &mut [u8],
95 reply_key: SurbEncryptionKey,
96 ) -> Result<(), MessageRecoveryError> {
97 self.decrypt_raw_message::<ReplySurbEncryptionAlgorithm>(
98 reply_ciphertext,
99 reply_key.inner(),
100 )
101 }
102
103 fn recover_plaintext_from_regular_packet<'a>(
104 &self,
105 local_key: &x25519::PrivateKey,
106 raw_enc_frag: &'a mut [u8],
107 ) -> Result<&'a mut [u8], MessageRecoveryError> {
108 if raw_enc_frag.len() < x25519::PUBLIC_KEY_SIZE {
109 return Err(MessageRecoveryError::NotEnoughBytesForEphemeralKey {
110 provided: raw_enc_frag.len(),
111 required: x25519::PUBLIC_KEY_SIZE,
112 });
113 }
114
115 let remote_key_bytes = &raw_enc_frag[..x25519::PUBLIC_KEY_SIZE];
117 let remote_ephemeral_key = x25519::PublicKey::from_bytes(remote_key_bytes)?;
118
119 let encryption_key = recompute_shared_key::<PacketEncryptionAlgorithm, PacketHkdfAlgorithm>(
121 &remote_ephemeral_key,
122 local_key,
123 );
124
125 let fragment_ciphertext = &mut raw_enc_frag[x25519::PUBLIC_KEY_SIZE..];
127
128 self.decrypt_raw_message::<PacketEncryptionAlgorithm>(
129 fragment_ciphertext,
130 &encryption_key,
131 )?;
132 let fragment_data = fragment_ciphertext;
133
134 Ok(fragment_data)
135 }
136
137 fn recover_fragment(&self, frag_data: &[u8]) -> Result<Fragment, MessageRecoveryError> {
138 Ok(Fragment::try_from_bytes(frag_data)?)
139 }
140
141 fn insert_new_fragment(
142 &mut self,
143 fragment: Fragment,
144 ) -> Result<Option<(NymMessage, Vec<i32>)>, MessageRecoveryError> {
145 if let Some((message, used_sets)) = self.reconstructor().insert_new_fragment(fragment) {
146 match PaddedMessage::new_reconstructed(message).remove_padding() {
147 Ok(message) => Ok(Some((message, used_sets))),
148 Err(err) => Err(MessageRecoveryError::MalformedReconstructedMessage {
149 source: err,
150 used_sets,
151 }),
152 }
153 } else {
154 Ok(None)
155 }
156 }
157}
158
159#[derive(Clone, Default)]
160pub struct SphinxMessageReceiver {
161 reconstructor: MessageReconstructor,
164}
165
166impl MessageReceiver for SphinxMessageReceiver {
167 fn new() -> Self {
168 Default::default()
169 }
170
171 fn decrypt_raw_message<C>(
172 &self,
173 message: &mut [u8],
174 key: &CipherKey<C>,
175 ) -> Result<(), MessageRecoveryError>
176 where
177 C: StreamCipher + KeyIvInit,
178 {
179 let zero_iv = stream_cipher::zero_iv::<C>();
180 stream_cipher::decrypt_in_place::<C>(key, &zero_iv, message);
181 Ok(())
182 }
183
184 fn reconstructor(&mut self) -> &mut MessageReconstructor {
185 &mut self.reconstructor
186 }
187}