ipcrypt_rs/common.rs
1//! Common utilities and constants used across different encryption modes.
2//!
3//! This module provides shared functionality for IP address handling and AES operations.
4//! It includes the AES S-box, inverse S-box, round constants, and IP address conversion utilities.
5
6use std::net::IpAddr;
7
8/// Converts an IP address to its 16-byte representation.
9///
10/// For IPv4 addresses, this function creates an IPv4-mapped IPv6 address by:
11/// - Setting the first 10 bytes to 0x00
12/// - Setting bytes 10-11 to 0xFF
13/// - Copying the 4 IPv4 address bytes to positions 12-15
14///
15/// For IPv6 addresses, it simply returns the 16-byte representation directly.
16///
17/// # Arguments
18///
19/// * `ip` - The IP address to convert
20///
21/// # Returns
22///
23/// A 16-byte array containing the address representation
24pub fn ip_to_bytes(ip: IpAddr) -> [u8; 16] {
25 match ip {
26 IpAddr::V4(ipv4) => {
27 let mut bytes = [0u8; 16];
28 bytes[10..12].copy_from_slice(&[0xFF; 2]); // Set IPv4-mapped prefix more efficiently
29 bytes[12..16].copy_from_slice(&ipv4.octets());
30 bytes
31 }
32 IpAddr::V6(ipv6) => ipv6.octets(),
33 }
34}
35
36/// Converts a 16-byte representation back to an IP address.
37///
38/// This function detects whether the input represents an IPv4-mapped address or a native IPv6 address:
39/// - If bytes 0-9 are 0x00 and bytes 10-11 are 0xFF, it's treated as an IPv4 address
40/// - Otherwise, it's treated as an IPv6 address
41///
42/// # Arguments
43///
44/// * `bytes` - The 16-byte array to convert
45///
46/// # Returns
47///
48/// The corresponding IP address
49pub fn bytes_to_ip(bytes: [u8; 16]) -> IpAddr {
50 if bytes[..10].iter().all(|&b| b == 0) && bytes[10..12] == [0xFF; 2] {
51 let mut ipv4_bytes = [0u8; 4];
52 ipv4_bytes.copy_from_slice(&bytes[12..16]);
53 IpAddr::V4(ipv4_bytes.into())
54 } else {
55 IpAddr::V6(bytes.into())
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use std::net::{Ipv4Addr, Ipv6Addr};
63
64 #[test]
65 fn test_ipv4_conversion() {
66 let ipv4 = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
67 let bytes = ip_to_bytes(ipv4);
68 assert_eq!(bytes_to_ip(bytes), ipv4);
69 }
70
71 #[test]
72 fn test_ipv6_conversion() {
73 let ipv6 = IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
74 let bytes = ip_to_bytes(ipv6);
75 assert_eq!(bytes_to_ip(bytes), ipv6);
76 }
77}