Comprehensive rules for implementing strong, modern encryption of data in transit and at rest, including key management, error handling, testing, and performance tuning.
You're handling sensitive data, but your current encryption implementation is holding you back. Maybe you're using deprecated algorithms, managing keys manually, or worse—storing sensitive data without encryption. Every day of delay increases your security debt and compliance risk.
Production systems face constant threats: data breaches cost companies an average of $4.45 million, and regulatory fines can reach tens of millions. But beyond compliance, inadequate encryption creates hidden productivity drains:
Your development team shouldn't spend time figuring out crypto primitives—they need bulletproof patterns that work reliably in production.
These Cursor Rules provide battle-tested encryption patterns that eliminate common security pitfalls while accelerating development. They establish production-grade standards for:
Modern Crypto Standards: Automatic enforcement of AES-256-GCM, TLS 1.3+, and post-quantum-ready algorithms without manual configuration headaches.
Zero-Trust Key Management: Seamless integration with AWS KMS and HashiCorp Vault, removing the temptation to hardcode secrets while automating key rotation.
Defensive Error Handling: Built-in honey encryption and circuit breakers that protect against timing attacks and oracle vulnerabilities.
Performance-Optimized Patterns: Hybrid encryption strategies that automatically optimize for your data size—streaming for large files, efficient wrapping for small payloads.
Instead of back-and-forth with security teams, these rules pre-implement approved patterns. Your crypto code passes reviews on the first attempt because it follows NIST standards and industry best practices by default.
# Auto-generates with proper key management and error handling
@encrypt_at_rest(key_source="kms://production-dek")
def store_user_data(user_id: str, data: bytes) -> str:
# Implementation handles key retrieval, encryption, and secure storage
pass
Clear error hierarchies and structured logging mean crypto failures surface actionable information instead of cryptic OpenSSL errors. No more hunting through stack traces to find why decryption failed.
These patterns align with SOC 2, HIPAA, and PCI DSS requirements out of the box. Your compliance documentation writes itself when you're using approved crypto primitives and key management practices.
Developers can implement encryption features rapidly without compromising security standards. The rules prevent common mistakes like IV reuse or weak cipher selection while maintaining code readability.
Before: Manual crypto implementation
# Fragile, security team will reject this
import hashlib
from Crypto.Cipher import AES
def encrypt_data(data: str, password: str):
key = hashlib.sha256(password.encode()).digest()
cipher = AES.new(key, AES.MODE_ECB) # ❌ Weak mode
# ❌ No padding, no IV, hardcoded key derivation
After: Rules-generated implementation
# Production-ready, passes security review
from security.crypto import encrypt
from security.keystore import get_key
def encrypt_user_data(plaintext: bytes) -> bytes:
key = get_key("user-data-dek", rotation_check=True)
return encrypt(key, plaintext, aad=b"user_table")
# ✅ AES-256-GCM, proper nonce, AAD protection, key rotation
Before: Mixed security practices
@app.post("/upload")
async def upload_file(file: UploadFile):
content = await file.read()
# ❌ Storing plaintext, no input validation
with open(f"uploads/{file.filename}", "wb") as f:
f.write(content)
After: Comprehensive protection
@app.post("/upload")
@require_tls_13
async def upload_file(file: UploadFile):
content = await file.read()
validate_file_size(content, max_size=32*1024*1024)
encrypted = encrypt_file_stream(content, aad=f"upload:{file.filename}")
store_encrypted_file(encrypted, metadata={
"filename": file.filename,
"encrypted_at": utcnow(),
"key_version": current_key_version()
})
pip install cryptography[complete] pynacl hvac boto3
pip install --dev hypothesis py-perf ruff
Copy the rules configuration to your .cursorrules file. The rules automatically scaffold the proper directory structure:
security/
├── crypto/ # Symmetric encryption helpers
├── pqc/ # Post-quantum algorithms
├── keystore/ # Vault/KMS integration
└── tests/ # Property-based security tests
# security/keystore/vault_client.py - Auto-generated
from hvac import Client
class VaultKeystore:
def __init__(self, vault_url: str, token_path: str):
self.client = Client(url=vault_url)
self.client.token = self._get_token(token_path)
def get_dek(self, key_name: str) -> bytes:
# Handles key retrieval with MFA enforcement
pass
When you type encryption-related code, Cursor automatically suggests patterns that implement:
# tests/security/test_crypto_properties.py - Auto-generated
from hypothesis import given, strategies as st
from security.crypto import encrypt, decrypt
@given(st.binary(min_size=1, max_size=1024))
def test_encryption_roundtrip(plaintext: bytes):
key = generate_key()
ciphertext = encrypt(key, plaintext)
assert decrypt(key, ciphertext) == plaintext
Your security team will thank you for implementing proper crypto patterns, your compliance auditors will find nothing to criticize, and your development team will stop worrying about encryption complexity. These rules transform encryption from a development bottleneck into a transparent, reliable foundation for secure applications.
The cost of weak encryption compounds daily. Implement these rules and secure your applications with patterns that scale from startup to enterprise.
You are an expert in Python 3.12+, OpenSSL 3.x, libsodium 1.0.19+, AWS KMS, HashiCorp Vault, and NIST post-quantum algorithms (ML-KEM, HQC).
Key Principles
- Encrypt every sensitive datum both in transit (TLS 1.3+) and at rest (AES-256-GCM by default).
- Never hard-code keys or secrets; retrieve them from a dedicated secrets manager (Vault/KMS) via short-lived tokens.
- Prefer authenticated encryption modes (GCM, ChaCha20-Poly1305) to guarantee confidentiality + integrity.
- Separate encryption concerns from business logic; place crypto helpers in `/security/crypto/`.
- Default to post-quantum-ready hybrids (e.g., ML-KEM for key exchange, AES-256-GCM for payload) when the data must remain confidential >10 years.
- Automate key rotation (≤90 days) and enforce MFA for any manual overrides.
- Treat encryption failures as security incidents; log only metadata, never plaintext or keys.
- Ensure every unit/integration test has a corresponding negative (tampering) test.
Python
- Use the `cryptography` package; never call OpenSSL through `subprocess`.
- Explicit imports only: `from cryptography.hazmat.primitives.ciphers.aead import AESGCM`.
- Type-annotate all crypto functions and return `bytes`, never strings, for ciphertext.
- Use context managers to zeroise sensitive material:
```python
with AESGCM.generate_key(bit_length=256) as key:
...
```
- Filenames: `*_crypto.py` for symmetric helpers, `*_pqc.py` for post-quantum code.
- Lint with `ruff` using the `flake8-bandit` plugin; treat B101-B604 as errors.
- Disallow `eval`, `marshal`, and `pickle` on untrusted input.
Error Handling & Validation
- Validate inputs before encryption: non-empty, type `bytes`, size ≤32 MB (stream larger data).
- Use early returns for error conditions:
```python
if not plaintext:
raise ValueError("Plaintext must not be empty")
```
- Catch only specific exceptions (`InvalidTag`, `InvalidSignature`); re-raise a custom `CryptoError` wrapper.
- Implement honey encryption for high-value stores: on decryption failure return plausible decoys logged with severity WARN.
- Force immediate process exit on repeated crypto errors (≥3 within 60 s) to avoid oracle leaks.
OpenSSL / libsodium (Framework Rules)
- Compile OpenSSL with `--enable-ec_nistp_64_gcc_128` and `no-deprecated`.
- Require `TLS_AES_256_GCM_SHA384` or `TLS_CHACHA20_POLY1305_SHA256` cipher suites.
- Enforce `X25519` or ML-KEM for ECDHE/KEM; disable RSA key exchange.
- For libsodium:
- Use `crypto_aead_chacha20poly1305_ietf_*` for UDP/QUIC traffic.
- Stream large files with `crypto_secretstream_xchacha20poly1305_*`.
- Always call `sodium_memzero` on key buffers after use.
Additional Sections
Testing
- Write property-based tests with `hypothesis` to ensure encryption⇄decryption round-trips for arbitrary payloads.
- Simulate corruption: flip random bits and assert `InvalidTag` is raised.
- Include post-quantum KATs (Known Answer Tests) from NIST vectors.
Performance
- Use hybrid encryption: RSA-4096 or ML-KEM for key wrap, AES-256-GCM for bulk.
- Chunk files >100 MB using 4 MB segments; update `AAD` with segment index.
- Benchmark with `py-perf`; target <2 µs/KB overhead.
Security
- Store root KEK in HSM; wrap DEKs with KEK (+ AES-KW).
- Enforce `kms:Decrypt` IAM policy with `aws:MultiFactorAuthPresent = true`.
- Log to an immutable store (CloudTrail, immudb) with SIG-V4 signed entries.
- Apply secure erase on disk (`blkdiscard --secure`) before decommission.
File & Directory Naming
- `security/crypto/` – symmetric helpers
- `security/pqc/` – post-quantum algorithms
- `security/keystore/` – Vault/KMS integration
- `tests/security/` – unit + property tests
Do-Not List
- Do not use DES, 3DES, RC4, or ECB mode.
- Never reuse IVs/nonces; generate `os.urandom(12)` per AES-GCM message.
- Do not downgrade TLS (`SSLv*`, `TLS 1.0/1.1`).
- Avoid storing encryption keys in environment variables for >10 minutes.
Examples
Symmetric Encryption Helper
```python
from os import urandom
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from .errors import CryptoError
__all__ = ["encrypt", "decrypt"]
KEY_SIZE = 32 # 256 bits
NONCE_SIZE = 12
def encrypt(key: bytes, plaintext: bytes, *, aad: bytes | None = None) -> bytes:
if len(key) != KEY_SIZE:
raise ValueError("Key must be 32 bytes (AES-256)")
if not plaintext:
raise ValueError("Plaintext empty")
nonce = urandom(NONCE_SIZE)
aesgcm = AESGCM(key)
try:
ct = aesgcm.encrypt(nonce, plaintext, aad)
return nonce + ct
except Exception as exc: # noqa: BLE001
raise CryptoError("Encryption failed") from exc
```
TLS Server Snippet (FastAPI)
```python
import ssl
from uvicorn import run
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ctx.minimum_version = ssl.TLSVersion.TLSv1_3
ctx.set_ciphers("TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256")
ctx.load_cert_chain("cert.pem", "key.pem")
run("app:api", host="0.0.0.0", port=443, ssl_context=ctx)
```