Agent Skills: Data Encryption

Implement strong encryption using AES, RSA, TLS, and proper key management. Use when securing data at rest, in transit, or implementing end-to-end encryption.

UncategorizedID: aj-geddes/useful-ai-prompts/data-encryption

Install this agent skill to your local

pnpm dlx add-skill https://github.com/aj-geddes/useful-ai-prompts/tree/HEAD/skills/data-encryption

Skill Files

Browse the full folder contents for data-encryption.

Download Skill

Loading file tree…

skills/data-encryption/SKILL.md

Skill Metadata

Name
data-encryption
Description
Implement strong encryption using AES, RSA, TLS, and proper key management. Use when securing data at rest, in transit, or implementing end-to-end encryption.

Data Encryption

Overview

Implement robust encryption strategies for protecting sensitive data at rest and in transit using industry-standard cryptographic algorithms and key management practices.

When to Use

  • Sensitive data storage
  • Database encryption
  • File encryption
  • Communication security
  • Compliance requirements (GDPR, HIPAA, PCI-DSS)
  • Password storage
  • End-to-end encryption

Implementation Examples

1. Node.js Encryption Library

// encryption-service.js
const crypto = require("crypto");
const fs = require("fs").promises;

class EncryptionService {
  constructor() {
    // AES-256-GCM for symmetric encryption
    this.algorithm = "aes-256-gcm";
    this.keyLength = 32; // 256 bits
    this.ivLength = 16; // 128 bits
    this.saltLength = 64;
    this.tagLength = 16;
  }

  /**
   * Generate a cryptographically secure random key
   */
  generateKey() {
    return crypto.randomBytes(this.keyLength);
  }

  /**
   * Derive a key from a password using PBKDF2
   */
  async deriveKey(password, salt = null) {
    if (!salt) {
      salt = crypto.randomBytes(this.saltLength);
    }

    return new Promise((resolve, reject) => {
      crypto.pbkdf2(
        password,
        salt,
        100000, // iterations
        this.keyLength,
        "sha512",
        (err, derivedKey) => {
          if (err) reject(err);
          else resolve({ key: derivedKey, salt });
        },
      );
    });
  }

  /**
   * Encrypt data using AES-256-GCM
   */
  encrypt(data, key) {
    const iv = crypto.randomBytes(this.ivLength);
    const cipher = crypto.createCipheriv(this.algorithm, key, iv);

    let encrypted = cipher.update(data, "utf8", "hex");
    encrypted += cipher.final("hex");

    const tag = cipher.getAuthTag();

    // Return IV + encrypted data + auth tag
    return {
      encrypted: encrypted,
      iv: iv.toString("hex"),
      tag: tag.toString("hex"),
    };
  }

  /**
   * Decrypt data using AES-256-GCM
   */
  decrypt(encryptedData, key, iv, tag) {
    const decipher = crypto.createDecipheriv(
      this.algorithm,
      key,
      Buffer.from(iv, "hex"),
    );

    decipher.setAuthTag(Buffer.from(tag, "hex"));

    let decrypted = decipher.update(encryptedData, "hex", "utf8");
    decrypted += decipher.final("utf8");

    return decrypted;
  }

  /**
   * Encrypt file
   */
  async encryptFile(inputPath, outputPath, key) {
    const iv = crypto.randomBytes(this.ivLength);
    const cipher = crypto.createCipheriv(this.algorithm, key, iv);

    const input = await fs.readFile(inputPath);
    const encrypted = Buffer.concat([cipher.update(input), cipher.final()]);

    const tag = cipher.getAuthTag();

    // Write IV + encrypted data + auth tag
    const output = Buffer.concat([iv, encrypted, tag]);
    await fs.writeFile(outputPath, output);

    return { iv: iv.toString("hex"), tag: tag.toString("hex") };
  }

  /**
   * Decrypt file
   */
  async decryptFile(inputPath, outputPath, key) {
    const data = await fs.readFile(inputPath);

    const iv = data.subarray(0, this.ivLength);
    const tag = data.subarray(data.length - this.tagLength);
    const encrypted = data.subarray(
      this.ivLength,
      data.length - this.tagLength,
    );

    const decipher = crypto.createDecipheriv(this.algorithm, key, iv);
    decipher.setAuthTag(tag);

    const decrypted = Buffer.concat([
      decipher.update(encrypted),
      decipher.final(),
    ]);

    await fs.writeFile(outputPath, decrypted);
  }

  /**
   * Hash password using bcrypt-style approach
   */
  async hashPassword(password) {
    const salt = crypto.randomBytes(16);

    return new Promise((resolve, reject) => {
      crypto.pbkdf2(password, salt, 100000, 64, "sha512", (err, hash) => {
        if (err) reject(err);
        else {
          const combined = Buffer.concat([salt, hash]);
          resolve(combined.toString("hex"));
        }
      });
    });
  }

  /**
   * Verify password hash
   */
  async verifyPassword(password, hashedPassword) {
    const combined = Buffer.from(hashedPassword, "hex");
    const salt = combined.subarray(0, 16);
    const hash = combined.subarray(16);

    return new Promise((resolve, reject) => {
      crypto.pbkdf2(
        password,
        salt,
        100000,
        64,
        "sha512",
        (err, derivedHash) => {
          if (err) reject(err);
          else resolve(crypto.timingSafeEqual(hash, derivedHash));
        },
      );
    });
  }

  /**
   * Generate RSA key pair
   */
  generateKeyPair() {
    return crypto.generateKeyPairSync("rsa", {
      modulusLength: 4096,
      publicKeyEncoding: {
        type: "spki",
        format: "pem",
      },
      privateKeyEncoding: {
        type: "pkcs8",
        format: "pem",
        cipher: "aes-256-cbc",
        passphrase: process.env.KEY_PASSPHRASE || "top-secret",
      },
    });
  }

  /**
   * Encrypt with public key (RSA)
   */
  encryptWithPublicKey(data, publicKey) {
    return crypto.publicEncrypt(
      {
        key: publicKey,
        padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
        oaepHash: "sha256",
      },
      Buffer.from(data),
    );
  }

  /**
   * Decrypt with private key (RSA)
   */
  decryptWithPrivateKey(encrypted, privateKey) {
    return crypto.privateDecrypt(
      {
        key: privateKey,
        padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
        oaepHash: "sha256",
      },
      encrypted,
    );
  }
}

// Usage examples
async function main() {
  const encryptionService = new EncryptionService();

  // 1. Symmetric encryption
  const key = encryptionService.generateKey();
  const encrypted = encryptionService.encrypt("Secret message", key);
  console.log("Encrypted:", encrypted);

  const decrypted = encryptionService.decrypt(
    encrypted.encrypted,
    key,
    encrypted.iv,
    encrypted.tag,
  );
  console.log("Decrypted:", decrypted);

  // 2. Password-based encryption
  const { key: derivedKey, salt } =
    await encryptionService.deriveKey("myPassword");
  const passwordEncrypted = encryptionService.encrypt("Data", derivedKey);
  console.log("Password encrypted:", passwordEncrypted);

  // 3. Password hashing
  const hashedPassword =
    await encryptionService.hashPassword("userPassword123");
  const isValid = await encryptionService.verifyPassword(
    "userPassword123",
    hashedPassword,
  );
  console.log("Password valid:", isValid);

  // 4. RSA encryption
  const { publicKey, privateKey } = encryptionService.generateKeyPair();
  const rsaEncrypted = encryptionService.encryptWithPublicKey(
    "Secret",
    publicKey,
  );
  const rsaDecrypted = encryptionService.decryptWithPrivateKey(
    rsaEncrypted,
    privateKey,
  );
  console.log("RSA decrypted:", rsaDecrypted.toString());
}

main().catch(console.error);

module.exports = EncryptionService;

2. Python Cryptography Implementation

# encryption_service.py
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
import os
import base64
from typing import Tuple, Dict

class EncryptionService:
    def __init__(self):
        self.backend = default_backend()

    def generate_key(self) -> bytes:
        """Generate a random 256-bit key"""
        return os.urandom(32)

    def derive_key(self, password: str, salt: bytes = None) -> Tuple[bytes, bytes]:
        """Derive encryption key from password using PBKDF2"""
        if salt is None:
            salt = os.urandom(16)

        kdf = PBKDF2(
            algorithm=hashes.SHA256(),
            length=32,
            salt=salt,
            iterations=100000,
            backend=self.backend
        )

        key = kdf.derive(password.encode())
        return key, salt

    def encrypt_aes_gcm(self, plaintext: bytes, key: bytes) -> Dict[str, str]:
        """Encrypt data using AES-256-GCM"""
        iv = os.urandom(12)  # 96-bit IV for GCM

        cipher = Cipher(
            algorithms.AES(key),
            modes.GCM(iv),
            backend=self.backend
        )

        encryptor = cipher.encryptor()
        ciphertext = encryptor.update(plaintext) + encryptor.finalize()

        return {
            'ciphertext': base64.b64encode(ciphertext).decode(),
            'iv': base64.b64encode(iv).decode(),
            'tag': base64.b64encode(encryptor.tag).decode()
        }

    def decrypt_aes_gcm(self, ciphertext: str, key: bytes, iv: str, tag: str) -> bytes:
        """Decrypt data using AES-256-GCM"""
        cipher = Cipher(
            algorithms.AES(key),
            modes.GCM(
                base64.b64decode(iv),
                base64.b64decode(tag)
            ),
            backend=self.backend
        )

        decryptor = cipher.decryptor()
        plaintext = decryptor.update(base64.b64decode(ciphertext)) + decryptor.finalize()

        return plaintext

    def encrypt_file(self, input_path: str, output_path: str, key: bytes) -> None:
        """Encrypt file using AES-256-GCM"""
        with open(input_path, 'rb') as f:
            plaintext = f.read()

        result = self.encrypt_aes_gcm(plaintext, key)

        # Write IV + ciphertext + tag
        with open(output_path, 'wb') as f:
            f.write(base64.b64decode(result['iv']))
            f.write(base64.b64decode(result['ciphertext']))
            f.write(base64.b64decode(result['tag']))

    def decrypt_file(self, input_path: str, output_path: str, key: bytes) -> None:
        """Decrypt file using AES-256-GCM"""
        with open(input_path, 'rb') as f:
            data = f.read()

        iv = data[:12]
        tag = data[-16:]
        ciphertext = data[12:-16]

        cipher = Cipher(
            algorithms.AES(key),
            modes.GCM(iv, tag),
            backend=self.backend
        )

        decryptor = cipher.decryptor()
        plaintext = decryptor.update(ciphertext) + decryptor.finalize()

        with open(output_path, 'wb') as f:
            f.write(plaintext)

    def generate_rsa_keypair(self) -> Tuple[bytes, bytes]:
        """Generate RSA key pair"""
        private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=4096,
            backend=self.backend
        )

        private_pem = private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.BestAvailableEncryption(b'passphrase')
        )

        public_pem = private_key.public_key().public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo
        )

        return private_pem, public_pem

    def encrypt_rsa(self, plaintext: bytes, public_key_pem: bytes) -> bytes:
        """Encrypt with RSA public key"""
        public_key = serialization.load_pem_public_key(
            public_key_pem,
            backend=self.backend
        )

        ciphertext = public_key.encrypt(
            plaintext,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )

        return ciphertext

    def decrypt_rsa(self, ciphertext: bytes, private_key_pem: bytes, passphrase: bytes) -> bytes:
        """Decrypt with RSA private key"""
        private_key = serialization.load_pem_private_key(
            private_key_pem,
            password=passphrase,
            backend=self.backend
        )

        plaintext = private_key.decrypt(
            ciphertext,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )

        return plaintext

# Usage
if __name__ == '__main__':
    service = EncryptionService()

    # AES encryption
    key = service.generate_key()
    encrypted = service.encrypt_aes_gcm(b'Secret data', key)
    print(f"Encrypted: {encrypted['ciphertext']}")

    decrypted = service.decrypt_aes_gcm(
        encrypted['ciphertext'],
        key,
        encrypted['iv'],
        encrypted['tag']
    )
    print(f"Decrypted: {decrypted.decode()}")

    # Password-based encryption
    password = "mySecurePassword"
    key, salt = service.derive_key(password)
    print(f"Derived key: {base64.b64encode(key).decode()}")

    # RSA encryption
    private_key, public_key = service.generate_rsa_keypair()
    rsa_encrypted = service.encrypt_rsa(b'Secret message', public_key)
    rsa_decrypted = service.decrypt_rsa(rsa_encrypted, private_key, b'passphrase')
    print(f"RSA decrypted: {rsa_decrypted.decode()}")

3. Database Encryption (PostgreSQL)

-- Database-level encryption using pgcrypto

-- Enable pgcrypto extension
CREATE EXTENSION IF NOT EXISTS pgcrypto;

-- Create table with encrypted columns
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL,
    -- Encrypted sensitive data
    ssn BYTEA,
    credit_card BYTEA,
    created_at TIMESTAMP DEFAULT NOW()
);

-- Insert encrypted data
INSERT INTO users (email, ssn, credit_card)
VALUES (
    'user@example.com',
    pgp_sym_encrypt('123-45-6789', 'encryption-key'),
    pgp_sym_encrypt('4111-1111-1111-1111', 'encryption-key')
);

-- Query encrypted data
SELECT
    email,
    pgp_sym_decrypt(ssn, 'encryption-key') AS ssn,
    pgp_sym_decrypt(credit_card, 'encryption-key') AS credit_card
FROM users
WHERE email = 'user@example.com';

-- Create function for transparent encryption
CREATE OR REPLACE FUNCTION encrypt_sensitive_data()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.ssn IS NOT NULL THEN
        NEW.ssn := pgp_sym_encrypt(NEW.ssn::TEXT, current_setting('app.encryption_key'));
    END IF;

    IF NEW.credit_card IS NOT NULL THEN
        NEW.credit_card := pgp_sym_encrypt(NEW.credit_card::TEXT, current_setting('app.encryption_key'));
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Attach trigger
CREATE TRIGGER encrypt_before_insert
    BEFORE INSERT ON users
    FOR EACH ROW
    EXECUTE FUNCTION encrypt_sensitive_data();

4. TLS/SSL Configuration

// tls-server.js - HTTPS server with strong TLS
const https = require("https");
const fs = require("fs");

const tlsOptions = {
  key: fs.readFileSync("private-key.pem"),
  cert: fs.readFileSync("certificate.pem"),
  ca: fs.readFileSync("ca-cert.pem"), // Certificate authority

  // TLS version restrictions
  minVersion: "TLSv1.2",
  maxVersion: "TLSv1.3",

  // Strong cipher suites
  ciphers: [
    "TLS_AES_256_GCM_SHA384",
    "TLS_CHACHA20_POLY1305_SHA256",
    "TLS_AES_128_GCM_SHA256",
    "ECDHE-RSA-AES256-GCM-SHA384",
    "ECDHE-RSA-AES128-GCM-SHA256",
  ].join(":"),

  // Prefer server cipher order
  honorCipherOrder: true,

  // Require client certificate (mutual TLS)
  requestCert: true,
  rejectUnauthorized: true,
};

const server = https.createServer(tlsOptions, (req, res) => {
  // Verify client certificate
  const cert = req.socket.getPeerCertificate();

  if (req.client.authorized) {
    res.writeHead(200);
    res.end("Secure connection established");
  } else {
    res.writeHead(401);
    res.end("Unauthorized");
  }
});

server.listen(443, () => {
  console.log("Secure server running on port 443");
});

Best Practices

✅ DO

  • Use AES-256-GCM for symmetric encryption
  • Use RSA-4096 or ECC for asymmetric encryption
  • Implement proper key rotation
  • Use secure key storage (HSM, KMS)
  • Salt and hash passwords
  • Use TLS 1.2+ for transit encryption
  • Implement key derivation (PBKDF2, Argon2)
  • Use authenticated encryption

❌ DON'T

  • Roll your own crypto
  • Store keys in code
  • Use ECB mode
  • Use MD5 or SHA1
  • Reuse IVs/nonces
  • Use weak key lengths
  • Skip authentication tags

Encryption Standards

  • AES-256: Symmetric encryption
  • RSA-4096: Asymmetric encryption
  • ECDSA/EdDSA: Digital signatures
  • TLS 1.3: Transport security
  • PBKDF2/Argon2: Key derivation
  • HMAC-SHA256: Message authentication

Resources