1use aes::cipher::{BlockEncrypt, KeyInit};
2use aes::Aes128;
3use aes::Block;
4use std::net::IpAddr;
5
6use crate::common::{bytes_to_ip, ip_to_bytes};
7
8pub struct IpcryptPfx {
10 cipher1: Aes128,
11 cipher2: Aes128,
12}
13
14impl IpcryptPfx {
15 pub const KEY_BYTES: usize = 32;
17
18 pub fn generate_key() -> [u8; Self::KEY_BYTES] {
20 rand::random()
21 }
22
23 pub fn new(key: [u8; Self::KEY_BYTES]) -> Self {
34 let (k1, k2) = key.split_at(16);
36
37 assert_ne!(k1, k2, "The two halves of the key must be different");
39
40 let cipher1 = Aes128::new_from_slice(k1).expect("key length is guaranteed to be correct");
41 let cipher2 = Aes128::new_from_slice(k2).expect("key length is guaranteed to be correct");
42
43 Self { cipher1, cipher2 }
44 }
45
46 pub fn new_random() -> Self {
48 loop {
49 let key = Self::generate_key();
50 let (k1, k2) = key.split_at(16);
51 if k1 != k2 {
52 return Self::new(key);
53 }
54 }
55 }
56
57 pub fn encrypt_ipaddr(&self, ip: IpAddr) -> IpAddr {
67 let bytes = ip_to_bytes(ip);
68 let encrypted = self.encrypt_bytes(&bytes, ip);
69 bytes_to_ip(encrypted)
70 }
71
72 pub fn decrypt_ipaddr(&self, encrypted: IpAddr) -> IpAddr {
82 let encrypted_bytes = ip_to_bytes(encrypted);
83 let decrypted = self.decrypt_bytes(&encrypted_bytes, encrypted);
84 bytes_to_ip(decrypted)
85 }
86
87 fn encrypt_bytes(&self, bytes: &[u8; 16], ip: IpAddr) -> [u8; 16] {
89 let mut encrypted = [0u8; 16];
90
91 let prefix_start = if ip.is_ipv4() { 96 } else { 0 };
93
94 if ip.is_ipv4() {
96 encrypted[..12].copy_from_slice(&bytes[..12]);
97 }
98
99 let mut padded_prefix = if prefix_start == 0 {
101 Self::pad_prefix_0()
102 } else {
103 Self::pad_prefix_96()
104 };
105
106 for prefix_len_bits in prefix_start..128 {
108 let mut block1 = Block::from(padded_prefix);
110 let mut block2 = Block::from(padded_prefix);
111
112 self.cipher1.encrypt_block(&mut block1);
113 self.cipher2.encrypt_block(&mut block2);
114
115 let e1: [u8; 16] = block1.into();
117 let e2: [u8; 16] = block2.into();
118 let mut e = [0u8; 16];
119 for i in 0..16 {
120 e[i] = e1[i] ^ e2[i];
121 }
122
123 let cipher_bit = e[15] & 1;
125
126 let bit_pos = 127 - prefix_len_bits;
128 let original_bit = Self::get_bit(bytes, bit_pos);
129
130 Self::set_bit(&mut encrypted, bit_pos, cipher_bit ^ original_bit);
132
133 padded_prefix = Self::shift_left_one_bit(&padded_prefix);
135 Self::set_bit(&mut padded_prefix, 0, original_bit);
136 }
137
138 encrypted
139 }
140
141 fn decrypt_bytes(&self, encrypted_bytes: &[u8; 16], encrypted_ip: IpAddr) -> [u8; 16] {
143 let mut decrypted = [0u8; 16];
144
145 let prefix_start = if encrypted_ip.is_ipv4() { 96 } else { 0 };
147
148 if prefix_start == 96 {
150 decrypted[10..12].copy_from_slice(&[0xFF; 2]);
151 }
152
153 let mut padded_prefix = if prefix_start == 0 {
155 Self::pad_prefix_0()
156 } else {
157 Self::pad_prefix_96()
158 };
159
160 for prefix_len_bits in prefix_start..128 {
162 let mut block1 = Block::from(padded_prefix);
164 let mut block2 = Block::from(padded_prefix);
165
166 self.cipher1.encrypt_block(&mut block1);
167 self.cipher2.encrypt_block(&mut block2);
168
169 let e1: [u8; 16] = block1.into();
171 let e2: [u8; 16] = block2.into();
172 let mut e = [0u8; 16];
173 for i in 0..16 {
174 e[i] = e1[i] ^ e2[i];
175 }
176
177 let cipher_bit = e[15] & 1;
179
180 let bit_pos = 127 - prefix_len_bits;
182 let encrypted_bit = Self::get_bit(encrypted_bytes, bit_pos);
183 let original_bit = cipher_bit ^ encrypted_bit;
184
185 Self::set_bit(&mut decrypted, bit_pos, original_bit);
187
188 padded_prefix = Self::shift_left_one_bit(&padded_prefix);
190 Self::set_bit(&mut padded_prefix, 0, original_bit);
191 }
192
193 decrypted
194 }
195
196 fn get_bit(data: &[u8; 16], position: usize) -> u8 {
199 let byte_index = 15 - (position / 8);
200 let bit_index = position % 8;
201 (data[byte_index] >> bit_index) & 1
202 }
203
204 fn set_bit(data: &mut [u8; 16], position: usize, value: u8) {
207 let byte_index = 15 - (position / 8);
208 let bit_index = position % 8;
209 if value != 0 {
210 data[byte_index] |= 1 << bit_index;
211 } else {
212 data[byte_index] &= !(1 << bit_index);
213 }
214 }
215
216 fn shift_left_one_bit(data: &[u8; 16]) -> [u8; 16] {
219 let mut result = [0u8; 16];
220 let mut carry = 0;
221
222 for i in (0..16).rev() {
224 result[i] = (data[i] << 1) | carry;
226 carry = (data[i] >> 7) & 1;
228 }
229
230 result
231 }
232
233 fn pad_prefix_0() -> [u8; 16] {
236 let mut padded = [0u8; 16];
237 padded[15] = 0x01; padded
239 }
240
241 fn pad_prefix_96() -> [u8; 16] {
245 let mut padded = [0u8; 16];
246 padded[3] = 0x01; padded[14] = 0xFF;
248 padded[15] = 0xFF;
249 padded
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256 use ct_codecs::{Decoder as _, Hex};
257 use std::str::FromStr;
258
259 #[test]
260 fn test_pfx_basic_vectors() {
261 let test_vectors = vec![
262 (
264 "0123456789abcdeffedcba98765432101032547698badcfeefcdab8967452301",
265 "0.0.0.0",
266 "151.82.155.134",
267 ),
268 (
270 "0123456789abcdeffedcba98765432101032547698badcfeefcdab8967452301",
271 "255.255.255.255",
272 "94.185.169.89",
273 ),
274 (
276 "0123456789abcdeffedcba98765432101032547698badcfeefcdab8967452301",
277 "192.0.2.1",
278 "100.115.72.131",
279 ),
280 (
282 "0123456789abcdeffedcba98765432101032547698badcfeefcdab8967452301",
283 "2001:db8::1",
284 "c180:5dd4:2587:3524:30ab:fa65:6ab6:f88",
285 ),
286 ];
287
288 for (key_hex, input_ip, expected_output) in test_vectors {
289 let key_vec = Hex::decode_to_vec(key_hex.as_bytes(), None).unwrap();
291 let mut key = [0u8; IpcryptPfx::KEY_BYTES];
292 key.copy_from_slice(&key_vec);
293
294 let ipcrypt = IpcryptPfx::new(key);
296
297 let ip = IpAddr::from_str(input_ip).unwrap();
299
300 let encrypted = ipcrypt.encrypt_ipaddr(ip);
302 assert_eq!(encrypted.to_string(), expected_output);
303
304 let decrypted = ipcrypt.decrypt_ipaddr(encrypted);
306 assert_eq!(decrypted, ip);
307 }
308 }
309
310 #[test]
311 fn test_pfx_prefix_preserving_ipv4_24() {
312 let key_hex = "2b7e151628aed2a6abf7158809cf4f3ca9f5ba40db214c3798f2e1c23456789a";
313 let key_vec = Hex::decode_to_vec(key_hex.as_bytes(), None).unwrap();
314 let mut key = [0u8; IpcryptPfx::KEY_BYTES];
315 key.copy_from_slice(&key_vec);
316 let ipcrypt = IpcryptPfx::new(key);
317
318 let test_cases = vec![
320 ("10.0.0.47", "19.214.210.244"),
321 ("10.0.0.129", "19.214.210.80"),
322 ("10.0.0.234", "19.214.210.30"),
323 ];
324
325 for (input_ip, expected_output) in test_cases {
326 let ip = IpAddr::from_str(input_ip).unwrap();
327 let encrypted = ipcrypt.encrypt_ipaddr(ip);
328 assert_eq!(encrypted.to_string(), expected_output);
329
330 let decrypted = ipcrypt.decrypt_ipaddr(encrypted);
331 assert_eq!(decrypted, ip);
332 }
333
334 let ip1 = IpAddr::from_str("10.0.0.47").unwrap();
336 let ip2 = IpAddr::from_str("10.0.0.129").unwrap();
337 let ip3 = IpAddr::from_str("10.0.0.234").unwrap();
338
339 let enc1 = ipcrypt.encrypt_ipaddr(ip1);
340 let enc2 = ipcrypt.encrypt_ipaddr(ip2);
341 let enc3 = ipcrypt.encrypt_ipaddr(ip3);
342
343 assert!(enc1.is_ipv4());
345 assert!(enc2.is_ipv4());
346 assert!(enc3.is_ipv4());
347
348 let enc1_bytes = match enc1 {
350 IpAddr::V4(ip) => ip.octets(),
351 _ => panic!("Expected IPv4"),
352 };
353 let enc2_bytes = match enc2 {
354 IpAddr::V4(ip) => ip.octets(),
355 _ => panic!("Expected IPv4"),
356 };
357 let enc3_bytes = match enc3 {
358 IpAddr::V4(ip) => ip.octets(),
359 _ => panic!("Expected IPv4"),
360 };
361
362 assert_eq!(enc1_bytes[0], enc2_bytes[0]);
364 assert_eq!(enc1_bytes[0], enc3_bytes[0]);
365 assert_eq!(enc1_bytes[1], enc2_bytes[1]);
366 assert_eq!(enc1_bytes[1], enc3_bytes[1]);
367 assert_eq!(enc1_bytes[2], enc2_bytes[2]);
368 assert_eq!(enc1_bytes[2], enc3_bytes[2]);
369 }
370
371 #[test]
372 fn test_pfx_prefix_preserving_ipv4_16() {
373 let key_hex = "2b7e151628aed2a6abf7158809cf4f3ca9f5ba40db214c3798f2e1c23456789a";
374 let key_vec = Hex::decode_to_vec(key_hex.as_bytes(), None).unwrap();
375 let mut key = [0u8; IpcryptPfx::KEY_BYTES];
376 key.copy_from_slice(&key_vec);
377 let ipcrypt = IpcryptPfx::new(key);
378
379 let test_cases = vec![
381 ("172.16.5.193", "210.78.229.136"),
382 ("172.16.97.42", "210.78.179.241"),
383 ("172.16.248.177", "210.78.121.215"),
384 ];
385
386 for (input_ip, expected_output) in test_cases {
387 let ip = IpAddr::from_str(input_ip).unwrap();
388 let encrypted = ipcrypt.encrypt_ipaddr(ip);
389 assert_eq!(encrypted.to_string(), expected_output);
390
391 let decrypted = ipcrypt.decrypt_ipaddr(encrypted);
392 assert_eq!(decrypted, ip);
393 }
394 }
395
396 #[test]
397 fn test_pfx_prefix_preserving_ipv6_64() {
398 let key_hex = "2b7e151628aed2a6abf7158809cf4f3ca9f5ba40db214c3798f2e1c23456789a";
399 let key_vec = Hex::decode_to_vec(key_hex.as_bytes(), None).unwrap();
400 let mut key = [0u8; IpcryptPfx::KEY_BYTES];
401 key.copy_from_slice(&key_vec);
402 let ipcrypt = IpcryptPfx::new(key);
403
404 let test_cases = vec![
406 (
407 "2001:db8::a5c9:4e2f:bb91:5a7d",
408 "7cec:702c:1243:f70:1956:125:b9bd:1aba",
409 ),
410 (
411 "2001:db8::7234:d8f1:3c6e:9a52",
412 "7cec:702c:1243:f70:a3ef:c8e:95c1:cd0d",
413 ),
414 (
415 "2001:db8::f1e0:937b:26d4:8c1a",
416 "7cec:702c:1243:f70:443c:c8e:6a62:b64d",
417 ),
418 ];
419
420 for (input_ip, expected_output) in test_cases {
421 let ip = IpAddr::from_str(input_ip).unwrap();
422 let encrypted = ipcrypt.encrypt_ipaddr(ip);
423 assert_eq!(encrypted.to_string(), expected_output);
424
425 let decrypted = ipcrypt.decrypt_ipaddr(encrypted);
426 assert_eq!(decrypted, ip);
427 }
428 }
429
430 #[test]
431 fn test_pfx_prefix_preserving_ipv6_32() {
432 let key_hex = "2b7e151628aed2a6abf7158809cf4f3ca9f5ba40db214c3798f2e1c23456789a";
433 let key_vec = Hex::decode_to_vec(key_hex.as_bytes(), None).unwrap();
434 let mut key = [0u8; IpcryptPfx::KEY_BYTES];
435 key.copy_from_slice(&key_vec);
436 let ipcrypt = IpcryptPfx::new(key);
437
438 let test_cases = vec![
440 (
441 "2001:db8:3a5c::e7d1:4b9f:2c8a:f673",
442 "7cec:702c:3503:bef:e616:96bd:be33:a9b9",
443 ),
444 (
445 "2001:db8:9f27::b4e2:7a3d:5f91:c8e6",
446 "7cec:702c:a504:b74e:194a:3d90:b047:2d1a",
447 ),
448 (
449 "2001:db8:d8b4::193c:a5e7:8b2f:46d1",
450 "7cec:702c:f840:aa67:1b8:e84f:ac9d:77fb",
451 ),
452 ];
453
454 for (input_ip, expected_output) in test_cases {
455 let ip = IpAddr::from_str(input_ip).unwrap();
456 let encrypted = ipcrypt.encrypt_ipaddr(ip);
457 assert_eq!(encrypted.to_string(), expected_output);
458
459 let decrypted = ipcrypt.decrypt_ipaddr(encrypted);
460 assert_eq!(decrypted, ip);
461 }
462 }
463
464 #[test]
465 fn test_random_key() {
466 let ipcrypt = IpcryptPfx::new_random();
467 let ip = IpAddr::from_str("192.0.2.1").unwrap();
468 let encrypted = ipcrypt.encrypt_ipaddr(ip);
469 let decrypted = ipcrypt.decrypt_ipaddr(encrypted);
470 assert_eq!(ip, decrypted);
471 }
472
473 #[test]
474 #[should_panic(expected = "The two halves of the key must be different")]
475 fn test_identical_key_halves() {
476 let mut key = [0u8; 32];
477 key[0..16].copy_from_slice(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
479 key[16..32].copy_from_slice(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
480 IpcryptPfx::new(key);
481 }
482
483 #[test]
484 fn test_bit_operations() {
485 let mut data = [0u8; 16];
486
487 for pos in 0..128 {
489 IpcryptPfx::set_bit(&mut data, pos, 1);
490 assert_eq!(IpcryptPfx::get_bit(&data, pos), 1);
491 IpcryptPfx::set_bit(&mut data, pos, 0);
492 assert_eq!(IpcryptPfx::get_bit(&data, pos), 0);
493 }
494 }
495
496 #[test]
497 fn test_shift_left() {
498 let data = [
499 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
500 0x00, 0x01,
501 ];
502 let result = IpcryptPfx::shift_left_one_bit(&data);
503
504 assert_eq!(result[0], 0x00); assert_eq!(result[15], 0x02); }
508
509 #[test]
510 fn test_pad_prefix() {
511 let padded0 = IpcryptPfx::pad_prefix_0();
512 assert_eq!(padded0[15], 0x01);
513 assert_eq!(padded0[0..15], [0u8; 15]);
514
515 let padded96 = IpcryptPfx::pad_prefix_96();
516 assert_eq!(padded96[3], 0x01);
517 assert_eq!(padded96[14], 0xFF);
518 assert_eq!(padded96[15], 0xFF);
519 assert_eq!(padded96[0..3], [0u8; 3]);
520 assert_eq!(padded96[4..14], [0u8; 10]);
521 }
522}