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}