1use crate::{
2 constants::{DEFAULT_HOPS, MAGIC_SLICE, MIN_PACKET_SIZE, MIX_PARAMS_LEN},
3 error::OutfoxError,
4 format::{MixCreationParameters, MixStageParameters},
5};
6use sphinx_packet::{
7 crypto::PrivateKey,
8 packet::builder::DEFAULT_PAYLOAD_SIZE,
9 route::{Destination, Node},
10};
11use std::{array::TryFromSliceError, collections::VecDeque, ops::Range};
12
13#[derive(Debug)]
14pub struct OutfoxPacket {
15 mix_params: MixCreationParameters,
16 payload: Vec<u8>,
17}
18
19pub struct OutfoxProcessedPacket {
20 packet: OutfoxPacket,
21 next_address: [u8; 32],
22}
23
24impl OutfoxProcessedPacket {
25 pub fn new(packet: OutfoxPacket, next_address: [u8; 32]) -> Self {
26 OutfoxProcessedPacket {
27 packet,
28 next_address,
29 }
30 }
31
32 pub fn into_packet(self) -> OutfoxPacket {
33 self.packet
34 }
35
36 pub fn next_address(&self) -> &[u8; 32] {
37 &self.next_address
38 }
39}
40
41impl TryFrom<&[u8]> for OutfoxPacket {
42 type Error = OutfoxError;
43
44 fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
45 let (header, payload) = v.split_at(MIX_PARAMS_LEN);
46 Ok(OutfoxPacket {
47 mix_params: MixCreationParameters::try_from(header)?,
48 payload: payload.to_vec(),
49 })
50 }
51}
52
53impl OutfoxPacket {
54 pub fn recover_plaintext(&self) -> Result<Vec<u8>, OutfoxError> {
55 let plaintext = self.payload()[self.payload_range()].to_vec();
56 let mut plaintext = VecDeque::from_iter(plaintext);
57 while let Some(0) = plaintext.front() {
58 plaintext.pop_front();
59 }
60 let mut plaintext = plaintext.make_contiguous().to_vec();
61 let payload = plaintext.split_off(MAGIC_SLICE.len());
62 if plaintext != MAGIC_SLICE {
63 Err(OutfoxError::InvalidMagicBytes(plaintext))
64 } else {
65 Ok(payload)
66 }
67 }
68
69 pub fn len(&self) -> usize {
70 self.mix_params().total_packet_length() + MIX_PARAMS_LEN
71 }
72
73 pub fn is_empty(&self) -> bool {
74 self.len() == 0
75 }
76
77 pub fn to_bytes(&self) -> Result<Vec<u8>, OutfoxError> {
78 let mut bytes = vec![];
79 bytes.extend(self.mix_params.to_bytes());
80 bytes.extend(self.payload.as_slice());
81 Ok(bytes)
82 }
83
84 pub fn build<M: AsRef<[u8]>>(
85 payload: M,
86 route: &[Node; 4],
87 destination: &Destination,
88 packet_size: Option<usize>,
89 ) -> Result<OutfoxPacket, OutfoxError> {
90 let secret_key = x25519_dalek::StaticSecret::random();
91 let packet_size = packet_size.unwrap_or(DEFAULT_PAYLOAD_SIZE);
92 let packet_size = if packet_size < MIN_PACKET_SIZE {
93 MIN_PACKET_SIZE
94 } else {
95 packet_size
96 } + MAGIC_SLICE.len();
97 let mix_params = MixCreationParameters::new(packet_size as u16);
98
99 let padding = mix_params.total_packet_length() - payload.as_ref().len() - MAGIC_SLICE.len();
100 let mut buffer = vec![0; padding];
101 buffer.extend_from_slice(MAGIC_SLICE);
102 buffer.extend_from_slice(payload.as_ref());
103
104 let (range, stage_params) = mix_params.get_stage_params(0);
106 stage_params.encode_mix_layer(
107 &mut buffer[range],
108 &secret_key,
109 route.last().unwrap().pub_key,
110 destination.address.as_bytes_ref(),
111 )?;
112
113 let route = route.iter().rev().collect::<Vec<&Node>>();
114
115 for (idx, nodes) in route.windows(2).enumerate() {
125 let (range, stage_params) = mix_params.get_stage_params(idx + 1);
126 let processing_node = nodes.last().unwrap();
128 let destination_node = nodes.first().unwrap();
129 let secret_key = x25519_dalek::StaticSecret::random();
130 stage_params.encode_mix_layer(
131 &mut buffer[range],
132 &secret_key,
133 processing_node.pub_key,
134 destination_node.address.as_bytes(),
135 )?;
136 }
137
138 Ok(OutfoxPacket {
139 mix_params,
140 payload: buffer,
141 })
142 }
143
144 pub fn stage_params(&self, layer_number: usize) -> (Range<usize>, MixStageParameters) {
145 self.mix_params().get_stage_params(layer_number)
146 }
147
148 pub fn mix_params(&self) -> &MixCreationParameters {
149 &self.mix_params
150 }
151
152 pub fn payload(&self) -> &[u8] {
153 &self.payload
154 }
155
156 pub fn payload_range(&self) -> Range<usize> {
157 self.stage_params(DEFAULT_HOPS - 1).1.payload_range()
158 }
159
160 pub fn payload_mut(&mut self) -> &mut [u8] {
161 &mut self.payload
162 }
163
164 pub fn decode_mix_layer(
165 &mut self,
166 layer: usize,
167 mix_secret_key: &x25519_dalek::StaticSecret,
168 ) -> Result<Vec<u8>, OutfoxError> {
169 let (range, params) = self.stage_params(layer);
170 let routing_data =
171 params.decode_mix_layer(&mut self.payload_mut()[range], mix_secret_key)?;
172 Ok(routing_data)
173 }
174
175 pub fn update_routing_information(&mut self, layer: usize) -> Result<(), TryFromSliceError> {
176 let mut routing_info = self
177 .mix_params()
178 .routing_information_length_by_stage
179 .to_vec();
180 routing_info.push(0);
181 routing_info.swap_remove(layer);
182 self.mix_params.routing_information_length_by_stage = routing_info.as_slice().try_into()?;
183 Ok(())
184 }
185
186 pub fn is_final_hop(&self) -> bool {
187 self.mix_params()
188 .routing_information_length_by_stage
189 .iter()
190 .all(|x| x == &0)
191 }
192
193 pub fn decode_next_layer(
194 &mut self,
195 mix_secret_key: &PrivateKey,
196 ) -> Result<[u8; 32], OutfoxError> {
197 let routing_lenght_by_stage = self
198 .mix_params()
199 .routing_information_length_by_stage
200 .as_slice();
201 let mut layer = DEFAULT_HOPS - 1;
202 for (i, length) in routing_lenght_by_stage.iter().rev().enumerate() {
203 if length == &32 {
204 layer = DEFAULT_HOPS - 1 - i;
205 break;
206 }
207 }
208 self.decode_mix_layer(layer, mix_secret_key)?;
209 self.update_routing_information(layer)?;
210 let (range, stage_params) = self.mix_params().get_stage_params(layer);
211 let routing_bytes = &self.payload()[range][stage_params.routing_data_range()];
212 let routing_address: [u8; 32] = routing_bytes.try_into()?;
213 Ok(routing_address)
214 }
215}