IPCrypt Encryption Modes

IPCrypt provides four distinct encryption modes, each designed for specific use cases and security requirements. This page explains each mode in detail, including their operation, properties, and appropriate use cases.

Format Preservation: Deterministic mode preserves IP address format
Correlation Protection: Non-deterministic modes prevent correlation attacks
IPv4 and IPv6 Support: All modes handle both address types uniformly

Overview of Encryption Modes

IPCrypt offers the following encryption modes:

D

ipcrypt-deterministic

Format-preserving encryption using AES-128

The deterministic mode always produces the same output for the same input and key, preserving the IP address format.

Format preservation
Consistent output
Searchable
ND

ipcrypt-nd

Non-deterministic encryption using KIASU-BC with an 8-byte tweak

The non-deterministic mode produces different outputs for the same input and key, preventing correlation attacks.

Correlation protection
8-byte tweak
24-byte output
NDX

ipcrypt-ndx

Non-deterministic encryption using AES-XTS with a 16-byte tweak

The extended non-deterministic mode provides maximum security with a larger tweak and output size.

Maximum security
16-byte tweak
32-byte output
PFX

ipcrypt-pfx

Prefix-preserving encryption that maintains network structure

The prefix-preserving mode maintains network relationships in encrypted addresses, enabling network-level analytics while protecting actual network identities.

Prefix preservation
Network analytics
Native address sizes
Feature Deterministic Prefix-Preserving (PFX) Non-Deterministic (ND) Extended ND (NDX)
Format Preservation
Correlation Protection
Output Size 16 bytes 4/16 bytes 24 bytes 32 bytes
Algorithm AES-128 Dual AES-128 KIASU-BC AES-XTS
Tweak Size N/A N/A 8 bytes 16 bytes

ipcrypt-deterministic Mode

D

How It Works

Format-preserving encryption using AES-128

The deterministic mode uses AES-128 as a single-block operation to encrypt IP addresses while preserving their format.

    +----------------+     +----------------+     +----------------+
    |                |     |                |     |                |
    |   IP Address   |---->|   Convert to   |---->|    AES-128     |
    | (192.168.1.1)  |     |  16-byte form  |     |   Encryption   |
    |                |     |                |     |                |
    +----------------+     +----------------+     +----------------+
                                                   |
                           +----------------+      |
                           |                |      |
                           |   16-byte Key  |------+
                           |                |
                           +----------------+
                                                   |
                                                   v
                           +----------------+     +----------------+
                           |                |     |                |
                           |   Encrypted    |<----|  Convert back  |
                           |  IP Address    |     |  to IP format  |
                           |                |     |                |
                           +----------------+     +----------------+
        

Process Flow

1
Input Preparation: The IP address (IPv4 or IPv6) is converted to a standard 16-byte representation
2
Encryption: The 16-byte representation is encrypted using AES-128 with the provided key
3
Output Formatting: The encrypted result is converted back to an IP address format

Key Properties

Format Preservation: The output maintains the IP address format
Deterministic: The same input always produces the same output with a given key
Invertible: The original IP address can be recovered with the key
Uniform: Both IPv4 and IPv6 addresses are handled consistently

Use Cases

📊
Logging: When you need to correlate log entries by IP address
🛡️
Rate Limiting: When you need to count or limit requests by IP
🔍
Database Indexing: When you need to query or join on encrypted IP addresses

Code Example

```python from ipcrypt import IPCrypt # Initialize with a 16-byte key key = bytes.fromhex("000102030405060708090a0b0c0d0e0f") ipcrypt = IPCrypt(key) # Encrypt an IPv4 address ip = "192.168.1.1" encrypted_ip = ipcrypt.encrypt_deterministic(ip) print(f"Original IP: {ip}") print(f"Encrypted IP: {encrypted_ip}") # Decrypt the IP address decrypted_ip = ipcrypt.decrypt_deterministic(encrypted_ip) print(f"Decrypted IP: {decrypted_ip}") ```

ipcrypt-pfx Mode

PFX

How It Works

Prefix-preserving encryption using dual AES-128

The prefix-preserving mode encrypts IP addresses while maintaining network structure. Addresses from the same network produce encrypted addresses that share a common encrypted prefix, enabling network analytics while protecting actual network identities.

    +----------------+     +----------------+     +----------------+
    |                |     |                |     |                |
    |   IP Address   |---->| Process each   |---->| For each bit:  |
    | (192.168.1.1)  |     |  bit position  |     | Compute PRF    |
    |                |     | sequentially   |     | XOR with input |
    +----------------+     +----------------+     +----------------+
                                                   |
                           +----------------+      |
                           |                |      |
                           |  32-byte Key   |------+
                           |                |
                           +----------------+
                                                   |
                                                   v
                           +----------------+     +----------------+
                           |                |     |                |
                           | Encrypted IP   |<----|  Maintains     |
                           | (Same subnet   |     |  native size   |
                           | = same prefix) |     | (4 or 16 bytes)|
                           +----------------+     +----------------+
        

Process Flow

1
Key Setup: The 32-byte key is used to initialize the encryption algorithm
2
Bit-by-bit Processing: Each bit of the IP address is processed sequentially from MSB to LSB
3
PRF Computation: For each bit, a pseudorandom function is computed based on the prefix processed so far
4
Bit Encryption: XOR the PRF's least significant bit with the current input bit
5
Native Size Preservation: IPv4 addresses remain 4 bytes, IPv6 addresses remain 16 bytes

Key Properties

Prefix Preservation: Addresses from the same network share encrypted prefixes
Network Analytics: Enables traffic pattern analysis without revealing actual networks
Deterministic: Same IP always produces same encrypted output with given key
Format Preservation: Maintains native IP address sizes and formats
Security Beyond Birthday Bound: XOR of two AES permutations provides robust security

Use Cases

🌐
Network Monitoring: Detect traffic patterns from common networks without identifying them
🛡️
DDoS Mitigation: Implement network-level rate limiting on encrypted addresses
📊
Network Analytics: Analyze network topology without accessing raw IP addresses
🔒
Privacy-Preserving Monitoring: Monitor subnet traffic while protecting individual addresses

Important Considerations

🔑
Key Requirement: Uses a 32-byte key for enhanced security
🔍
Network Visibility: This mode intentionally reveals network structure for analytics purposes
Performance: Requires 64 AES operations for IPv4 and 256 for IPv6 addresses
💾
Caching Optimization: Caching prefix computations improves performance for addresses in same subnet

Code Example

```python from ipcrypt import IPCrypt import os # Initialize with a 32-byte random key key = os.urandom(32) # Generate a secure random 32-byte key ipcrypt = IPCrypt(key) # Encrypt IPv4 addresses from same subnet ip1 = "10.0.0.47" ip2 = "10.0.0.129" encrypted_ip1 = ipcrypt.encrypt_pfx(ip1) encrypted_ip2 = ipcrypt.encrypt_pfx(ip2) print(f"Original: {ip1} -> Encrypted: {encrypted_ip1}") print(f"Original: {ip2} -> Encrypted: {encrypted_ip2}") # Note: Both encrypted IPs will share the same /24 prefix # Decrypt the IP addresses decrypted_ip1 = ipcrypt.decrypt_pfx(encrypted_ip1) print(f"Decrypted: {decrypted_ip1}") # IPv6 example ipv6 = "2001:db8::1" encrypted_ipv6 = ipcrypt.encrypt_pfx(ipv6) print(f"IPv6: {ipv6} -> {encrypted_ipv6}") ```

Prefix Preservation Example

The following example demonstrates how addresses from the same network maintain their relationship after encryption:

``` Original Network: 192.168.1.0/24 ├── 192.168.1.10 ├── 192.168.1.25 └── 192.168.1.200 Encrypted (with same key): ├── 87.234.19.147 (shares encrypted /24 prefix) ├── 87.234.19.201 (shares encrypted /24 prefix) └── 87.234.19.42 (shares encrypted /24 prefix) Note: The encrypted prefix (87.234.19.x) is cryptographically transformed and unrecognizable without the key, but the network relationship is preserved. ```

ipcrypt-nd Mode

ND

How It Works

Non-deterministic encryption using KIASU-BC with an 8-byte tweak

The non-deterministic (nd) mode uses KIASU-BC, a tweakable block cipher based on AES, with an 8-byte tweak to provide non-deterministic encryption.

    +----------------+     +----------------+     +----------------+
    |                |     |                |     |                |
    |   IP Address   |---->|   Convert to   |---->|    KIASU-BC    |
    | (192.168.1.1)  |     |  16-byte form  |     |   Encryption   |
    |                |     |                |     |                |
    +----------------+     +----------------+     +----------------+
                                                   |
                           +----------------+      |
                           |                |      |
                           |   16-byte Key  |------+
                           |                |
                           +----------------+
                                                   |
                           +----------------+      |
                           |                |      |
                           |   8-byte Tweak |------+
                           |    (random)    |
                           +----------------+
                                                   |
                                                   v
                                                  +----------------+
                                                  |                |
                                                  |   Encrypted    |
                                                  |  24-byte value |
                                                  | (tweak+cipher) |
                                                  +----------------+
        

Process Flow

1
Input Preparation: The IP address is converted to a 16-byte representation
2
Tweak Generation: An 8-byte random tweak is generated
3
Encryption: The 16-byte representation is encrypted using KIASU-BC with the key and tweak
4
Output Formatting: The tweak and encrypted result are combined to form a 24-byte output

Key Properties

Non-Deterministic: Different encryptions of the same IP address produce different outputs
Correlation Protection: Prevents linking different encrypted versions of the same IP
Larger Output: Produces a 24-byte output that is not in IP address format
Tweak-Dependent: Decryption requires both the key and the original tweak

Use Cases

🔄
Data Sharing: When sharing data with third parties and correlation protection is important
📦
Long-term Storage: When data will be stored for extended periods
🔒
Privacy-Critical Applications: When maximum privacy protection is required

Code Example

```python from ipcrypt import IPCrypt import os # Initialize with a 16-byte key key = bytes.fromhex("000102030405060708090a0b0c0d0e0f") ipcrypt = IPCrypt(key) # Generate a random 8-byte tweak tweak = os.urandom(8) # Encrypt an IPv4 address ip = "192.168.1.1" encrypted_ip = ipcrypt.encrypt_nd(ip, tweak) print(f"Original IP: {ip}") print(f"Encrypted IP: {encrypted_ip}") # Decrypt the IP address decrypted_ip = ipcrypt.decrypt_nd(encrypted_ip, tweak) print(f"Decrypted IP: {decrypted_ip}") ```

ipcrypt-ndx Mode

NDX

How It Works

Non-deterministic encryption using AES-XTS with a 16-byte tweak

The extended non-deterministic (ndx) mode uses AES-XTS, a tweakable block cipher designed for disk encryption, with a 16-byte tweak to provide maximum security.

    +----------------+     +----------------+     +----------------+
    |                |     |                |     |                |
    |   IP Address   |---->|   Convert to   |---->|    AES-XTS     |
    | (192.168.1.1)  |     |  16-byte form  |     |   Encryption   |
    |                |     |                |     |                |
    +----------------+     +----------------+     +----------------+
                                                   |
                           +----------------+      |
                           |                |      |
                           |   16-byte Key  |------+
                           |                |
                           +----------------+
                                                   |
                           +----------------+      |
                           |                |      |
                           |  16-byte Tweak |------+
                           |    (random)    |
                           +----------------+
                                                   |
                                                   v
                                                  +----------------+
                                                  |                |
                                                  |   Encrypted    |
                                                  |  32-byte value |
                                                  | (tweak+cipher) |
                                                  +----------------+
        

Process Flow

1
Input Preparation: The IP address is converted to a 16-byte representation
2
Tweak Generation: A 16-byte random tweak is generated
3
Encryption: The 16-byte representation is encrypted using AES-XTS with the key and tweak
4
Output Formatting: The tweak and encrypted result are combined to form a 32-byte output

Key Properties

Maximum Security: Provides the highest security margin of all modes
Non-Deterministic: Different encryptions of the same IP address produce different outputs
Largest Output: Produces a 32-byte output
128-bit Tweak Space: Uses a full 16-byte tweak for maximum randomness

Use Cases

🔐
Highest Security Requirements: When maximum security is needed
📜
Regulatory Compliance: When strict privacy regulations must be met
🛡️
Sensitive Data Protection: When protecting highly sensitive information

Code Example

```python from ipcrypt import IPCrypt import os # Initialize with a 16-byte key key = bytes.fromhex("000102030405060708090a0b0c0d0e0f") ipcrypt = IPCrypt(key) # Generate a random 16-byte tweak tweak = os.urandom(16) # Encrypt an IPv4 address ip = "192.168.1.1" encrypted_ip = ipcrypt.encrypt_ndx(ip, tweak) print(f"Original IP: {ip}") print(f"Encrypted IP: {encrypted_ip}") # Decrypt the IP address decrypted_ip = ipcrypt.decrypt_ndx(encrypted_ip, tweak) print(f"Decrypted IP: {decrypted_ip}") ```

Choosing the Right Mode

?

Mode Selection Guide

Factors to consider when choosing an encryption mode

When selecting an encryption mode, consider the following factors:

1
Format Requirements: If you need to maintain the IP address format, use deterministic or pfx mode
2
Network Analytics: If you need to analyze network patterns, use pfx mode
3
Correlation Protection: If preventing correlation is important, use nd or ndx mode
4
Security Requirements: For maximum security, use ndx mode
5
Performance Considerations: Deterministic mode is fastest, followed by nd, ndx, and pfx
6
Storage Constraints: Consider the different output sizes when storage is limited

For most applications, the deterministic mode provides a good balance of security and usability. When network analytics are needed, pfx mode preserves subnet relationships. When privacy concerns are paramount, the non-deterministic modes offer stronger protection against correlation attacks.

Mode Comparison

Feature Deterministic Prefix-Preserving (PFX) Non-Deterministic (ND) Extended ND (NDX)
Underlying Algorithm AES-128 Dual AES-128 KIASU-BC AES-XTS
Format Preservation
Correlation Protection
Output Size 16 bytes 4/16 bytes 24 bytes 32 bytes
Tweak Size N/A N/A 8 bytes 16 bytes
Security Margin Standard Beyond Birthday High Highest
Performance Fastest Slower (bit-by-bit) Fast Moderate
Recommended Use Case Logging, Rate Limiting Network Analytics Data Sharing Highest Security Needs

Implementation Considerations

⚙️

Implementation Best Practices

Key considerations when implementing IPCrypt

When implementing these encryption modes, keep in mind:

🔑
Key Management: Securely generate and store encryption keys
🎲
Tweak Generation: For nd and ndx modes, use a cryptographically secure random number generator for tweaks
💾
Tweak Storage: Store tweaks alongside encrypted values for later decryption
⚠️
Error Handling: Implement proper error handling for invalid inputs
Testing: Verify your implementation against the provided test vectors

For more information on implementing these modes, see the Code Examples page.