#![doc = include_str!("../README.md")]
use std::error::Error;
use std::ffi::{CStr, CString};
use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::os::raw::{c_char, c_int};
pub mod reexports {
pub use rand;
}
#[repr(C)]
pub struct IPCrypt {
opaque: [u8; 16 * 11],
}
#[repr(C)]
pub struct IPCryptNDX {
opaque: [u8; 16 * 11 * 2],
}
#[repr(C)]
pub struct IPCryptPFX {
opaque: [u8; 16 * 11 * 2],
}
extern "C" {
fn ipcrypt_str_to_ip16(ip16: *mut u8, ip_str: *const c_char) -> c_int;
fn ipcrypt_ip16_to_str(ip_str: *mut c_char, ip16: *const u8) -> usize;
fn ipcrypt_init(ipcrypt: *mut IPCrypt, key: *const u8);
fn ipcrypt_deinit(ipcrypt: *mut IPCrypt);
fn ipcrypt_encrypt_ip16(ipcrypt: *const IPCrypt, ip16: *mut u8);
fn ipcrypt_decrypt_ip16(ipcrypt: *const IPCrypt, ip16: *mut u8);
fn ipcrypt_encrypt_ip_str(
ipcrypt: *const IPCrypt,
encrypted_ip_str: *mut c_char,
ip_str: *const c_char,
) -> usize;
fn ipcrypt_decrypt_ip_str(
ipcrypt: *const IPCrypt,
ip_str: *mut c_char,
encrypted_ip_str: *const c_char,
) -> usize;
fn ipcrypt_nd_encrypt_ip16(
ipcrypt: *const IPCrypt,
ndip: *mut u8,
ip16: *const u8,
random: *const u8,
);
fn ipcrypt_nd_decrypt_ip16(ipcrypt: *const IPCrypt, ip16: *mut u8, ndip: *const u8);
fn ipcrypt_nd_encrypt_ip_str(
ipcrypt: *const IPCrypt,
encrypted_ip_str: *mut c_char,
ip_str: *const c_char,
random: *const u8,
) -> usize;
fn ipcrypt_nd_decrypt_ip_str(
ipcrypt: *const IPCrypt,
ip_str: *mut c_char,
encrypted_ip_str: *const c_char,
) -> usize;
fn ipcrypt_ndx_init(ipcrypt: *mut IPCryptNDX, key: *const u8);
fn ipcrypt_ndx_deinit(ipcrypt: *mut IPCryptNDX);
fn ipcrypt_ndx_encrypt_ip16(
ipcrypt: *const IPCryptNDX,
ndip: *mut u8,
ip16: *const u8,
random: *const u8,
);
fn ipcrypt_ndx_decrypt_ip16(ipcrypt: *const IPCryptNDX, ip16: *mut u8, ndip: *const u8);
fn ipcrypt_ndx_encrypt_ip_str(
ipcrypt: *const IPCryptNDX,
encrypted_ip_str: *mut c_char,
ip_str: *const c_char,
random: *const u8,
) -> usize;
fn ipcrypt_ndx_decrypt_ip_str(
ipcrypt: *const IPCryptNDX,
ip_str: *mut c_char,
encrypted_ip_str: *const c_char,
) -> usize;
fn ipcrypt_pfx_init(ipcrypt: *mut IPCryptPFX, key: *const u8);
fn ipcrypt_pfx_deinit(ipcrypt: *mut IPCryptPFX);
fn ipcrypt_pfx_encrypt_ip16(ipcrypt: *const IPCryptPFX, ip16: *mut u8);
fn ipcrypt_pfx_decrypt_ip16(ipcrypt: *const IPCryptPFX, ip16: *mut u8);
fn ipcrypt_pfx_encrypt_ip_str(
ipcrypt: *const IPCryptPFX,
encrypted_ip_str: *mut c_char,
ip_str: *const c_char,
) -> usize;
fn ipcrypt_pfx_decrypt_ip_str(
ipcrypt: *const IPCryptPFX,
ip_str: *mut c_char,
encrypted_ip_str: *const c_char,
) -> usize;
}
#[derive(Debug)]
pub enum IpcryptError {
NullByteInInput,
Utf8Error(std::str::Utf8Error),
OperationFailed,
}
impl fmt::Display for IpcryptError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
IpcryptError::NullByteInInput => write!(f, "input contains a null byte"),
IpcryptError::Utf8Error(e) => write!(f, "UTF-8 conversion error: {}", e),
IpcryptError::OperationFailed => write!(f, "operation failed"),
}
}
}
impl Error for IpcryptError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
IpcryptError::Utf8Error(e) => Some(e),
_ => None,
}
}
}
impl From<std::str::Utf8Error> for IpcryptError {
fn from(err: std::str::Utf8Error) -> Self {
IpcryptError::Utf8Error(err)
}
}
pub struct Ipcrypt {
inner: IPCrypt,
}
impl Ipcrypt {
pub const KEY_BYTES: usize = 16;
pub const TWEAK_BYTES: usize = 8;
pub const NDIP_BYTES: usize = 24;
pub const NDIP_STR_BYTES: usize = 48 + 1;
pub fn generate_key() -> [u8; Self::KEY_BYTES] {
rand::random()
}
pub fn new(key: [u8; Self::KEY_BYTES]) -> Self {
let mut inner = std::mem::MaybeUninit::<IPCrypt>::uninit();
unsafe {
ipcrypt_init(inner.as_mut_ptr(), key.as_ptr());
Self {
inner: inner.assume_init(),
}
}
}
pub fn encrypt_ip16(&self, ip: &mut [u8; 16]) {
unsafe {
ipcrypt_encrypt_ip16(&self.inner, ip.as_mut_ptr());
}
}
pub fn decrypt_ip16(&self, ip: &mut [u8; 16]) {
unsafe {
ipcrypt_decrypt_ip16(&self.inner, ip.as_mut_ptr());
}
}
pub fn encrypt_ip_str(&self, ip: &str) -> Result<String, IpcryptError> {
let c_ip = CString::new(ip).map_err(|_| IpcryptError::NullByteInInput)?;
let mut buffer = [0u8; MAX_IP_STR_BYTES];
let ret = unsafe {
ipcrypt_encrypt_ip_str(
&self.inner,
buffer.as_mut_ptr() as *mut c_char,
c_ip.as_ptr(),
)
};
if ret == 0 {
return Err(IpcryptError::OperationFailed);
}
unsafe {
CStr::from_ptr(buffer.as_ptr() as *const c_char)
.to_str()
.map(|s| s.to_owned())
.map_err(Into::into)
}
}
pub fn decrypt_ip_str(&self, encrypted: &str) -> Result<String, IpcryptError> {
let c_encrypted = CString::new(encrypted).map_err(|_| IpcryptError::NullByteInInput)?;
let mut buffer = [0u8; MAX_IP_STR_BYTES];
let ret = unsafe {
ipcrypt_decrypt_ip_str(
&self.inner,
buffer.as_mut_ptr() as *mut c_char,
c_encrypted.as_ptr(),
)
};
if ret == 0 {
return Err(IpcryptError::OperationFailed);
}
unsafe {
CStr::from_ptr(buffer.as_ptr() as *const c_char)
.to_str()
.map(|s| s.to_owned())
.map_err(Into::into)
}
}
pub fn nd_encrypt_ip16(&self, ip: &[u8; 16]) -> [u8; Self::NDIP_BYTES] {
let random: [u8; Self::TWEAK_BYTES] = rand::random();
let mut ndip = [0u8; Self::NDIP_BYTES];
unsafe {
ipcrypt_nd_encrypt_ip16(&self.inner, ndip.as_mut_ptr(), ip.as_ptr(), random.as_ptr());
}
ndip
}
pub fn nd_decrypt_ip16(&self, ndip: &[u8; Self::NDIP_BYTES]) -> [u8; 16] {
let mut ip = [0u8; 16];
unsafe {
ipcrypt_nd_decrypt_ip16(&self.inner, ip.as_mut_ptr(), ndip.as_ptr());
}
ip
}
pub fn nd_encrypt_ip_str(&self, ip: &str) -> Result<String, IpcryptError> {
let c_ip = CString::new(ip).map_err(|_| IpcryptError::NullByteInInput)?;
let random: [u8; Self::TWEAK_BYTES] = rand::random();
let mut buffer = [0u8; Self::NDIP_STR_BYTES];
let ret = unsafe {
ipcrypt_nd_encrypt_ip_str(
&self.inner,
buffer.as_mut_ptr() as *mut c_char,
c_ip.as_ptr(),
random.as_ptr(),
)
};
if ret == 0 {
return Err(IpcryptError::OperationFailed);
}
unsafe {
CStr::from_ptr(buffer.as_ptr() as *const c_char)
.to_str()
.map(|s| s.to_owned())
.map_err(Into::into)
}
}
pub fn nd_decrypt_ip_str(&self, encrypted: &str) -> Result<String, IpcryptError> {
let c_encrypted = CString::new(encrypted).map_err(|_| IpcryptError::NullByteInInput)?;
let mut buffer = [0u8; MAX_IP_STR_BYTES];
let ret = unsafe {
ipcrypt_nd_decrypt_ip_str(
&self.inner,
buffer.as_mut_ptr() as *mut c_char,
c_encrypted.as_ptr(),
)
};
if ret == 0 {
return Err(IpcryptError::OperationFailed);
}
unsafe {
CStr::from_ptr(buffer.as_ptr() as *const c_char)
.to_str()
.map(|s| s.to_owned())
.map_err(Into::into)
}
}
pub fn str_to_ip16(ip: &str) -> Result<[u8; 16], IpcryptError> {
let c_ip = CString::new(ip).map_err(|_| IpcryptError::NullByteInInput)?;
let mut ip16 = [0u8; 16];
let ret = unsafe { ipcrypt_str_to_ip16(ip16.as_mut_ptr(), c_ip.as_ptr()) };
if ret != 0 {
Err(IpcryptError::OperationFailed)
} else {
Ok(ip16)
}
}
pub fn ip16_to_str(ip16: &[u8; 16]) -> Result<String, IpcryptError> {
let mut buffer = [0u8; MAX_IP_STR_BYTES];
let ret = unsafe { ipcrypt_ip16_to_str(buffer.as_mut_ptr() as *mut c_char, ip16.as_ptr()) };
if ret == 0 {
return Err(IpcryptError::OperationFailed);
}
unsafe {
CStr::from_ptr(buffer.as_ptr() as *const c_char)
.to_str()
.map(|s| s.to_owned())
.map_err(Into::into)
}
}
pub fn encrypt_ipaddr(&self, ip: IpAddr) -> Result<IpAddr, IpcryptError> {
let mut ip16 = ipaddr_to_ip16(ip);
self.encrypt_ip16(&mut ip16);
ip16_to_ipaddr(ip16)
}
pub fn decrypt_ipaddr(&self, encrypted: IpAddr) -> Result<IpAddr, IpcryptError> {
let mut ip16 = ipaddr_to_ip16(encrypted);
self.decrypt_ip16(&mut ip16);
ip16_to_ipaddr(ip16)
}
pub fn nd_encrypt_ipaddr(&self, ip: IpAddr) -> Result<[u8; Self::NDIP_BYTES], IpcryptError> {
let ip16 = ipaddr_to_ip16(ip);
Ok(self.nd_encrypt_ip16(&ip16))
}
pub fn nd_decrypt_ipaddr(
&self,
encrypted: [u8; Self::NDIP_BYTES],
) -> Result<IpAddr, IpcryptError> {
let decrypted = self.nd_decrypt_ip16(&encrypted);
ip16_to_ipaddr(decrypted)
}
pub fn nd_encrypt_ipaddr_str(&self, ip: IpAddr) -> Result<String, IpcryptError> {
let ip_str = match ip {
IpAddr::V4(v4) => v4.to_string(),
IpAddr::V6(v6) => v6.to_string(),
};
self.nd_encrypt_ip_str(&ip_str)
}
pub fn nd_decrypt_ipaddr_str(&self, encrypted: &str) -> Result<IpAddr, IpcryptError> {
let decrypted_str = self.nd_decrypt_ip_str(encrypted)?;
let ip = Ipcrypt::str_to_ip16(&decrypted_str)?;
ip16_to_ipaddr(ip)
}
pub fn new_random() -> Self {
Self::new(Self::generate_key())
}
pub fn encrypt(&self, ip: &str) -> Result<String, IpcryptError> {
self.encrypt_ip_str(ip)
}
pub fn decrypt(&self, encrypted: &str) -> Result<String, IpcryptError> {
self.decrypt_ip_str(encrypted)
}
pub fn encrypt_nd(&self, ip: &str) -> Result<String, IpcryptError> {
self.nd_encrypt_ip_str(ip)
}
pub fn decrypt_nd(&self, encrypted: &str) -> Result<String, IpcryptError> {
self.nd_decrypt_ip_str(encrypted)
}
pub fn to_bytes(ip: &str) -> Result<[u8; 16], IpcryptError> {
Self::str_to_ip16(ip)
}
pub fn from_bytes(ip16: &[u8; 16]) -> Result<String, IpcryptError> {
Self::ip16_to_str(ip16)
}
}
impl Drop for Ipcrypt {
fn drop(&mut self) {
unsafe {
ipcrypt_deinit(&mut self.inner);
}
}
}
pub struct IpcryptNdx {
inner: IPCryptNDX,
}
impl IpcryptNdx {
pub const KEY_BYTES: usize = 32;
pub const TWEAK_BYTES: usize = 16;
pub const NDIP_BYTES: usize = 32;
pub const NDIP_STR_BYTES: usize = 64 + 1;
pub fn generate_key() -> [u8; Self::KEY_BYTES] {
rand::random()
}
pub fn new(key: [u8; Self::KEY_BYTES]) -> Self {
let mut inner = std::mem::MaybeUninit::<IPCryptNDX>::uninit();
unsafe {
ipcrypt_ndx_init(inner.as_mut_ptr(), key.as_ptr());
Self {
inner: inner.assume_init(),
}
}
}
pub fn nd_encrypt_ip16(&self, ip: &[u8; 16]) -> [u8; Self::NDIP_BYTES] {
let random: [u8; Self::TWEAK_BYTES] = rand::random();
let mut ndip = [0u8; Self::NDIP_BYTES];
unsafe {
ipcrypt_ndx_encrypt_ip16(&self.inner, ndip.as_mut_ptr(), ip.as_ptr(), random.as_ptr());
}
ndip
}
pub fn nd_decrypt_ip16(&self, ndip: &[u8; Self::NDIP_BYTES]) -> [u8; 16] {
let mut ip = [0u8; 16];
unsafe {
ipcrypt_ndx_decrypt_ip16(&self.inner, ip.as_mut_ptr(), ndip.as_ptr());
}
ip
}
pub fn nd_encrypt_ip_str(&self, ip: &str) -> Result<String, IpcryptError> {
let c_ip = CString::new(ip).map_err(|_| IpcryptError::NullByteInInput)?;
let random: [u8; Self::TWEAK_BYTES] = rand::random();
let mut buffer = [0u8; Self::NDIP_STR_BYTES];
let ret = unsafe {
ipcrypt_ndx_encrypt_ip_str(
&self.inner,
buffer.as_mut_ptr() as *mut c_char,
c_ip.as_ptr(),
random.as_ptr(),
)
};
if ret == 0 {
return Err(IpcryptError::OperationFailed);
}
unsafe {
CStr::from_ptr(buffer.as_ptr() as *const c_char)
.to_str()
.map(|s| s.to_owned())
.map_err(Into::into)
}
}
pub fn nd_decrypt_ip_str(&self, encrypted: &str) -> Result<String, IpcryptError> {
let c_encrypted = CString::new(encrypted).map_err(|_| IpcryptError::NullByteInInput)?;
let mut buffer = [0u8; MAX_IP_STR_BYTES];
let ret = unsafe {
ipcrypt_ndx_decrypt_ip_str(
&self.inner,
buffer.as_mut_ptr() as *mut c_char,
c_encrypted.as_ptr(),
)
};
if ret == 0 {
return Err(IpcryptError::OperationFailed);
}
unsafe {
CStr::from_ptr(buffer.as_ptr() as *const c_char)
.to_str()
.map(|s| s.to_owned())
.map_err(Into::into)
}
}
pub fn nd_encrypt_ipaddr(&self, ip: IpAddr) -> Result<[u8; Self::NDIP_BYTES], IpcryptError> {
let ip_str = ipaddr_to_ip16(ip);
let encrypted = self.nd_encrypt_ip16(&ip_str);
Ok(encrypted)
}
pub fn nd_decrypt_ipaddr(
&self,
encrypted: [u8; Self::NDIP_BYTES],
) -> Result<IpAddr, IpcryptError> {
let decrypted = self.nd_decrypt_ip16(&encrypted);
let decrypted_ip = ip16_to_ipaddr(decrypted)?;
Ok(decrypted_ip)
}
pub fn nd_encrypt_ipaddr_str(&self, ip: IpAddr) -> Result<String, IpcryptError> {
let ip_str = match ip {
IpAddr::V4(v4) => v4.to_string(),
IpAddr::V6(v6) => v6.to_string(),
};
self.nd_encrypt_ip_str(&ip_str)
}
pub fn nd_decrypt_ipaddr_str(&self, encrypted: &str) -> Result<IpAddr, IpcryptError> {
let decrypted_str = self.nd_decrypt_ip_str(encrypted)?;
let ip = Ipcrypt::str_to_ip16(&decrypted_str)?;
ip16_to_ipaddr(ip)
}
pub fn new_random() -> Self {
Self::new(Self::generate_key())
}
pub fn encrypt(&self, ip: &str) -> Result<String, IpcryptError> {
self.nd_encrypt_ip_str(ip)
}
pub fn decrypt(&self, encrypted: &str) -> Result<String, IpcryptError> {
self.nd_decrypt_ip_str(encrypted)
}
pub fn to_bytes(ip: &str) -> Result<[u8; 16], IpcryptError> {
Ipcrypt::str_to_ip16(ip)
}
pub fn from_bytes(ip16: &[u8; 16]) -> Result<String, IpcryptError> {
Ipcrypt::ip16_to_str(ip16)
}
}
impl Drop for IpcryptNdx {
fn drop(&mut self) {
unsafe {
ipcrypt_ndx_deinit(&mut self.inner);
}
}
}
pub struct IpcryptPfx {
inner: IPCryptPFX,
}
impl IpcryptPfx {
pub const KEY_BYTES: usize = 32;
pub fn generate_key() -> [u8; Self::KEY_BYTES] {
rand::random()
}
pub fn new(key: [u8; Self::KEY_BYTES]) -> Self {
let mut inner = std::mem::MaybeUninit::<IPCryptPFX>::uninit();
unsafe {
ipcrypt_pfx_init(inner.as_mut_ptr(), key.as_ptr());
Self {
inner: inner.assume_init(),
}
}
}
pub fn encrypt_ip16(&self, ip: &mut [u8; 16]) {
unsafe {
ipcrypt_pfx_encrypt_ip16(&self.inner, ip.as_mut_ptr());
}
}
pub fn decrypt_ip16(&self, ip: &mut [u8; 16]) {
unsafe {
ipcrypt_pfx_decrypt_ip16(&self.inner, ip.as_mut_ptr());
}
}
pub fn encrypt_ip_str(&self, ip: &str) -> Result<String, IpcryptError> {
let c_ip = CString::new(ip).map_err(|_| IpcryptError::NullByteInInput)?;
let mut buffer = [0u8; MAX_IP_STR_BYTES];
let ret = unsafe {
ipcrypt_pfx_encrypt_ip_str(
&self.inner,
buffer.as_mut_ptr() as *mut c_char,
c_ip.as_ptr(),
)
};
if ret == 0 {
return Err(IpcryptError::OperationFailed);
}
unsafe {
CStr::from_ptr(buffer.as_ptr() as *const c_char)
.to_str()
.map(|s| s.to_owned())
.map_err(Into::into)
}
}
pub fn decrypt_ip_str(&self, encrypted: &str) -> Result<String, IpcryptError> {
let c_encrypted = CString::new(encrypted).map_err(|_| IpcryptError::NullByteInInput)?;
let mut buffer = [0u8; MAX_IP_STR_BYTES];
let ret = unsafe {
ipcrypt_pfx_decrypt_ip_str(
&self.inner,
buffer.as_mut_ptr() as *mut c_char,
c_encrypted.as_ptr(),
)
};
if ret == 0 {
return Err(IpcryptError::OperationFailed);
}
unsafe {
CStr::from_ptr(buffer.as_ptr() as *const c_char)
.to_str()
.map(|s| s.to_owned())
.map_err(Into::into)
}
}
pub fn encrypt_ipaddr(&self, ip: IpAddr) -> Result<IpAddr, IpcryptError> {
let mut ip16 = ipaddr_to_ip16(ip);
self.encrypt_ip16(&mut ip16);
ip16_to_ipaddr(ip16)
}
pub fn decrypt_ipaddr(&self, encrypted: IpAddr) -> Result<IpAddr, IpcryptError> {
let mut ip16 = ipaddr_to_ip16(encrypted);
self.decrypt_ip16(&mut ip16);
ip16_to_ipaddr(ip16)
}
pub fn new_random() -> Self {
Self::new(Self::generate_key())
}
pub fn encrypt(&self, ip: &str) -> Result<String, IpcryptError> {
self.encrypt_ip_str(ip)
}
pub fn decrypt(&self, encrypted: &str) -> Result<String, IpcryptError> {
self.decrypt_ip_str(encrypted)
}
pub fn to_bytes(ip: &str) -> Result<[u8; 16], IpcryptError> {
Ipcrypt::str_to_ip16(ip)
}
pub fn from_bytes(ip16: &[u8; 16]) -> Result<String, IpcryptError> {
Ipcrypt::ip16_to_str(ip16)
}
}
impl Drop for IpcryptPfx {
fn drop(&mut self) {
unsafe {
ipcrypt_pfx_deinit(&mut self.inner);
}
}
}
pub fn str_to_ip16(ip: &str) -> Result<[u8; 16], IpcryptError> {
let c_ip = CString::new(ip).map_err(|_| IpcryptError::NullByteInInput)?;
let mut ip16 = [0u8; 16];
let ret = unsafe { ipcrypt_str_to_ip16(ip16.as_mut_ptr(), c_ip.as_ptr()) };
if ret != 0 {
Err(IpcryptError::OperationFailed)
} else {
Ok(ip16)
}
}
pub const MAX_IP_STR_BYTES: usize = 46;
pub fn ip16_to_str(ip16: &[u8; 16]) -> Result<String, IpcryptError> {
let mut buffer = [0u8; MAX_IP_STR_BYTES];
let ret = unsafe { ipcrypt_ip16_to_str(buffer.as_mut_ptr() as *mut c_char, ip16.as_ptr()) };
if ret == 0 {
return Err(IpcryptError::OperationFailed);
}
unsafe {
CStr::from_ptr(buffer.as_ptr() as *const c_char)
.to_str()
.map(|s| s.to_owned())
.map_err(Into::into)
}
}
pub fn ipaddr_to_ip16(ip: IpAddr) -> [u8; 16] {
match ip {
IpAddr::V4(v4) => v4.to_ipv6_mapped().octets(),
IpAddr::V6(v6) => v6.octets(),
}
}
pub fn ip16_to_ipaddr(ip16: [u8; 16]) -> Result<IpAddr, IpcryptError> {
if ip16[0..10] == [0u8; 10] && ip16[10] == 0xff && ip16[11] == 0xff {
let octets = [ip16[12], ip16[13], ip16[14], ip16[15]];
Ok(IpAddr::V4(Ipv4Addr::from(octets)))
} else {
Ok(IpAddr::V6(Ipv6Addr::from(ip16)))
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
#[test]
fn test_ip16_encrypt_decrypt() {
let key = [0u8; Ipcrypt::KEY_BYTES];
let ipcrypt = Ipcrypt::new(key);
let mut ip = [192, 168, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let original = ip;
ipcrypt.encrypt_ip16(&mut ip);
assert_ne!(ip, original);
ipcrypt.decrypt_ip16(&mut ip);
assert_eq!(ip, original);
}
#[test]
fn test_ip_str_encrypt_decrypt() {
let key = [0u8; Ipcrypt::KEY_BYTES];
let ipcrypt = Ipcrypt::new(key);
let ip = "192.168.1.1";
let encrypted = ipcrypt.encrypt_ip_str(ip).expect("Encryption failed");
let decrypted = ipcrypt
.decrypt_ip_str(&encrypted)
.expect("Decryption failed");
assert_eq!(ip, decrypted);
}
#[test]
fn test_nd_ip16_encrypt_decrypt() {
let key = [0u8; Ipcrypt::KEY_BYTES];
let ipcrypt = Ipcrypt::new(key);
let ip: [u8; 16] = [10, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let nd_encrypted = ipcrypt.nd_encrypt_ip16(&ip);
let decrypted = ipcrypt.nd_decrypt_ip16(&nd_encrypted);
assert_eq!(ip, decrypted);
}
#[test]
fn test_nd_ip_str_encrypt_decrypt() {
let key = [0u8; Ipcrypt::KEY_BYTES];
let ipcrypt = Ipcrypt::new(key);
let ip = "10.0.0.1";
let nd_encrypted = ipcrypt.nd_encrypt_ip_str(ip).expect("ND Encryption failed");
let nd_decrypted = ipcrypt
.nd_decrypt_ip_str(&nd_encrypted)
.expect("ND Decryption failed");
assert_eq!(ip, nd_decrypted);
}
#[test]
fn test_str_to_ip16_and_back() {
let ip_str = "192.168.1.1";
let ip16 = Ipcrypt::str_to_ip16(ip_str).expect("Conversion to ip16 failed");
let ip_str_converted = Ipcrypt::ip16_to_str(&ip16).expect("Conversion to string failed");
assert_eq!(ip_str, ip_str_converted);
}
#[test]
fn test_encrypt_decrypt_ipaddr() {
let key = [0u8; Ipcrypt::KEY_BYTES];
let ipcrypt = Ipcrypt::new(key);
let ip_v4 = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
let encrypted_v4 = ipcrypt.encrypt_ipaddr(ip_v4).expect("Encryption failed");
let decrypted_v4 = ipcrypt
.decrypt_ipaddr(encrypted_v4)
.expect("Decryption failed");
assert_eq!(ip_v4, decrypted_v4);
let ip_v6 = IpAddr::V6(Ipv6Addr::LOCALHOST);
let encrypted_v6 = ipcrypt.encrypt_ipaddr(ip_v6).expect("Encryption failed");
let decrypted_v6 = ipcrypt
.decrypt_ipaddr(encrypted_v6)
.expect("Decryption failed");
assert_eq!(ip_v6, decrypted_v6);
}
#[test]
fn test_nd_encrypt_decrypt_ipaddr() {
let key = [0u8; Ipcrypt::KEY_BYTES];
let ipcrypt = Ipcrypt::new(key);
let ip_v4 = IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1));
let encrypted_v4 = ipcrypt
.nd_encrypt_ipaddr(ip_v4)
.expect("ND Encryption failed");
let decrypted_v4 = ipcrypt
.nd_decrypt_ipaddr(encrypted_v4)
.expect("ND Decryption failed");
assert_eq!(ip_v4, decrypted_v4);
let ip_v6 = IpAddr::V6(Ipv6Addr::LOCALHOST);
let encrypted_v6 = ipcrypt
.nd_encrypt_ipaddr(ip_v6)
.expect("ND Encryption failed");
let decrypted_v6 = ipcrypt
.nd_decrypt_ipaddr(encrypted_v6)
.expect("ND Decryption failed");
assert_eq!(ip_v6, decrypted_v6);
}
#[test]
fn test_nd_ipaddr_str_encrypt_decrypt() {
let key = [0u8; Ipcrypt::KEY_BYTES];
let ipcrypt = Ipcrypt::new(key);
let ip = IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1));
let nd_encrypted = ipcrypt
.nd_encrypt_ipaddr_str(ip)
.expect("ND Encryption failed");
let nd_decrypted = ipcrypt
.nd_decrypt_ipaddr_str(&nd_encrypted)
.expect("ND Decryption failed");
assert_eq!(ip, nd_decrypted);
}
#[test]
fn test_nxd_encrypt_decrypt_ipaddr() {
let key = [0u8; IpcryptNdx::KEY_BYTES];
let ipcrypt = IpcryptNdx::new(key);
let ip_v4 = IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1));
let encrypted_v4 = ipcrypt
.nd_encrypt_ipaddr(ip_v4)
.expect("NDX Encryption failed");
let decrypted_v4 = ipcrypt
.nd_decrypt_ipaddr(encrypted_v4)
.expect("NDX Decryption failed");
assert_eq!(ip_v4, decrypted_v4);
let ip_v6 = IpAddr::V6(Ipv6Addr::LOCALHOST);
let encrypted_v6 = ipcrypt
.nd_encrypt_ipaddr(ip_v6)
.expect("NDX Encryption failed");
let decrypted_v6 = ipcrypt
.nd_decrypt_ipaddr(encrypted_v6)
.expect("NDX Decryption failed");
assert_eq!(ip_v6, decrypted_v6);
}
#[test]
fn test_ndx_ipaddr_str_encrypt_decrypt() {
let key = [0u8; IpcryptNdx::KEY_BYTES];
let ipcrypt = IpcryptNdx::new(key);
let ip = IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1));
let nd_encrypted = ipcrypt
.nd_encrypt_ipaddr_str(ip)
.expect("NDX Encryption failed");
let nd_decrypted = ipcrypt
.nd_decrypt_ipaddr_str(&nd_encrypted)
.expect("NDX Decryption failed");
assert_eq!(ip, nd_decrypted);
}
#[test]
fn test_pfx_ip16_encrypt_decrypt() {
let key = IpcryptPfx::generate_key();
let ipcrypt = IpcryptPfx::new(key);
let mut ip = [192, 168, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let original = ip;
ipcrypt.encrypt_ip16(&mut ip);
assert_ne!(ip, original);
ipcrypt.decrypt_ip16(&mut ip);
assert_eq!(ip, original);
}
#[test]
fn test_pfx_ip_str_encrypt_decrypt() {
let key = IpcryptPfx::generate_key();
let ipcrypt = IpcryptPfx::new(key);
let ip = "192.168.1.1";
let encrypted = ipcrypt.encrypt_ip_str(ip).expect("PFX Encryption failed");
let decrypted = ipcrypt
.decrypt_ip_str(&encrypted)
.expect("PFX Decryption failed");
assert_eq!(ip, decrypted);
}
#[test]
fn test_pfx_encrypt_decrypt_ipaddr() {
let key = IpcryptPfx::generate_key();
let ipcrypt = IpcryptPfx::new(key);
let ip_v4 = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
let encrypted_v4 = ipcrypt
.encrypt_ipaddr(ip_v4)
.expect("PFX Encryption failed");
let decrypted_v4 = ipcrypt
.decrypt_ipaddr(encrypted_v4)
.expect("PFX Decryption failed");
assert_eq!(ip_v4, decrypted_v4);
let ip_v6 = IpAddr::V6(Ipv6Addr::LOCALHOST);
let encrypted_v6 = ipcrypt
.encrypt_ipaddr(ip_v6)
.expect("PFX Encryption failed");
let decrypted_v6 = ipcrypt
.decrypt_ipaddr(encrypted_v6)
.expect("PFX Decryption failed");
assert_eq!(ip_v6, decrypted_v6);
}
#[test]
fn test_pfx_convenience_methods() {
let ipcrypt = IpcryptPfx::new_random();
let ip = "10.0.0.1";
let encrypted = ipcrypt.encrypt(ip).expect("Encryption failed");
let decrypted = ipcrypt.decrypt(&encrypted).expect("Decryption failed");
assert_eq!(ip, decrypted);
let ip16 = IpcryptPfx::to_bytes(ip).expect("to_bytes failed");
let ip_str = IpcryptPfx::from_bytes(&ip16).expect("from_bytes failed");
assert_eq!(ip, ip_str);
}
#[test]
fn test_pfx_prefix_preservation() {
let key = IpcryptPfx::generate_key();
let ipcrypt = IpcryptPfx::new(key);
let ip1 = "192.168.1.1";
let ip2 = "192.168.1.2";
let encrypted1 = ipcrypt.encrypt_ip_str(ip1).unwrap();
let encrypted2 = ipcrypt.encrypt_ip_str(ip2).unwrap();
assert_eq!(&encrypted1[..7], &encrypted2[..7]); }
}