PTENES
MODULE 3.3

🔐 Encryption and Secret Protection

Fernet + PBKDF2, hardware UUID as the key, secure storage in ~/.intelecto/.secrets, and an immutable audit log.

6
Topics
75
Minutes
Advanced
Level
Technical
Type
1

🔑 Fernet — Symmetric Encryption

Fernet is the safest and simplest solution for encrypting data at rest in Python. AES-128-CBC for encryption, HMAC-SHA256 for authentication—you can’t decrypt without also verifying integrity.

📌 Why Fernet Is the Right Choice

Comparison with alternatives:

  • •Plain text: key visible in any text editor — unacceptable
  • •Base64: it's not encryption, just encoding—still exposed
  • •Pure AES: requires managing IV, padding, and operation mode—error-prone
  • •Fernet: one line of code, semantically secure, authenticated—ideal

💡 Practical Tip

Always use from cryptography.fernet import Fernet. Never implement your own encryption — the cryptography library has been audited by security experts.

2

🔗 PBKDF2 — Key Derivation

PBKDF2 transforms any value (such as the hardware UUID) into a robust cryptographic key. The many iterations make brute-force attacks computationally infeasible.

📌 PBKDF2 Parameters

Recommended settings for 2026:

  • •Hash: SHA-256 (the most secure standard available)
  • •Iterations: minimum 600.000 for use on modern hardware
  • •Salt: 32 random bytes, stored alongside the hash
  • •Length: 32 bytes (256 bits) for use as an AES-256 key
  • •Library: hashlib.pbkdf2_hmac() — native to Python

💡 Practical Tip

Use 600.000+ iterations (OWASP 2024 recommendation). It may seem high, but it takes ~0.3 seconds on modern hardware — acceptable for key unlock.

3

💻 Hardware UUID as Key

O Hardware UUID is unique to each machine and immutable throughout the hardware’s lifetime. Using it as material for PBKDF2 creates encryption tied to that specific machine.

📌 How to Get the Hardware UUID

Cross-platform method for obtaining a UUID:

  • •Linux: cat /sys/class/dmi/id/product_uuid ou dmidecode -s system-uuid
  • •macOS: ioreg -rd1 -c IOPlatformExpertDevice | grep UUID
  • •Windows: wmic csproduct get UUID
  • •Fallback: generate a deterministic UUID based on multiple hardware identifiers

💡 Practical Tip

Test the UUID before encrypting important data. If the UUID changes after a BIOS update or hardware change, your secrets will be inaccessible without a backup of the original key.

4

📁 Storage in ~/.intelecto/.secrets

The file ~/.intelecto/.secrets is where the encrypted keys live. Simple JSON format, restrictive permissions, and a location hidden by convention.

📌 Structure of .secrets

Secrets file format:

  • •{"OPENROUTER_API_KEY": "gAAA...token_fernet..."}
  • •Each key: secret name
  • •Each value: encrypted Fernet token (starts with gAAA)
  • •chmod 600: only the owner can read and write
  • •.gitignore: ~/.intelecto/ must be in the global gitignore

💡 Practical Tip

Configure a global gitignore (~/.gitignore_global) that excludes ~/.intelecto/ from any repository. An accidental git add . must not leak your secrets.

5

📋 audit.log — Immutable Record

O audit.log is INTELECTO’s forensic memory. Every significant action is recorded in append-only form—the log only grows; no lines are ever deleted or changed.

📌 Audit Log Format

Each log line is structured JSON:

  • •{"ts": "2026-04-28T10:30:00Z", "user": "telegram:123", "action": "exec", "tool": "shell", "cmd": "ls -la", "result": "ok"}
  • •ts: ISO 8601 timestamp with timezone
  • •user: channel and user identifier
  • •action: action type (read, exec, deny, error)
  • •tool: which tool was called (if applicable)
  • •result: ok, denied, error

💡 Practical Tip

Configure logrotate for audit.log with the nocreate option — it preserves the original file. Compress old logs, but never delete them. They’re forensic evidence.

6

🔄 Key Rotation

API keys should be rotated periodically. secrets.py supports multiple keys with precedence to allow rotation without downtime.

📌 Rotation Process

Rotation without service interruption:

  • •1. Generate a new Fernet key
  • •2. Re-encrypt secrets with the new key
  • •3. Configure: current_key = new, fallback_key = old
  • •4. Test that the service works with the new key
  • •5. After 24h of stability: remove fallback_key
  • •6. Record the rotation in audit.log

💡 Practical Tip

Schedule automatic key rotation with cron: once per quarter for personal use, monthly for use with sensitive data. INTELECTO has the rotate_keys.py script ready.

✅ Module 3.3 Summary

✓
Fernet — Symmetric Encryption — AES-128-CBC + HMAC-SHA256 in a simple API — the right choice for secrets
✓
PBKDF2 — Key Derivation — 600k+ iterations, random salt, SHA-256 — robust key derivation from the hardware UUID
✓
Hardware UUID as a Key — Unique UUID per machine + PBKDF2 = encryption that works only on the original hardware
✓
Storage in ~/.intelecto/.secrets — JSON with Fernet tokens, chmod 600, hidden location, and outside any git repo
✓
audit.log — Immutable Record — Structured, append-only JSON with timestamp, user, action, and result — immutable forensic evidence
✓
Key Rotation — Multi-key precedence enables zero-downtime rotation in 6 steps

Next:

3.4 — IronClaw Zero-Trust