Metadata-Version: 2.4
Name: encryptbox
Version: 1.0.0
Summary: Encrypt files with envelope encryption, key rotation, and audit logging — no server required
Author-email: JSLEEKR <93jslee@gmail.com>
License: MIT
Keywords: encryption,envelope-encryption,key-rotation,cli,security
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security :: Cryptography
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.1
Requires-Dist: cryptography>=41.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Dynamic: license-file

<div align="center">

# encryptbox

### Encrypt files with key rotation — no server required

[![Stars](https://img.shields.io/github/stars/JSLEEKR/encryptbox?style=for-the-badge)](https://github.com/JSLEEKR/encryptbox/stargazers)
[![License](https://img.shields.io/github/license/JSLEEKR/encryptbox?style=for-the-badge)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.10+-blue?style=for-the-badge&logo=python&logoColor=white)](https://python.org)
[![Tests](https://img.shields.io/badge/tests-157_passed-brightgreen?style=for-the-badge)](tests/)

<br/>

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

</div>

---

## 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

```bash
pip install encryptbox
```

Or from source:

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

### Requirements

- Python 3.10+
- [cryptography](https://cryptography.io/) (pyca/cryptography)
- [click](https://click.palletsprojects.com/) (CLI framework)

---

## Quick Start

### 1. Initialize

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

### 2. Generate a keypair

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

### 3. Encrypt a file

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

### 4. Decrypt it back

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

### 5. Rotate keys

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

### 6. Check the audit log

```bash
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

```bash
# 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:

```bash
# 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:

```bash
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:

```bash
# 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

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

### Running Tests

```bash
# 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](LICENSE) — JSLEEKR
