Install
$ agentstack add skill-martinholovsky-claude-skills-generator-encryption ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
About
Encryption Skill
name: encryption version: 1.0.0 domain: security/cryptography risklevel: HIGH languages: [python, typescript, rust, go] frameworks: [sqlcipher, cryptography, libsodium] requiressecurityreview: true compliance: [GDPR, HIPAA, PCI-DSS, SOC2] lastupdated: 2025-01-15 ---
> MANDATORY READING PROTOCOL: Before implementing ANY encryption, read references/advanced-patterns.md for key derivation and references/security-examples.md for implementation patterns.
1. Overview
1.1 Purpose and Scope
This skill provides secure-by-default patterns for implementing encryption in JARVIS AI Assistant, covering:
- SQLCipher: Encrypted SQLite database with AES-256-GCM
- Argon2id: Memory-hard key derivation function
- Key Management: Secure generation, storage, rotation, and destruction
- Secure Memory: Protection against memory disclosure attacks
1.2 Risk Assessment
Risk Level: HIGH
Justification:
- Cryptographic failures expose all protected data
- Key compromise leads to complete confidentiality loss
- Implementation errors are catastrophic and often undetectable
- Regulatory violations (GDPR, HIPAA, PCI-DSS) carry severe penalties
Attack Surface:
- Key derivation weaknesses
- Insecure random number generation
- Timing side-channels
- Memory disclosure (cold boot, crash dumps)
- Key reuse across contexts
2. Core Responsibilities
2.1 Primary Functions
- Encrypt data at rest using AES-256-GCM with authenticated encryption
- Derive keys securely using Argon2id with appropriate parameters
- Manage key lifecycle including rotation, escrow, and destruction
- Protect key material in memory and during operations
- Integrate with OS keychains for master key storage
2.2 Core Principles
- TDD First - Write tests before implementation; test encryption/decryption round-trips, authentication failures, and edge cases
- Performance Aware - Cache derived keys, use streaming for large data, leverage hardware acceleration
- Security by Default - Use authenticated encryption modes, memory-hard KDFs, secure random sources
- Defense in Depth - Multiple layers of protection, fail securely, minimize key exposure
2.3 Security Principles
- NEVER implement custom cryptographic algorithms
- NEVER use ECB mode or unauthenticated encryption
- ALWAYS use cryptographically secure random number generators
- ALWAYS validate ciphertext authenticity before decryption
- ALWAYS use constant-time comparison for authentication tags
3. Implementation Workflow (TDD)
Step 1: Write Failing Test First
import pytest
from cryptography.exceptions import InvalidTag
class TestEncryptionTDD:
"""TDD tests for encryption implementation."""
def test_encrypt_decrypt_roundtrip(self):
"""Test that encryption followed by decryption returns original data."""
from jarvis.security.encryption import SecureEncryption
key = secrets.token_bytes(32)
encryptor = SecureEncryption(key)
plaintext = b"sensitive data for JARVIS"
ciphertext = encryptor.encrypt(plaintext)
decrypted = encryptor.decrypt(ciphertext)
assert decrypted == plaintext
assert ciphertext != plaintext # Must be encrypted
def test_tampered_ciphertext_raises_error(self):
"""Test that tampered ciphertext is rejected."""
from jarvis.security.encryption import SecureEncryption
key = secrets.token_bytes(32)
encryptor = SecureEncryption(key)
ciphertext = encryptor.encrypt(b"secret")
tampered = ciphertext[:-1] + bytes([ciphertext[-1] ^ 0xFF])
with pytest.raises(InvalidTag):
encryptor.decrypt(tampered)
def test_key_derivation_consistency(self):
"""Same password + salt = same key; different salt = different key."""
from jarvis.security.encryption import SecureKeyDerivation
password = "strong_password_123"
salt = secrets.token_bytes(16)
key1, _ = SecureKeyDerivation.derive_key(password, salt)
key2, _ = SecureKeyDerivation.derive_key(password, salt)
assert key1 == key2 and len(key1) == 32
key3, salt3 = SecureKeyDerivation.derive_key(password)
assert key1 != key3 # Different salt = different key
Step 2: Implement Minimum to Pass
Implement only what's needed to pass the tests. Start with basic encryption/decryption, then add key derivation.
Step 3: Refactor Following Patterns
After tests pass, add: memory protection, error handling, AAD support, key caching.
Step 4: Run Full Verification
# Run encryption tests with coverage
pytest tests/security/test_encryption.py -v --cov=jarvis.security.encryption --cov-fail-under=90
# Run security-specific tests
pytest tests/security/ -k "encryption or crypto" -v
# Check for timing vulnerabilities
pytest tests/security/test_timing.py -v
# Verify no secrets in output
pytest --log-cli-level=DEBUG 2>&1 | grep -i "key\|secret\|password" && echo "WARNING: Secrets in logs!"
4. Technology Stack
4.1 Recommended Libraries
| Language | Library | Version | Notes | |----------|---------|---------|-------| | Python | cryptography | >=42.0.0 | Uses OpenSSL 3.x backend | | Python | argon2-cffi | >=23.1.0 | Reference Argon2 implementation | | TypeScript | @noble/ciphers | >=0.5.0 | Audited pure-JS implementation | | Rust | ring | >=0.17.0 | BoringSSL-backed | | Go | crypto/cipher | stdlib | Use with golang.org/x/crypto |
4.2 SQLCipher Configuration
Minimum Version: SQLCipher 4.5.6+ (includes SQLite 3.44.2)
# SQLCipher secure configuration
SQLCIPHER_PRAGMAS = {
'key': None, # Set via secure key injection
'cipher': 'aes-256-gcm',
'kdf_iter': 256000, # PBKDF2 iterations
'cipher_page_size': 4096,
'cipher_kdf_algorithm': 'PBKDF2_HMAC_SHA512',
'cipher_hmac_algorithm': 'HMAC_SHA512',
'cipher_plaintext_header_size': 0,
}
5. Performance Patterns
5.1 Key Caching
Bad: Deriving key on every operation (~500ms per Argon2id call)
Good - Cache with TTL:
class CachedKeyManager:
def __init__(self, cache_ttl: int = 300):
self._cache: dict[str, tuple[bytes, float]] = {}
self._ttl = cache_ttl
def get_key(self, password: str, salt: bytes) -> bytes:
cache_key = f"{hash(password)}:{salt.hex()}"
if cache_key in self._cache:
key, ts = self._cache[cache_key]
if time.time() - ts tuple[bytes, bytes]:
"""
Derive a 256-bit key from password.
Returns:
tuple: (derived_key, salt) for storage
"""
if salt is None:
salt = secrets.token_bytes(cls.SALT_LEN)
# Validate inputs
if not password or len(password) bytes:
"""
Encrypt with random nonce, prepended to ciphertext.
Returns:
bytes: nonce || ciphertext || tag
"""
nonce = secrets.token_bytes(self.NONCE_SIZE)
ciphertext = self._aesgcm.encrypt(nonce, plaintext, associated_data)
return nonce + ciphertext
def decrypt(self, ciphertext: bytes, associated_data: bytes = None) -> bytes:
"""
Decrypt and verify authenticity.
Raises:
InvalidTag: If authentication fails
"""
if len(ciphertext) Q", time())` | `secrets.token_bytes(12)` |
| No Auth | `modes.CBC(iv)` | `aesgcm.encrypt(nonce, pt, aad)` |
| Weak KDF | `sha256(password)` | `Argon2id.derive_key()` |
## 10. Pre-Implementation Checklist
### Phase 1: Before Writing Code
- [ ] Read threat model in `references/threat-model.md`
- [ ] Identify data classification (PII, PHI, credentials)
- [ ] Choose appropriate algorithm (AES-256-GCM or ChaCha20-Poly1305)
- [ ] Design key derivation strategy (Argon2id parameters)
- [ ] Plan key storage (OS keychain integration)
- [ ] Write failing tests for encrypt/decrypt round-trips
- [ ] Write tests for authentication tag verification
- [ ] Write tests for key derivation consistency
### Phase 2: During Implementation
- [ ] Use `cryptography` library (not custom implementations)
- [ ] Generate nonces with `secrets.token_bytes(12)`
- [ ] Implement key caching with TTL for performance
- [ ] Use streaming for files >10MB
- [ ] Zero key material after use (SecureKeyHolder pattern)
- [ ] Add associated data (AAD) for context binding
- [ ] Handle InvalidTag exceptions without leaking info
- [ ] Run tests after each function implementation
### Phase 3: Before Committing
- [ ] All TDD tests pass with 90%+ coverage
- [ ] Nonce uniqueness validated over 10,000+ operations
- [ ] Key derivation timing variance 100MB/s
- Batch operations: Linear scaling
- [ ] Security review requested for HIGH risk code
## 11. Summary
**Key Objectives**: AES-256-GCM with random nonces, Argon2id KDF, OS keychain integration, authenticated encryption, key rotation support.
**Security Reminders**: No custom crypto, use audited libraries, test auth tags, rotate keys on schedule.
**References**: `references/advanced-patterns.md`, `references/security-examples.md`, `references/threat-model.md`
---
**Encryption done wrong is worse than no encryption - it provides false confidence.**
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [martinholovsky](https://github.com/martinholovsky)
- **Source:** [martinholovsky/claude-skills-generator](https://github.com/martinholovsky/claude-skills-generator)
- **License:** Unlicense
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.