AgentStack
SKILL verified Unlicense Self-run

Encryption

skill-martinholovsky-claude-skills-generator-encryption · by martinholovsky

A Claude skill from martinholovsky/claude-skills-generator.

No reviews yet
0 installs
12 views
0.0% view→install

Install

$ agentstack add skill-martinholovsky-claude-skills-generator-encryption

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Are you the author of Encryption? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

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

  1. Encrypt data at rest using AES-256-GCM with authenticated encryption
  2. Derive keys securely using Argon2id with appropriate parameters
  3. Manage key lifecycle including rotation, escrow, and destruction
  4. Protect key material in memory and during operations
  5. Integrate with OS keychains for master key storage

2.2 Core Principles

  1. TDD First - Write tests before implementation; test encryption/decryption round-trips, authentication failures, and edge cases
  2. Performance Aware - Cache derived keys, use streaming for large data, leverage hardware acceleration
  3. Security by Default - Use authenticated encryption modes, memory-hard KDFs, secure random sources
  4. 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.

Versions

  • v0.1.0 Imported from the upstream source.