Async Redis cache with optional AES-128 encryption powered by mores-encryption
Project description
๐ ValCache
Async Redis Cache with Optional AES-128 Encryption
ValCache is a lightweight, async-first Redis caching library for Python with two modes:
- ๐ Normal Mode (
ValCache) โ Fast plaintext caching with JSON support - ๐ Encrypted Mode (
EncryptedValCache) โ Transparent AES-128 encryption via mores-encryption
Perfect for securing PII, medical data, API keys, session tokens, or any sensitive information in your Redis cache.
๐ฆ Installation
pip install valcache
โ๏ธ Setup (Encrypted Mode)
Generate a secure encryption key:
python -c "from cryptography.fernet import Fernet; print('ENCRYPTION_KEY=' + Fernet.generate_key().decode())"
Save it in your .env file:
ENCRYPTION_KEY=your_generated_key_here
Or pass it directly to the constructor (see usage below).
๐ Usage
1. Normal Cache
from valcache import ValCache
cache = ValCache(host="localhost", port=6379, default_ttl=600)
await cache.connect()
# String operations
await cache.set("user:1", "John Doe")
name = await cache.get("user:1") # "John Doe"
# JSON operations
await cache.set_json("profile:1", {"name": "John", "age": 30})
profile = await cache.get_json("profile:1") # {"name": "John", "age": 30}
# Check existence
exists = await cache.exists("user:1") # True
# Delete
await cache.delete("user:1")
# Health check
healthy = await cache.health_check() # True
await cache.close()
2. Encrypted Cache
from valcache import EncryptedValCache
cache = EncryptedValCache(
host="localhost",
port=6379,
encryption_key="your-fernet-key-here", # or set ENCRYPTION_KEY env var
)
await cache.connect()
# Values are automatically encrypted in Redis
await cache.set("secret", "My Secret Data")
result = await cache.get("secret") # "My Secret Data" (decrypted)
# JSON encryption โ entire dict encrypted as one blob
await cache.set_json("patient:1", {"ssn": "123-45-6789", "diagnosis": "healthy"})
data = await cache.get_json("patient:1") # decrypted dict
await cache.close()
3. Hashed Keys (Full Anonymization)
When even the Redis key should not reveal sensitive information:
from valcache import EncryptedValCache
cache = EncryptedValCache(encryption_key="your-fernet-key")
await cache.connect()
# Key is hashed, value is encrypted
await cache.set_hashed("patient@hospital.com", "diagnosis data", salt="my_salt")
# Redis key: "a3F9x...Kz8=" (hashed) | Redis value: "gAAAAABk..." (encrypted)
# Retrieve using the same key + salt
data = await cache.get_hashed("patient@hospital.com", salt="my_salt")
# "diagnosis data" (decrypted)
# JSON with hashed keys
await cache.set_json_hashed("user@example.com", {"role": "admin"}, salt="my_salt")
profile = await cache.get_json_hashed("user@example.com", salt="my_salt")
# Delete & exists with hashed keys
await cache.delete_hashed("patient@hospital.com", salt="my_salt")
exists = await cache.exists_hashed("patient@hospital.com", salt="my_salt") # False
await cache.close()
๐ API Reference
ValCache (Normal Mode)
| Method | Description |
|---|---|
connect() |
Initialize the Redis connection pool |
close() |
Gracefully close the connection pool |
set(key, value, ttl=None) |
Store a value with optional TTL |
get(key) |
Retrieve a value by key |
delete(key) |
Delete a key |
exists(key) |
Check if a key exists |
set_json(key, data, ttl=None) |
Store a dict as JSON |
get_json(key) |
Retrieve and parse a JSON value |
health_check() |
Ping the Redis server |
get_ttl(key) |
Get remaining TTL for a key |
keys(pattern="*") |
List keys matching a pattern |
flush_db() |
Delete all keys in the database |
EncryptedValCache (Encrypted Mode)
Inherits all methods from ValCache. The following are automatically encrypted:
| Method | Key | Value |
|---|---|---|
set(key, value) |
Plaintext | ๐ Encrypted |
get(key) |
Plaintext | ๐ Decrypted |
set_json(key, data) |
Plaintext | ๐ Encrypted |
get_json(key) |
Plaintext | ๐ Decrypted |
Hashed-key methods (key is also anonymized):
| Method | Key | Value |
|---|---|---|
set_hashed(key, value, salt) |
๐ Hashed | ๐ Encrypted |
get_hashed(key, salt) |
๐ Hashed | ๐ Decrypted |
delete_hashed(key, salt) |
๐ Hashed | โ |
exists_hashed(key, salt) |
๐ Hashed | โ |
set_json_hashed(key, data, salt) |
๐ Hashed | ๐ Encrypted |
get_json_hashed(key, salt) |
๐ Hashed | ๐ Decrypted |
๐ Security Details
| Component | Implementation |
|---|---|
| Encryption | AES-128 CBC via cryptography.fernet.Fernet (PKCS7 padding, HMAC-SHA256 integrity) |
| Key Hashing | PBKDF2HMAC-SHA256 with 200,000 iterations, 32-byte output |
| Encoding | URL-safe Base64 for all encrypted outputs |
| Key Management | Via ENCRYPTION_KEY env var or constructor parameter |
๐งช Running Tests
pip install -e ".[encrypted,dev]"
pytest tests/ -v
๐ง Configuration
ValCache resolves configuration in this priority order:
- Constructor params โ
ValCache(host="myhost")wins .envfile / environment variables โ auto-loaded viapython-dotenv- Defaults โ
localhost,6379,0
.env File (Recommended)
Create a .env file in your project root:
# Redis connection
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_DB=0
REDIS_PASSWORD=your_redis_password
REDIS_MAX_CONNECTIONS=20
# Encryption (EncryptedValCache only)
ENCRYPTION_KEY=your_fernet_key_here
ValCache auto-loads this file โ no extra setup needed.
Environment Variables
| Variable | Description | Default |
|---|---|---|
REDIS_HOST |
Redis server hostname | localhost |
REDIS_PORT |
Redis server port | 6379 |
REDIS_DB |
Redis database number | 0 |
REDIS_PASSWORD |
Redis auth password | None |
REDIS_MAX_CONNECTIONS |
Connection pool size | 20 |
ENCRYPTION_KEY |
Fernet encryption key | Auto-generated |
Constructor Parameters
All env vars can be overridden via constructor:
| Parameter | Type | Overrides Env Var |
|---|---|---|
host |
str |
REDIS_HOST |
port |
int |
REDIS_PORT |
db |
int |
REDIS_DB |
password |
str |
REDIS_PASSWORD |
max_connections |
int |
REDIS_MAX_CONNECTIONS |
default_ttl |
int |
โ (no env var, default 3600) |
encryption_key |
str |
ENCRYPTION_KEY (EncryptedValCache only) |
๐ License
MIT License โ see LICENSE for details.
๐ Related
- mores-encryption โ The encryption library powering ValCache's encrypted mode
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file valcache-0.1.0.tar.gz.
File metadata
- Download URL: valcache-0.1.0.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bcd8703c104da2ece0995969c41961dbf05f3cce28129db4d43843e5ed207c7a
|
|
| MD5 |
5bae0364f2e214acee4a7ab0d15af76d
|
|
| BLAKE2b-256 |
15911930901a621aecef64abc28ddf070844ac2ed2c41647ed07bf021440d7bf
|
File details
Details for the file valcache-0.1.0-py3-none-any.whl.
File metadata
- Download URL: valcache-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20d406727b098535d3cf3059f344030199929d18d366785f759cc7b812fcf070
|
|
| MD5 |
e65ef66ea4452ee6a22079fc0c42a4ca
|
|
| BLAKE2b-256 |
76f878d4cfb8898282935dbe15d1192af28fd3b7a58581d07787df78bef6579b
|