Skip to main content

ValCache

PyPI Python License: MIT Tests

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:

  1. Constructor params — ValCache(host="myhost") wins
  2. .env file / environment variables — auto-loaded via python-dotenv
  3. Defaults — localhost, 6379, 0

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.


  • mores-encryption — The encryption library powering ValCache's encrypted mode

Metadata

Release files for valcache 1.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for valcache 1.0.2
File Size Uploaded
valcache-1.0.2.tar.gz 14.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for valcache 1.0.2
File Interpreter ABI Platform
valcache-1.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 25.2 kB

Release files / valcache-1.0.2.tar.gz

Download URL valcache-1.0.2.tar.gz
Size 14.4 kB
Tags Source
SHA-256 checksum
How to use checksums
3a2d5be97d0bb69cd0f459b6ccc6925a2726c6944983756ec67a32edbf6a0d9f
BLAKE2b-256 checksum
How to use checksums
6acffae149ef55cd8a1340ceb01b027130b5ab81395895afad37cdf9f86d8950
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.15

Release files / valcache-1.0.2-py3-none-any.whl

Download URL valcache-1.0.2-py3-none-any.whl
Size 10.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4b18b62a7e355d1d086ad080c98b6ed3fb71c96c0b7a7645f87e61d722061ba4
BLAKE2b-256 checksum
How to use checksums
844a23da689e7e5339fd0dac14afa32bfcd91ccbbe1823eb9497ae967f78122d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.15

Release history Release notifications | RSS feed

This release

1.0.2 This release

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page