ENCRYPTION_SERVICE
AES-256-CTR encryption/decryption utilities with deterministic IV generation for cross-language interoperability.
Installation
pip install ENCRYPTION_SERVICE
Quick Start
Set environment variables in .env
ENCRYPTION_KEY=your-secret-phrase # MUST be ≥ 32 bytes, cryptographically random
Import and use
from ENCRYPTION_SERVICE import Aes256CtrEncryption
# Encrypt plaintext to base64
token = Aes256CtrEncryption.encrypt("s3cr3t") # → "XXXXX..."
# Decrypt back to plaintext
plain = Aes256CtrEncryption.decrypt(token) # → "s3cr3t"
# Decrypt a nested field in JSON
payload = {"db": {"pass": Aes256CtrEncryption.encrypt("hunter2")}}
pw = Aes256CtrEncryption.decrypt_json_field(payload, "db.pass") # → "hunter2"
⚠️ SECURITY: ENCRYPTION_KEY must be ≥ 32 bytes of cryptographically random data.
Never use a human-chosen password. A warning fires on first use if key is too short.
Configuration
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
ENCRYPTION_KEY |
Yes | — | AES-256 key material (≥ 32 bytes, cryptographically random) |
API Reference
Aes256CtrEncryption.encrypt(plaintext: str) -> str
Encrypts arbitrary plaintext to a base64 string.
plaintext: String to encrypt- Returns: Base64-encoded ciphertext
Aes256CtrEncryption.decrypt(encoded_ciphertext: str) -> str
Decrypts base64-encoded ciphertext back to plaintext.
encoded_ciphertext: Base64-encoded ciphertext from encrypt()- Returns: Original plaintext string
- Raises:
ValueErrorif ciphertext is malformed (shorter than 16 bytes)
Aes256CtrEncryption.decrypt_json_field(encrypted_json: dict, json_path: str) -> str
Decrypts a single nested field in a JSON object.
encrypted_json: Dictionary containing encrypted fieldsjson_path: Dot-notation path (e.g. "user.credentials.password")- Returns: Decrypted plaintext string
- Raises:
ValueErrorif path doesn't exist or points to non-string
Key Features
- Deterministic IV Generation — Same plaintext always produces same ciphertext (cross-language compatible)
- AES-256-CTR Mode — High-performance encryption with no padding issues
- SHA-256 Key Derivation — Compatible with Rust sibling implementation
- Retry with Exponential Backoff + Jitter — 3 attempts with exponential backoff and ±25% jitter
- Lazy Config Loading — No side effects on import; validated on first use
- Pure Cryptographic Functions — No side effects, thread-safe, deterministic
Security Notes
- Key Requirements: Use cryptographically random keys ≥ 32 bytes. SHA-256 derivation provides no brute-force resistance.
- Deterministic Encryption: Identical plaintexts produce identical ciphertexts — acceptable for this use case.
- Cross-Language Interop: IV derivation matches Rust implementation exactly.
Performance
┌──────────────────────┬──────────┬──────────┬─────────────┬──────────┬──────────┐
│ Test │ Ops │ Time │ Throughput │ Target │ Status │
├──────────────────────┼──────────┼──────────┼─────────────┼──────────┼──────────┤
│ Encrypt (1-thread) │ 1,000 │ 0.038 s │ 26,253/sec │ 10k/sec │ ✅ PASS │
│ Decrypt (1-thread) │ 1,000 │ 0.028 s │ 35,920/sec │ 10k/sec │ ✅ PASS │
│ Round-trip │ 100 │ 0.058 ms │ avg/call │ < 1 ms │ ✅ PASS │
│ JSON field decrypt │ 500 │ 0.014 s │ 37,171/sec │ 10k/sec │ ✅ PASS │
│ Encrypt (4-thread) │ 1,000 │ 0.092 s │ 11,052/sec │ 10k/sec │ ✅ PASS │
│ Encrypt (8-thread) │ 2,000 │ 0.197 s │ 10,163/sec │ 10k/sec │ ✅ PASS │
└──────────────────────┴──────────┴──────────┴─────────────┴──────────┴──────────┘
System: Ubuntu 24.04.4 LTS | AMD Ryzen 7 5800H (16 cores, 13Gi RAM) | Python 3.12.3
Tested: 2026-04-03 16:56 UTC
GIL note: Multi-thread throughput is limited by Python's GIL — AES-CTR is CPU-bound.
Use multiprocessing if CPU-bound parallelism is required.
Error Handling
The library will raise ValueError if:
ENCRYPTION_KEYis not set (raised on first crypto call, not at import)- Ciphertext is shorter than 16 bytes (truncated IV)
- JSON path does not exist in the provided dict
- JSON path resolves to a non-string leaf (not an encrypted value)
UserWarning fires on first use if ENCRYPTION_KEY is shorter than 32 bytes.
Retry Policy
All cryptographic operations use @with_retry decorator:
- Max attempts: 3
- Delay: Exponential backoff (1s, 2s, 4s) with ±25% jitter
- Retryable: All exceptions (local crypto has no 4xx-equivalent)
- Logging: WARNING per attempt, ERROR on exhaustion
Test Coverage
python3 -m pytest ENCRYPTION_SERVICE.py -v
| Function | Tier | Tests | What is tested |
|---|---|---|---|
encrypt() |
1 | 4 | non-empty base64, determinism, different inputs, empty string |
decrypt() |
1 | 4 | round-trip, empty string, too-short input, unicode |
decrypt_json_field() |
1 | 4 | nested path, single-level, missing key, wrong type |
with_retry() |
2 | 4 | first-attempt success, third-attempt success, exhaustion, all exception types |
_derive_256bit_key() |
2 | 3 | 32 bytes output, determinism, different passwords |
_generate_deterministic_iv() |
2 | 3 | 16 bytes output, determinism, different plaintexts |
Import validation |
3 | 1 | missing key raises, short key warns |
Release files for ENCRYPTION-SERVICE 0.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| encryption_service-0.0.3.tar.gz | 18.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| encryption_service-0.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:35.0 kB
Release files / encryption_service-0.0.3.tar.gz
| Download URL | encryption_service-0.0.3.tar.gz |
|---|---|
| Size | 18.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2ffa757c92314d0cd58d0f90b68edcd68d151f1f2e12bead6c85b364eca44604
|
|
BLAKE2b-256 checksum How to use checksums |
45dd40916f5270f7062e3207454536318c533e0e9738dd86e8d16fa79c613ba0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / encryption_service-0.0.3-py3-none-any.whl
| Download URL | encryption_service-0.0.3-py3-none-any.whl |
|---|---|
| Size | 16.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
41b4c24a02b4f6bcd4828e4fb836588a10a9fd5f9fd0db5ea57b0cc81d67241d
|
|
BLAKE2b-256 checksum How to use checksums |
0548ac7533afee6f4d0230373a6a070e4973acd22b61ae4cf95869f99ed8226d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|