Skip to main content

Encrypt files with envelope encryption, key rotation, and audit logging — no server required

Project description

encryptbox

Encrypt files with key rotation — no server required

Stars License Python Tests


Envelope encryption + key rotation + audit log in a single CLI


Why This Exists

You need to encrypt config files, backups, or secrets. Your options are:

  • age — simple, but no key rotation. Rotate the key = re-encrypt everything.
  • AWS KMS / HashiCorp Vault — powerful, but you need infrastructure, IAM policies, network access.
  • GPG — works, but the UX is from 1999 and key management is painful.

encryptbox gives you envelope encryption (the same pattern AWS KMS uses) in a local CLI. Rotate your master key without touching encrypted files. Every operation gets logged in a tamper-evident audit trail. No server, no cloud, no subscriptions.


How It Works

Envelope Encryption

┌─────────────────────────────────────────────────┐
│ Your File                                       │
│                                                 │
│  plaintext ──► AES-256-GCM ──► ciphertext       │
│                    ▲                             │
│                    │                             │
│              data key (random)                   │
│                    │                             │
│              X25519 wrap ──► wrapped data key    │
│                    ▲                             │
│                    │                             │
│              master key (your keypair)           │
└─────────────────────────────────────────────────┘
  1. A random data key encrypts your file with AES-256-GCM
  2. The data key is wrapped (encrypted) with your X25519 public key
  3. Both the wrapped key and ciphertext go into a .ebox file

To rotate: unwrap the data key with the old master, re-wrap with the new master. The encrypted file data stays untouched.

Audit Chain

Every operation (encrypt, decrypt, rotate, keygen) is logged with an HMAC chain:

entry[0].hmac ──► entry[1].prev_hmac ──► entry[1].hmac ──► entry[2].prev_hmac ──► ...

Tamper with any entry and the chain breaks. Delete an entry and the chain breaks. The verification is O(n) and deterministic.


Installation

pip install encryptbox

Or from source:

git clone https://github.com/JSLEEKR/encryptbox.git
cd encryptbox
pip install -e ".[dev]"

Requirements


Quick Start

1. Initialize

encryptbox init
# [OK] Keystore initialized
#   Keystore created at: .encryptbox
#   Run 'encryptbox keygen' to generate your first keypair.

2. Generate a keypair

encryptbox keygen --label "my-laptop"
# [OK] Generated key: a1b2c3d4e5f6a7b8
#   Label: my-laptop
#   Key ID: a1b2c3d4e5f6a7b8

3. Encrypt a file

encryptbox encrypt secrets.env
# [OK] Encrypted: secrets.env
#   Output: secrets.env.ebox

4. Decrypt it back

encryptbox decrypt secrets.env.ebox
# [OK] Decrypted: secrets.env.ebox
#   Output: secrets.env

5. Rotate keys

encryptbox rotate
# [OK] Key rotated
#   Old key: a1b2c3d4e5f6a7b8 (deactivated)
#   New key: f8e7d6c5b4a39281 (active)
#   Files re-wrapped: 3

6. Check the audit log

encryptbox audit
# [2026-03-28 14:00:01]  INIT  (by alice)
# [2026-03-28 14:00:02]  KEYGEN  key=a1b2c3d4e5f6a7b8  (by alice)
# [2026-03-28 14:00:05]  ENCRYPT  key=a1b2c3d4e5f6a7b8  secrets.env  (by alice)
# [2026-03-28 14:01:00]  ROTATE  key=f8e7d6c5b4a39281  (by alice)

CLI Reference

Core Commands

Command Description
encryptbox init Initialize the keystore in the current directory
encryptbox keygen Generate a new X25519 keypair
encryptbox encrypt <file> Encrypt a file with envelope encryption
encryptbox decrypt <file> Decrypt a .ebox file
encryptbox rotate Rotate master key and re-wrap all .ebox files
encryptbox audit Show the audit log
encryptbox status Show keystore status and health

Batch Commands

Command Description
encryptbox encrypt-dir <dir> Encrypt all files in a directory
encryptbox decrypt-dir <dir> Decrypt all .ebox files in a directory

Key Management

Command Description
encryptbox export-key Export a public key as hex
encryptbox import-key <hex> --id <name> Import a public key

Options

# Encrypt with custom output path
encryptbox encrypt secret.txt -o /backup/secret.enc

# Encrypt for multiple recipients
encryptbox encrypt secret.txt -k key1 -k key2

# Remove original after encryption
encryptbox encrypt secret.txt --remove

# Encrypt only .env files in a directory
encryptbox encrypt-dir ./configs -p "*.env"

# Verify audit log integrity
encryptbox audit --verify

# Show last 5 audit entries
encryptbox audit --last 5

# Output audit as JSON
encryptbox audit --json-output

# Use a specific key for decryption
encryptbox decrypt secret.txt.ebox -k a1b2c3d4e5f6a7b8

# Specify project root
encryptbox --root /path/to/project encrypt file.txt

Multi-Recipient Encryption

Encrypt a file so multiple people can decrypt it:

# Alice generates a key and shares her public key
encryptbox keygen --label alice
encryptbox export-key
# Public key: 7a3f...

# Bob imports Alice's public key
encryptbox import-key 7a3f... --id alice-pub

# Bob encrypts for both himself and Alice
encryptbox encrypt shared-secret.txt -k bob-key-id -k alice-pub

Both Alice and Bob can decrypt the file independently with their own private keys.


Key Rotation

Key rotation re-wraps data keys without re-encrypting file data:

encryptbox rotate

What happens:

  1. A new X25519 keypair is generated
  2. All .ebox files in the project tree are found
  3. Each file's data key is unwrapped with the old key and re-wrapped with the new key
  4. The old key is marked as inactive
  5. The operation is logged in the audit trail

The encrypted data itself is never touched during rotation. This means:

  • Rotation is fast (no I/O proportional to file sizes)
  • File integrity is preserved
  • You can verify by decrypting after rotation

Audit Log

Every operation is logged with a tamper-evident HMAC chain:

# View all entries
encryptbox audit

# Verify chain integrity
encryptbox audit --verify
# [OK] All 42 entries verified

# Export as JSON for analysis
encryptbox audit --json-output > audit.json

What Gets Logged

Field Description
timestamp Unix timestamp
action init, keygen, encrypt, decrypt, rotate
key_id The key used
file_path The file involved
file_hash SHA-256 of the file
user System username
prev_hmac HMAC of the previous entry
entry_hmac HMAC of this entry

Tamper Detection

The audit log uses HMAC-SHA256 chaining. Each entry's HMAC includes the previous entry's HMAC, forming a hash chain. If any entry is modified, deleted, or inserted, audit --verify will detect it.


File Format

Encrypted files use the .ebox binary format:

EBOX (4 bytes)           — magic bytes
VERSION (1 byte)         — format version (currently 1)
NUM_RECIPIENTS (2 bytes) — number of recipient key entries

For each recipient:
  KEY_ID_LEN (1 byte)    — length of key ID
  KEY_ID (variable)      — key ID string
  WRAPPED_LEN (4 bytes)  — length of wrapped key data
  WRAPPED_KEY (variable) — ephemeral public key + encrypted data key

ORIGINAL_HASH (32 bytes) — SHA-256 of original plaintext
ENCRYPTED_DATA (variable) — AES-256-GCM nonce + ciphertext

Architecture

encryptbox/
├── crypto.py      # AES-256-GCM encryption, X25519 key wrapping
├── keystore.py    # On-disk key management, metadata
├── envelope.py    # Envelope encryption, .ebox format, key rotation
├── audit.py       # HMAC-chained append-only audit log
├── operations.py  # High-level orchestration (encrypt/decrypt/rotate)
└── cli.py         # Click CLI interface

Module Responsibilities

Module Responsibility
crypto Low-level crypto: AES-256-GCM encrypt/decrypt, X25519 key wrap/unwrap, HKDF key derivation
keystore Key lifecycle: generate, store, load, list, deactivate, import/export keypairs
envelope Envelope encryption: combine crypto + multi-recipient + serialization into .ebox format
audit Append-only log with HMAC chain for tamper detection
operations Orchestrate all modules: file I/O, batch ops, rotation, status
cli User-facing CLI commands via Click

Security Properties

  • AES-256-GCM — authenticated encryption with 96-bit nonces (CSPRNG)
  • X25519 — Curve25519 key exchange for key wrapping
  • HKDF-SHA256 — key derivation from shared secrets
  • CSPRNG — all random bytes from os.urandom
  • No custom crypto — everything from pyca/cryptography

Development

git clone https://github.com/JSLEEKR/encryptbox.git
cd encryptbox
pip install -e ".[dev]"
pytest

Running Tests

# All tests
pytest

# With verbose output
pytest -v

# With coverage
pytest --cov=encryptbox --cov-report=term-missing

# Specific module
pytest tests/test_crypto.py

Test Coverage

Module Tests Coverage
crypto 27 encrypt/decrypt, key wrapping, serialization, edge cases
keystore 28 init, keygen, retrieval, metadata, import/export
envelope 17 envelope encrypt/decrypt, multi-recipient, rotation, serialization
audit 22 logging, chain verification, tamper detection, persistence
operations 33 file encrypt/decrypt, rotation, batch ops, status, audit integration
cli 20 all CLI commands end-to-end
Total 157

Comparison

Feature encryptbox age GPG AWS KMS
Envelope encryption Yes No No Yes
Key rotation (no re-encrypt) Yes No No Yes
Audit log Yes No No CloudTrail
Multi-recipient Yes Yes Yes Via policies
No server required Yes Yes Yes No
Tamper-evident logging Yes No No No
Binary format .ebox .age .gpg N/A
CLI UX Modern (Click) Good Legacy AWS CLI

Security Considerations

  • Key storage: Private keys are stored as raw bytes on disk. Use appropriate file permissions.
  • Memory: Data keys exist in memory during encrypt/decrypt operations.
  • Not a replacement for KMS: For production secrets management at scale, use a proper KMS. encryptbox is for developer workflows, local encryption, and backup protection.
  • Audit log secret: The HMAC secret for the audit chain is stored in .encryptbox/audit.secret. Protect this file.

License

MIT — JSLEEKR

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

encryptbox-1.0.0.tar.gz (33.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

encryptbox-1.0.0-py3-none-any.whl (21.0 kB view details)

Uploaded Python 3

File details

Details for the file encryptbox-1.0.0.tar.gz.

File metadata

  • Download URL: encryptbox-1.0.0.tar.gz
  • Upload date:
  • Size: 33.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for encryptbox-1.0.0.tar.gz
Algorithm Hash digest
SHA256 0c655fcb11e9216a974be784180456bbf7f7c79e7b383449220fbf6d266faaa8
MD5 f9ce4d27042258b2b9361d9e65e2be47
BLAKE2b-256 7516cb5663b5aeca19b09244b1326cbee80165d9efee4fa4afc768d55c370dea

See more details on using hashes here.

File details

Details for the file encryptbox-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: encryptbox-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 21.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for encryptbox-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 96e68d220e99b6e673d442061c4c6d8724444409bad0369504f4fee0fae2325d
MD5 43384c7280a0e0e2b84a32afc86a4fbc
BLAKE2b-256 4af34ea2b8465dc9fd3222339d25e07a73c27027be86da9e5bde250423000650

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page