cipherx 1.1.0
A custom SPN cipher implementation
Requires Python: >=3.6

# CipherX

A Python implementation of a custom Substitution-Permutation Network (SPN) cipher with multiple modes of operation.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python Version](https://img.shields.io/badge/python-3.6%2B-blue.svg)](https://www.python.org/downloads/)

## Overview

CipherX implements a block cipher based on the Substitution-Permutation Network (SPN) architecture, inspired by AES design principles. It features:

- **Block size:** 128 bits (16 bytes)
- **Key size:** 256 bits (32 bytes)
- **Rounds:** 10
- **Modes:** ECB, CBC, CTR
- **Components:** AES S-box, custom permutation layer, GF(2^8) MixColumns

## Installation

Install via pip:

```bash
pip install cipherx
```

Or install from source:

```bash
git clone https://github.com/metisos/cipherx.git
cd cipherx
pip install -e .
```

## Quick Start

### Basic Encryption/Decryption (CBC Mode - Recommended)

```python
from cipher import encrypt_cbc, decrypt_cbc
import os

# Generate a random 256-bit key
key = os.urandom(32)

# Your message
message = b"Hello, CipherX!"

# Encrypt (IV is automatically generated)
ciphertext, iv = encrypt_cbc(message, key)

# Decrypt
plaintext = decrypt_cbc(ciphertext, key, iv)

assert plaintext == message
```

### ECB Mode (Simple, but less secure)

```python
from cipher import encrypt, decrypt

key = b'supersecretkeythatis32byteslong!'
message = b"Hello, World!"

ciphertext = encrypt(message, key)
plaintext = decrypt(ciphertext, key)
```

### CTR Mode (Streaming)

```python
from cipher import encrypt_ctr, decrypt_ctr
import os

key = os.urandom(32)
nonce = os.urandom(8)

message = b"Stream this data!"

ciphertext = encrypt_ctr(message, key, nonce)
plaintext = decrypt_ctr(ciphertext, key, nonce)
```

## Security Considerations

### Mode Selection

**CBC Mode (Recommended):** Use `encrypt_cbc()` / `decrypt_cbc()` for most applications
- Provides semantic security with random IVs
- Hides patterns in plaintext
- Suitable for encrypting files, messages, etc.

**CTR Mode:** Use `encrypt_ctr()` / `decrypt_ctr()` for streaming data
- Turns block cipher into stream cipher
- Can encrypt/decrypt in parallel
- Suitable for large files, network streams

**ECB Mode (Not Recommended):** Avoid `encrypt()` / `decrypt()` in production
- Deterministic - same plaintext always produces same ciphertext
- Reveals patterns in data
- Only suitable for random data (e.g., encrypting random keys)

### Important Security Notes

1. **Key Management:**
   - Use `os.urandom(32)` to generate cryptographically secure random keys
   - Never hardcode keys in source code
   - Store keys securely (HSM, key management service, encrypted storage)

2. **IV/Nonce Handling:**
   - CBC: IV is automatically generated - store it with ciphertext
   - CTR: Use unique nonce for each encryption with same key
   - Never reuse IV/nonce with the same key

3. **Authentication:**
   - CipherX provides encryption only, not authentication
   - For integrity protection, use HMAC:

   ```python
   import hmac
   import hashlib

   # Encrypt-then-MAC pattern
   ciphertext, iv = encrypt_cbc(plaintext, encryption_key)
   mac = hmac.new(mac_key, iv + ciphertext, hashlib.sha256).digest()
   # Store: iv + ciphertext + mac
   ```

4. **Production Use:**
   - This is a custom cipher without extensive cryptanalysis
   - For critical applications, prefer established libraries:
     - [cryptography](https://cryptography.io/) (AES-GCM)
     - [PyCryptodome](https://pycryptodome.readthedocs.io/)
     - [NaCl/libsodium](https://pynacl.readthedocs.io/)

## API Reference

### Encryption Functions

#### `encrypt(data: bytes, key: bytes) -> bytes`
Encrypts data using ECB mode.

**Parameters:**
- `data` (bytes): Plaintext to encrypt
- `key` (bytes): 32-byte encryption key

**Returns:** Ciphertext (bytes)

**Note:** ECB mode is not recommended for production use.

---

#### `decrypt(ciphertext: bytes, key: bytes) -> bytes`
Decrypts data encrypted with ECB mode.

**Parameters:**
- `ciphertext` (bytes): Data to decrypt
- `key` (bytes): 32-byte encryption key

**Returns:** Plaintext (bytes)

---

#### `encrypt_cbc(data: bytes, key: bytes, iv: bytes = None) -> tuple[bytes, bytes]`
Encrypts data using CBC mode (recommended).

**Parameters:**
- `data` (bytes): Plaintext to encrypt
- `key` (bytes): 32-byte encryption key
- `iv` (bytes, optional): 16-byte initialization vector (auto-generated if None)

**Returns:** Tuple of (ciphertext, iv)

**Example:**
```python
ciphertext, iv = encrypt_cbc(b"Secret message", key)
# Store both ciphertext and iv
```

---

#### `decrypt_cbc(ciphertext: bytes, key: bytes, iv: bytes) -> bytes`
Decrypts data encrypted with CBC mode.

**Parameters:**
- `ciphertext` (bytes): Data to decrypt
- `key` (bytes): 32-byte encryption key
- `iv` (bytes): 16-byte initialization vector from encryption

**Returns:** Plaintext (bytes)

---

#### `encrypt_ctr(data: bytes, key: bytes, nonce: bytes) -> bytes`
Encrypts data using CTR mode (stream cipher mode).

**Parameters:**
- `data` (bytes): Plaintext to encrypt
- `key` (bytes): 32-byte encryption key
- `nonce` (bytes): 8-byte nonce (must be unique per encryption)

**Returns:** Ciphertext (bytes)

**Warning:** Never reuse the same nonce with the same key!

---

#### `decrypt_ctr(ciphertext: bytes, key: bytes, nonce: bytes) -> bytes`
Decrypts data encrypted with CTR mode.

**Parameters:**
- `ciphertext` (bytes): Data to decrypt
- `key` (bytes): 32-byte encryption key
- `nonce` (bytes): 8-byte nonce from encryption

**Returns:** Plaintext (bytes)

---

### Utility Functions

#### `pad_data(data: bytes) -> bytes`
Applies PKCS#7 padding to data.

#### `unpad_data(data: bytes) -> bytes`
Removes PKCS#7 padding from data.

## Technical Details

### Cipher Structure

CipherX implements a 10-round Substitution-Permutation Network:

```
Input Block (128 bits)
    |
    v
Initial AddRoundKey
    |
    v
[For each Round 1-10:]
  - SubBytes       (AES S-box)
  - Permutation    (Custom byte rearrangement)
  - MixColumns     (GF(2^8) operations, skipped in round 10)
  - AddRoundKey    (XOR with round key + constant)
    |
    v
Output Block (128 bits)
```

### Cryptographic Components

1. **SubBytes:** Uses standard AES S-box for non-linear substitution
2. **Permutation:** Custom 16-byte permutation for diffusion
3. **MixColumns:** Galois Field GF(2^8) matrix multiplication
4. **Key Schedule:** SHA-256-based round key derivation
5. **Round Constants:** SHA-256-derived constants per round

### Performance

Approximate throughput on modern hardware:
- ECB mode: ~5-10 MB/s (Python implementation)
- CBC mode: ~5-10 MB/s (sequential)
- CTR mode: ~5-10 MB/s (parallelizable in theory)

For better performance, consider:
- Using PyPy instead of CPython
- Implementing performance-critical paths in Cython
- Using established C-based libraries (OpenSSL, libsodium)

## Development

### Running Tests

```bash
python test_cipherx.py
```

### Project Structure

```
cipherx/
 cipher/
    __init__.py      # Public API exports
    core.py          # Core cipher implementation
 test_cipherx.py      # Test suite
 setup.py             # Package configuration
 README.md            # This file
 License              # MIT License
```

## Contributing

Contributions are welcome! Please:

1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Ensure all tests pass
5. Submit a pull request

## License

This project is licensed under the MIT License - see the [License](License) file for details.

## Disclaimer

This cipher implementation is provided for educational and experimental purposes. While it uses sound cryptographic principles, it has not undergone extensive cryptanalysis or formal security audits. For production systems handling sensitive data, use well-established cryptographic libraries that have been thoroughly vetted by the security community.

## Author

Christian Johnson (cjohnson@metisos.com)

## Repository

https://github.com/metisos/cipherx