# @hugo-fixit/encrypt
Post-build AES-256-GCM encryption tool for the [FixIt](https://github.com/hugo-fixit/FixIt) Hugo theme.
It is designed for HTML generated by FixIt content encryption templates and should be run after your site has already been built.
## Usage
> After building your Hugo site, run the encryption tool from your site root.
Recommended: install as a dev dependency and configure scripts:
```bash
npm install -D @hugo-fixit/encrypt
```
Then in your `package.json`:
```json
{
"scripts": {
"build": "hugo --gc --minify --logLevel info",
"postbuild": "fixit-encrypt && fixit-encrypt --verify"
}
}
```
You can also run it directly via npx:
```bash
npx @hugo-fixit/encrypt
```
Or install globally and run the CLI directly:
```bash
npm install -g @hugo-fixit/encrypt
fixit-encrypt
```
### Options
| Option | Description | Default |
| --------------- | -------------------------------------------------- | -------- |
| `--input
` | Input directory containing HTML files | `public` |
| `--dry-run` | Show which files would be modified without writing | `false` |
| `--verify` | Verify all encryption templates are encrypted | `false` |
| `-h, --help` | Show CLI usage help | |
### Examples
```bash
# Show CLI help
npx @hugo-fixit/encrypt --help
# Encrypt content in the default public/ directory
npx @hugo-fixit/encrypt
# Encrypt content in a custom directory
npx @hugo-fixit/encrypt --input dist
# Verify encryption without modifying files
npx @hugo-fixit/encrypt --verify
# Dry run to see which files would be changed
npx @hugo-fixit/encrypt --dry-run
```
## How It Works
1. Scans all `.html` files in the input directory
2. Finds `` elements (encryption placeholders)
3. Encrypts the plaintext content using AES-256-GCM with PBKDF2 key derivation
4. Replaces the `data-password` hash with a PBKDF2-protected version
5. Writes the encrypted payload back to the template element
### Security
- **Algorithm**: AES-256-GCM (authenticated encryption)
- **Key derivation**: PBKDF2 with 100,000 iterations and random 16-byte salt
- **Password verification**: PBKDF2-protected hash (not raw SHA-256)
- **Payload format**: `base64(salt).base64(iv).base64(ciphertext+tag)`
## Performance
The performance bottleneck is **PBKDF2 key derivation** (100,000 iterations), which takes approximately **~53ms per template**. This is CPU-bound cryptographic computation — file I/O is negligible in comparison.
Benchmark results (Node.js v22, Apple M-series):
| Files | Templates | Total Time | Per Template |
| ----- | --------- | ---------- | ------------ |
| 100 | 100 | ~6s | ~59ms |
| 500 | 500 | ~27s | ~53ms |
| 1000 | 1000 | ~53s | ~53ms |
The per-template cost is constant regardless of file count or content size, as PBKDF2 dominates the runtime.
## Other Implementations
The current implementation is in **Node.js (TypeScript)**. For environments where Node.js performance is a bottleneck, community-maintained implementations in other languages are welcome:
| Language | Status | Repository |
| -------- | --------- | ---------------- |
| Node.js | Available | hugo-fixit/FixIt |
| Python | Planned | — |
| Go | Planned | — |
| Rust | Planned | — |
If you have implemented `fixit-encrypt` in another language, please open a PR to add it to this list.
## License
MIT