sphinx_packet/header/
filler.rs1use crate::constants::{HEADER_INTEGRITY_MAC_SIZE, MAX_PATH_LENGTH, NODE_META_INFO_SIZE};
16use crate::crypto;
17use crate::header::shared_secret::ExpandedSharedSecret;
18use crate::{constants, utils};
19
20pub const FILLER_STEP_SIZE_INCREASE: usize = NODE_META_INFO_SIZE + HEADER_INTEGRITY_MAC_SIZE;
21
22#[derive(Debug, PartialEq, Eq)]
23pub struct Filler(Vec<u8>);
24
25impl Filler {
26 pub(crate) fn new(expanded_shared_secrets: &[ExpandedSharedSecret]) -> Self {
27 assert!(expanded_shared_secrets.len() <= MAX_PATH_LENGTH);
28 let filler_value = expanded_shared_secrets
29 .iter()
30 .map(|ess| ess.stream_cipher_key()) .map(|cipher_key| {
32 crypto::generate_pseudorandom_bytes(
33 cipher_key,
34 &crypto::STREAM_CIPHER_INIT_VECTOR,
35 constants::STREAM_CIPHER_OUTPUT_LENGTH,
36 )
37 }) .enumerate() .map(|(i, pseudorandom_bytes)| (i + 1, pseudorandom_bytes)) .fold(
41 Vec::new(),
42 |filler_string_accumulator, (i, pseudorandom_bytes)| {
43 Self::filler_step(filler_string_accumulator, i, pseudorandom_bytes)
44 },
45 );
46 Self(filler_value)
47 }
48
49 fn filler_step(
50 mut filler_string_accumulator: Vec<u8>,
51 i: usize,
52 pseudorandom_bytes: Vec<u8>,
53 ) -> Vec<u8> {
54 assert_eq!(
55 pseudorandom_bytes.len(),
56 constants::STREAM_CIPHER_OUTPUT_LENGTH
57 );
58 assert_eq!(
59 filler_string_accumulator.len(),
60 FILLER_STEP_SIZE_INCREASE * (i - 1) );
62 let zero_bytes = vec![0u8; FILLER_STEP_SIZE_INCREASE];
63 filler_string_accumulator.extend(&zero_bytes);
64
65 utils::bytes::xor_with(
68 &mut filler_string_accumulator,
69 &pseudorandom_bytes[pseudorandom_bytes.len() - i * FILLER_STEP_SIZE_INCREASE..],
70 );
71
72 filler_string_accumulator
73 }
74}
75
76impl From<Vec<u8>> for Filler {
77 fn from(raw_bytes: Vec<u8>) -> Self {
78 Self(raw_bytes)
79 }
80}
81
82impl From<Filler> for Vec<u8> {
83 fn from(filler: Filler) -> Self {
84 filler.0
85 }
86}
87
88#[cfg(test)]
89mod test_creating_pseudorandom_bytes {
90 use super::*;
91 use crate::header::shared_secret::ExpandSecret;
92 use x25519_dalek::{PublicKey, StaticSecret};
93
94 #[test]
95 fn with_no_keys_it_generates_empty_filler_string() {
96 let expanded_shared_secret: Vec<_> = vec![];
97 let filler_string = Filler::new(&expanded_shared_secret);
98
99 assert_eq!(0, filler_string.0.len());
100 }
101
102 #[test]
103 fn with_1_key_it_generates_filler_of_length_1_times_3_times_security_parameter() {
104 let shared_keys = [PublicKey::from(&StaticSecret::random())];
105 let expanded_shared_secret: Vec<_> = shared_keys
106 .iter()
107 .map(|&key| key.expand_shared_secret())
108 .collect();
109 let filler_string = Filler::new(&expanded_shared_secret);
110
111 assert_eq!(FILLER_STEP_SIZE_INCREASE, filler_string.0.len());
112 }
113
114 #[test]
115 fn with_3_key_it_generates_filler_of_length_3_times_3_times_security_parameter() {
116 let shared_keys = [
117 PublicKey::from(&StaticSecret::random()),
118 PublicKey::from(&StaticSecret::random()),
119 PublicKey::from(&StaticSecret::random()),
120 ];
121 let expanded_shared_secret: Vec<_> = shared_keys
122 .iter()
123 .map(|&key| key.expand_shared_secret())
124 .collect();
125 let filler_string = Filler::new(&expanded_shared_secret);
126 assert_eq!(3 * FILLER_STEP_SIZE_INCREASE, filler_string.0.len());
127 }
128
129 #[test]
130 #[should_panic]
131 fn panics_with_more_keys_than_the_maximum_path_length() {
132 let shared_keys: Vec<_> = std::iter::repeat_n((), constants::MAX_PATH_LENGTH + 1)
133 .map(|_| PublicKey::from(&StaticSecret::random()))
134 .collect();
135 let expanded_shared_secrets: Vec<_> = shared_keys
136 .iter()
137 .map(|&key| key.expand_shared_secret())
138 .collect();
139 Filler::new(&expanded_shared_secrets);
140 }
141}
142
143#[cfg(test)]
144mod test_new_filler_bytes {
145 use super::*;
146 use crate::test_utils::fixtures::expanded_shared_secret_fixture;
147
148 #[test]
149 fn it_retusn_filler_bytes_of_correct_length_for_3_expanded_shared_secret() {
150 let routing_key_1 = expanded_shared_secret_fixture();
151 let routing_key_2 = expanded_shared_secret_fixture();
152 let routing_key_3 = expanded_shared_secret_fixture();
153 let expanded_shared_secret = [routing_key_1, routing_key_2, routing_key_3];
154 let filler = Filler::new(&expanded_shared_secret);
155 assert_eq!(
156 FILLER_STEP_SIZE_INCREASE * (expanded_shared_secret.len()),
157 filler.0.len()
158 )
159 }
160
161 #[test]
162 fn it_retusn_filler_bytes_of_correct_length_for_4_expanded_shared_secret() {
163 let routing_key_1 = expanded_shared_secret_fixture();
164 let routing_key_2 = expanded_shared_secret_fixture();
165 let routing_key_3 = expanded_shared_secret_fixture();
166 let routing_key_4 = expanded_shared_secret_fixture();
167 let expanded_shared_secret = [routing_key_1, routing_key_2, routing_key_3, routing_key_4];
168 let filler = Filler::new(&expanded_shared_secret);
169 assert_eq!(
170 FILLER_STEP_SIZE_INCREASE * (expanded_shared_secret.len()),
171 filler.0.len()
172 )
173 }
174}
175
176#[cfg(test)]
177mod test_generating_filler_bytes {
178 use super::*;
179
180 mod for_valid_inputs {
181 use super::*;
182
183 #[test]
184 fn it_returns_the_xored_byte_vector_of_a_correct_length_for_i_1() {
185 let pseudorandom_bytes = vec![0; constants::STREAM_CIPHER_OUTPUT_LENGTH];
186 let filler_string_accumulator = vec![];
187 let filler_string =
188 Filler::filler_step(filler_string_accumulator, 1, pseudorandom_bytes);
189 assert_eq!(FILLER_STEP_SIZE_INCREASE, filler_string.len());
190 for x in filler_string {
191 assert_eq!(0, x); }
193 }
194
195 #[test]
196 fn it_returns_the_xored_byte_vector_of_a_correct_length_for_i_3() {
197 let pseudorandom_bytes = vec![0; constants::STREAM_CIPHER_OUTPUT_LENGTH];
198 let filler_string_accumulator = vec![0u8; 2 * FILLER_STEP_SIZE_INCREASE];
199 let filler_string =
200 Filler::filler_step(filler_string_accumulator, 3, pseudorandom_bytes);
201 assert_eq!(FILLER_STEP_SIZE_INCREASE * 3, filler_string.len());
202 for x in filler_string {
203 assert_eq!(0, x); }
205 }
206
207 mod for_an_empty_filler_string_accumulator {
208 use super::*;
209
210 #[test]
211 #[should_panic]
212 fn it_panics() {
213 let pseudorandom_bytes = vec![0; constants::STREAM_CIPHER_OUTPUT_LENGTH];
214 Filler::filler_step(vec![], 0, pseudorandom_bytes);
215 }
216 }
217 }
218
219 mod for_invalid_inputs {
220 use super::*;
221
222 #[test]
223 #[should_panic]
224 fn panics_for_incorrectly_sized_pseudorandom_bytes_vector_and_accumulator_vector() {
225 let pseudorandom_bytes = vec![0; 1];
226 Filler::filler_step(vec![], 0, pseudorandom_bytes);
227 }
228
229 #[test]
230 #[should_panic]
231 fn panics_with_incorrect_length_filler_accumulator() {
232 let good_pseudorandom_bytes = vec![0; constants::STREAM_CIPHER_OUTPUT_LENGTH];
233 let wrong_accumulator = vec![0; 25];
234 Filler::filler_step(wrong_accumulator, 1, good_pseudorandom_bytes);
235 }
236 }
237}