ipcrypt_rs/
deterministic.rs1use aes::cipher::{BlockDecrypt, 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 Ipcrypt {
10 cipher: Aes128,
11}
12
13impl Ipcrypt {
14 pub const KEY_BYTES: usize = 16;
16
17 #[cfg(feature = "random")]
19 pub fn generate_key() -> [u8; Self::KEY_BYTES] {
20 rand::random()
21 }
22
23 pub fn new(key: [u8; Self::KEY_BYTES]) -> Self {
29 let cipher = Aes128::new_from_slice(&key).expect("key length is guaranteed to be correct");
30 Self { cipher }
31 }
32
33 #[cfg(feature = "random")]
35 pub fn new_random() -> Self {
36 Self::new(Self::generate_key())
37 }
38
39 pub fn encrypt_ip16(&self, ip: &mut [u8; 16]) {
41 let mut block = Block::from(*ip);
42 self.cipher.encrypt_block(&mut block);
43 *ip = block.into();
44 }
45
46 pub fn decrypt_ip16(&self, ip: &mut [u8; 16]) {
48 let mut block = Block::from(*ip);
49 self.cipher.decrypt_block(&mut block);
50 *ip = block.into();
51 }
52
53 pub fn encrypt_ipaddr(&self, ip: IpAddr) -> IpAddr {
62 let mut bytes = ip_to_bytes(ip);
63 self.encrypt_ip16(&mut bytes);
64 bytes_to_ip(bytes)
65 }
66
67 pub fn decrypt_ipaddr(&self, encrypted: IpAddr) -> IpAddr {
76 let mut bytes = ip_to_bytes(encrypted);
77 self.decrypt_ip16(&mut bytes);
78 bytes_to_ip(bytes)
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use ct_codecs::{Decoder as _, Hex};
86 use std::str::FromStr;
87
88 #[test]
89 fn test_deterministic_vectors() {
90 let test_vectors = vec![
91 (
92 "0123456789abcdeffedcba9876543210",
94 "0.0.0.0",
95 "bde9:6789:d353:824c:d7c6:f58a:6bd2:26eb",
96 ),
97 (
98 "1032547698badcfeefcdab8967452301",
100 "255.255.255.255",
101 "aed2:92f6:ea23:58c3:48fd:8b8:74e8:45d8",
102 ),
103 (
104 "2b7e151628aed2a6abf7158809cf4f3c",
106 "192.0.2.1",
107 "1dbd:c1b9:fff1:7586:7d0b:67b4:e76e:4777",
108 ),
109 ];
110
111 for (key_hex, input_ip, expected_output) in test_vectors {
112 let key_vec = Hex::decode_to_vec(key_hex.as_bytes(), None).unwrap();
114 let mut key = [0u8; Ipcrypt::KEY_BYTES];
115 key.copy_from_slice(&key_vec);
116
117 let ipcrypt = Ipcrypt::new(key);
119
120 let ip = IpAddr::from_str(input_ip).unwrap();
122
123 let encrypted = ipcrypt.encrypt_ipaddr(ip);
125 assert_eq!(encrypted.to_string(), expected_output);
126
127 let decrypted = ipcrypt.decrypt_ipaddr(encrypted);
129 assert_eq!(decrypted, ip);
130 }
131 }
132
133 #[test]
134 #[cfg(feature = "random")]
135 fn test_random_key() {
136 let ipcrypt = Ipcrypt::new_random();
137 let ip = IpAddr::from_str("192.0.2.1").unwrap();
138 let encrypted = ipcrypt.encrypt_ipaddr(ip);
139 let decrypted = ipcrypt.decrypt_ipaddr(encrypted);
140 assert_eq!(ip, decrypted);
141 }
142}