mirror of
https://github.com/hugo-fixit/FixIt.git
synced 2026-08-24 07:18:57 +00:00
refactor(encrypt): rename post-encrypt to encrypt
- Rename package from @hugo-fixit/post-encrypt to @hugo-fixit/encrypt - Rename bin from post-encrypt to fixit-encrypt - Update all i18n translations (16 files) to use npx @hugo-fixit/encrypt - Update CI workflow, publish script, code comments, and docs - Rewrite README with performance benchmarks and other implementations
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
name: Publish post-encrypt
|
name: Publish @hugo-fixit/encrypt
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- 'post-encrypt-v*.*.*'
|
- 'encrypt-v*.*.*'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -11,7 +11,7 @@ permissions:
|
|||||||
id-token: write
|
id-token: write
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: publish-post-encrypt-${{ github.ref }}
|
group: publish-encrypt-${{ github.ref }}
|
||||||
cancel-in-progress: false
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -36,8 +36,8 @@ jobs:
|
|||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build package
|
- name: Build package
|
||||||
run: pnpm -F post-encrypt build
|
run: pnpm -F encrypt build
|
||||||
|
|
||||||
- name: Publish package to npm
|
- name: Publish package to npm
|
||||||
working-directory: packages/post-encrypt
|
working-directory: packages/encrypt
|
||||||
run: npm publish --access public --provenance
|
run: npm publish --access public --provenance
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
*
|
*
|
||||||
* Payload formats:
|
* Payload formats:
|
||||||
* - v2 (current): PBKDF2(SHA-256(password), 100k iterations) → base64(salt).base64(iv).base64(ciphertext+tag)
|
* - v2 (current): PBKDF2(SHA-256(password), 100k iterations) → base64(salt).base64(iv).base64(ciphertext+tag)
|
||||||
* - Password verification: data-password stores PBKDF2(SHA-256(password), data-verify-salt) when post-encrypted
|
* - Password verification: data-password stores PBKDF2(SHA-256(password), data-verify-salt) when fixit-encrypted
|
||||||
*/
|
*/
|
||||||
import { eventBus } from '../core/event-bus'
|
import { eventBus } from '../core/event-bus'
|
||||||
import { flashTooltip } from '../utils'
|
import { flashTooltip } from '../utils'
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ password = "Passwort"
|
|||||||
enterBtn = "Eintreten"
|
enterBtn = "Eintreten"
|
||||||
encryptyAgain = "Erneut verschlüsseln"
|
encryptyAgain = "Erneut verschlüsseln"
|
||||||
encryptionWarning = "Inhaltsverschlüsselung erkannt, aber sie sind noch im Klartext!"
|
encryptionWarning = "Inhaltsverschlüsselung erkannt, aber sie sind noch im Klartext!"
|
||||||
encryptionCommand = "Führen Sie `npx @hugo-fixit/post-encrypt` nach dem Build aus, um sie tatsächlich zu verschlüsseln."
|
encryptionCommand = "Führen Sie `npx @hugo-fixit/encrypt` nach dem Build aus, um sie tatsächlich zu verschlüsseln."
|
||||||
relatedContent = "Ähnliche Inhalte"
|
relatedContent = "Ähnliche Inhalte"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ password = "Password"
|
|||||||
enterBtn = "Enter"
|
enterBtn = "Enter"
|
||||||
encryptyAgain = "Encrypt again"
|
encryptyAgain = "Encrypt again"
|
||||||
encryptionWarning = "Content encryption detected, but they are still in plaintext!"
|
encryptionWarning = "Content encryption detected, but they are still in plaintext!"
|
||||||
encryptionCommand = "Run `npx @hugo-fixit/post-encrypt` after building to actually encrypt them."
|
encryptionCommand = "Run `npx @hugo-fixit/encrypt` after building to actually encrypt them."
|
||||||
relatedContent = "Related Content"
|
relatedContent = "Related Content"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ password = "Contraseña"
|
|||||||
enterBtn = "Entrar"
|
enterBtn = "Entrar"
|
||||||
encryptyAgain = "Encriptar de nuevo"
|
encryptyAgain = "Encriptar de nuevo"
|
||||||
encryptionWarning = "¡Se detectó cifrado de contenido, pero aún están en texto plano!"
|
encryptionWarning = "¡Se detectó cifrado de contenido, pero aún están en texto plano!"
|
||||||
encryptionCommand = "Ejecute `npx @hugo-fixit/post-encrypt` después de la compilación para cifrarlos realmente."
|
encryptionCommand = "Ejecute `npx @hugo-fixit/encrypt` después de la compilación para cifrarlos realmente."
|
||||||
relatedContent = "Contenido relacionado"
|
relatedContent = "Contenido relacionado"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ password = "Mot de passe"
|
|||||||
enterBtn = "Entrer"
|
enterBtn = "Entrer"
|
||||||
encryptyAgain = "Chiffrer à nouveau"
|
encryptyAgain = "Chiffrer à nouveau"
|
||||||
encryptionWarning = "Chiffrement de contenu détecté, mais ils sont toujours en texte clair !"
|
encryptionWarning = "Chiffrement de contenu détecté, mais ils sont toujours en texte clair !"
|
||||||
encryptionCommand = "Exécutez `npx @hugo-fixit/post-encrypt` après la compilation pour les chiffrer réellement."
|
encryptionCommand = "Exécutez `npx @hugo-fixit/encrypt` après la compilation pour les chiffrer réellement."
|
||||||
relatedContent = "Contenu lié"
|
relatedContent = "Contenu lié"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -147,7 +147,7 @@ password = "पासवर्ड"
|
|||||||
enterBtn = "दर्ज करें"
|
enterBtn = "दर्ज करें"
|
||||||
encryptyAgain = "फिर से एन्क्रिप्ट करें"
|
encryptyAgain = "फिर से एन्क्रिप्ट करें"
|
||||||
encryptionWarning = "सामग्री एन्क्रिप्शन का पता चला, लेकिन वे अभी भी सादे पाठ में हैं!"
|
encryptionWarning = "सामग्री एन्क्रिप्शन का पता चला, लेकिन वे अभी भी सादे पाठ में हैं!"
|
||||||
encryptionCommand = "उन्हें वास्तव में एन्क्रिप्ट करने के लिए बिल्ड के बाद `npx @hugo-fixit/post-encrypt` चलाएं।"
|
encryptionCommand = "उन्हें वास्तव में एन्क्रिप्ट करने के लिए बिल्ड के बाद `npx @hugo-fixit/encrypt` चलाएं।"
|
||||||
relatedContent = "संबंधित सामग्री"
|
relatedContent = "संबंधित सामग्री"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ password = "Password"
|
|||||||
enterBtn = "Entra"
|
enterBtn = "Entra"
|
||||||
encryptyAgain = "Crittografa di nuovo"
|
encryptyAgain = "Crittografa di nuovo"
|
||||||
encryptionWarning = "Rilevata crittografia dei contenuti, ma sono ancora in testo in chiaro!"
|
encryptionWarning = "Rilevata crittografia dei contenuti, ma sono ancora in testo in chiaro!"
|
||||||
encryptionCommand = "Eseguire `npx @hugo-fixit/post-encrypt` dopo la compilazione per crittograffarli effettivamente."
|
encryptionCommand = "Eseguire `npx @hugo-fixit/encrypt` dopo la compilazione per crittograffarli effettivamente."
|
||||||
relatedContent = "Contenuti correlati"
|
relatedContent = "Contenuti correlati"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -144,7 +144,7 @@ password = "パスワード"
|
|||||||
enterBtn = "入る"
|
enterBtn = "入る"
|
||||||
encryptyAgain = "再度暗号化"
|
encryptyAgain = "再度暗号化"
|
||||||
encryptionWarning = "コンテンツの暗号化が検出されましたが、まだ平文です!"
|
encryptionWarning = "コンテンツの暗号化が検出されましたが、まだ平文です!"
|
||||||
encryptionCommand = "実際に暗号化するには、ビルド後に `npx @hugo-fixit/post-encrypt` を実行してください。"
|
encryptionCommand = "実際に暗号化するには、ビルド後に `npx @hugo-fixit/encrypt` を実行してください。"
|
||||||
relatedContent = "関連コンテンツ"
|
relatedContent = "関連コンテンツ"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -144,7 +144,7 @@ password = "비밀번호"
|
|||||||
enterBtn = "입장"
|
enterBtn = "입장"
|
||||||
encryptyAgain = "다시 암호화"
|
encryptyAgain = "다시 암호화"
|
||||||
encryptionWarning = "콘텐츠 암호화가 감지되었지만 여전히 평문입니다!"
|
encryptionWarning = "콘텐츠 암호화가 감지되었지만 여전히 평문입니다!"
|
||||||
encryptionCommand = "실제로 암호화하려면 빌드 후 `npx @hugo-fixit/post-encrypt`를 실행하세요."
|
encryptionCommand = "실제로 암호화하려면 빌드 후 `npx @hugo-fixit/encrypt`를 실행하세요."
|
||||||
relatedContent = "관련 콘텐츠"
|
relatedContent = "관련 콘텐츠"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ password = "Hasło"
|
|||||||
enterBtn = "Wejdź"
|
enterBtn = "Wejdź"
|
||||||
encryptyAgain = "Zaszyfruj ponownie"
|
encryptyAgain = "Zaszyfruj ponownie"
|
||||||
encryptionWarning = "Wykryto szyfrowanie treści, ale nadal są w postaci zwykłego tekstu!"
|
encryptionWarning = "Wykryto szyfrowanie treści, ale nadal są w postaci zwykłego tekstu!"
|
||||||
encryptionCommand = "Uruchom `npx @hugo-fixit/post-encrypt` po kompilacji, aby je faktycznie zaszyfrować."
|
encryptionCommand = "Uruchom `npx @hugo-fixit/encrypt` po kompilacji, aby je faktycznie zaszyfrować."
|
||||||
relatedContent = "Powiązane treści"
|
relatedContent = "Powiązane treści"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -147,7 +147,7 @@ password = "Senha"
|
|||||||
enterBtn = "Entrar"
|
enterBtn = "Entrar"
|
||||||
encryptyAgain = "Encripte novamente"
|
encryptyAgain = "Encripte novamente"
|
||||||
encryptionWarning = "Criptografia de conteúdo detectada, mas ainda estão em texto plano!"
|
encryptionWarning = "Criptografia de conteúdo detectada, mas ainda estão em texto plano!"
|
||||||
encryptionCommand = "Execute `npx @hugo-fixit/post-encrypt` após a compilação para realmente criptografá-los."
|
encryptionCommand = "Execute `npx @hugo-fixit/encrypt` após a compilação para realmente criptografá-los."
|
||||||
relatedContent = "Conteúdo relacionado"
|
relatedContent = "Conteúdo relacionado"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ password = "Parolă"
|
|||||||
enterBtn = "Intră"
|
enterBtn = "Intră"
|
||||||
encryptyAgain = "Criptează din nou"
|
encryptyAgain = "Criptează din nou"
|
||||||
encryptionWarning = "Criptarea conținutului a fost detectată, dar sunt încă în text clar!"
|
encryptionWarning = "Criptarea conținutului a fost detectată, dar sunt încă în text clar!"
|
||||||
encryptionCommand = "Rulați `npx @hugo-fixit/post-encrypt` după compilare pentru a le cripta efectiv."
|
encryptionCommand = "Rulați `npx @hugo-fixit/encrypt` după compilare pentru a le cripta efectiv."
|
||||||
relatedContent = "Conținut înrudit"
|
relatedContent = "Conținut înrudit"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ password = "арготизм"
|
|||||||
enterBtn = "Войти"
|
enterBtn = "Войти"
|
||||||
encryptyAgain = "Зашифровать снова"
|
encryptyAgain = "Зашифровать снова"
|
||||||
encryptionWarning = "Обнаружено шифрование контента, но он всё ещё в открытом виде!"
|
encryptionWarning = "Обнаружено шифрование контента, но он всё ещё в открытом виде!"
|
||||||
encryptionCommand = "Запустите `npx @hugo-fixit/post-encrypt` после сборки, чтобы фактически зашифровать их."
|
encryptionCommand = "Запустите `npx @hugo-fixit/encrypt` после сборки, чтобы фактически зашифровать их."
|
||||||
relatedContent = "Связанный контент"
|
relatedContent = "Связанный контент"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ password = "Паролица"
|
|||||||
enterBtn = "Унеси"
|
enterBtn = "Унеси"
|
||||||
encryptyAgain = "Поново шифруј"
|
encryptyAgain = "Поново шифруј"
|
||||||
encryptionWarning = "Детектовано је шифровање садржаја, али су и даље у обичном тексту!"
|
encryptionWarning = "Детектовано је шифровање садржаја, али су и даље у обичном тексту!"
|
||||||
encryptionCommand = "Покрените `npx @hugo-fixit/post-encrypt` након изградње да бисте их заиста шифровали."
|
encryptionCommand = "Покрените `npx @hugo-fixit/encrypt` након изградње да бисте их заиста шифровали."
|
||||||
relatedContent = "Повезани садржај"
|
relatedContent = "Повезани садржај"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -145,7 +145,7 @@ password = "Mật khẩu"
|
|||||||
enterBtn = "Nhập"
|
enterBtn = "Nhập"
|
||||||
encryptyAgain = "Mã hóa lại"
|
encryptyAgain = "Mã hóa lại"
|
||||||
encryptionWarning = "Phát hiện mã hóa nội dung, nhưng chúng vẫn ở dạng văn bản thuần!"
|
encryptionWarning = "Phát hiện mã hóa nội dung, nhưng chúng vẫn ở dạng văn bản thuần!"
|
||||||
encryptionCommand = "Chạy `npx @hugo-fixit/post-encrypt` sau khi build để thực sự mã hóa chúng."
|
encryptionCommand = "Chạy `npx @hugo-fixit/encrypt` sau khi build để thực sự mã hóa chúng."
|
||||||
relatedContent = "Nội dung liên quan"
|
relatedContent = "Nội dung liên quan"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -144,7 +144,7 @@ password = "密码"
|
|||||||
enterBtn = "进入"
|
enterBtn = "进入"
|
||||||
encryptyAgain = "重新加密"
|
encryptyAgain = "重新加密"
|
||||||
encryptionWarning = "检测到内容加密,但仍为明文状态!"
|
encryptionWarning = "检测到内容加密,但仍为明文状态!"
|
||||||
encryptionCommand = "请在构建后执行 `npx @hugo-fixit/post-encrypt` 以实际加密内容。"
|
encryptionCommand = "请在构建后执行 `npx @hugo-fixit/encrypt` 以实际加密内容。"
|
||||||
relatedContent = "相关内容"
|
relatedContent = "相关内容"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
+1
-1
@@ -144,7 +144,7 @@ password = "密碼"
|
|||||||
enterBtn = "進入"
|
enterBtn = "進入"
|
||||||
encryptyAgain = "重新加密"
|
encryptyAgain = "重新加密"
|
||||||
encryptionWarning = "偵測到內容加密,但仍為明文狀態!"
|
encryptionWarning = "偵測到內容加密,但仍為明文狀態!"
|
||||||
encryptionCommand = "請在建構後執行 `npx @hugo-fixit/post-encrypt` 以實際加密內容。"
|
encryptionCommand = "請在建構後執行 `npx @hugo-fixit/encrypt` 以實際加密內容。"
|
||||||
relatedContent = "相關內容"
|
relatedContent = "相關內容"
|
||||||
|
|
||||||
[single.includedIn]
|
[single.includedIn]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{{- hugo.Store.Set "version" "v1.0.0-mrpajmty" -}}
|
{{- hugo.Store.Set "version" "v1.0.0-mrrceo88" -}}
|
||||||
{{- .Store.Set "this" dict -}}
|
{{- .Store.Set "this" dict -}}
|
||||||
|
|
||||||
{{- partial "init/detection-env.html" . -}}
|
{{- partial "init/detection-env.html" . -}}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="details-content toc-content" id="toc-content-static"></div>
|
<div class="details-content toc-content" id="toc-content-static"></div>
|
||||||
</div>
|
</div>
|
||||||
{{- /* TOC source (copied to containers by initToc, encrypted by post-encrypt when password is set) */ -}}
|
{{- /* TOC source (copied to containers by initToc, encrypted by fixit-encrypt when password is set) */ -}}
|
||||||
<template data-toc{{ with .Params.password }} data-password="{{ sha256 . }}"{{ end }}>{{ $tableOfContents }}</template>
|
<template data-toc{{ with .Params.password }} data-password="{{ sha256 . }}"{{ end }}>{{ $tableOfContents }}</template>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@
|
|||||||
"build:demo": "pnpm -F demo build",
|
"build:demo": "pnpm -F demo build",
|
||||||
"build:test": "pnpm -F test build",
|
"build:test": "pnpm -F test build",
|
||||||
"build": "concurrently 'pnpm build:demo' 'pnpm build:test' && pnpm -F integration start && pnpm encrypt && pnpm encrypt --verify",
|
"build": "concurrently 'pnpm build:demo' 'pnpm build:test' && pnpm -F integration start && pnpm encrypt && pnpm encrypt --verify",
|
||||||
"encrypt": "pnpm -F post-encrypt start",
|
"encrypt": "pnpm -F encrypt start",
|
||||||
"clean": "rm -rf public resources/_gen apps/*/public apps/*/resources/_gen",
|
"clean": "rm -rf public resources/_gen apps/*/public apps/*/resources/_gen",
|
||||||
"preview": "serve public",
|
"preview": "serve public",
|
||||||
"lint": "eslint --cache .",
|
"lint": "eslint --cache .",
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
# @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 <dir>` | 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 `<template data-password="...">` 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
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "@hugo-fixit/post-encrypt",
|
"name": "@hugo-fixit/encrypt",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"description": "Post-build AES-256-GCM encryption tool for the FixIt Hugo theme",
|
"description": "Post-build AES-256-GCM encryption tool for the FixIt Hugo theme",
|
||||||
"author": "Lruihao",
|
"author": "Lruihao",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://github.com/hugo-fixit/FixIt/tree/main/packages/post-encrypt#readme",
|
"homepage": "https://github.com/hugo-fixit/FixIt/tree/main/packages/encrypt#readme",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/hugo-fixit/FixIt.git",
|
"url": "git+https://github.com/hugo-fixit/FixIt.git",
|
||||||
"directory": "packages/post-encrypt"
|
"directory": "packages/encrypt"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/hugo-fixit/FixIt/issues"
|
"url": "https://github.com/hugo-fixit/FixIt/issues"
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
],
|
],
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
"post-encrypt": "./dist/index.js"
|
"fixit-encrypt": "./dist/index.js"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
@@ -23,7 +23,7 @@ bump="$1"
|
|||||||
|
|
||||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
repo_root="$(cd "${script_dir}/../.." && pwd)"
|
repo_root="$(cd "${script_dir}/../.." && pwd)"
|
||||||
package_json_rel="packages/post-encrypt/package.json"
|
package_json_rel="packages/encrypt/package.json"
|
||||||
package_json_abs="${repo_root}/${package_json_rel}"
|
package_json_abs="${repo_root}/${package_json_rel}"
|
||||||
|
|
||||||
if [[ ! -f "${package_json_abs}" ]]; then
|
if [[ ! -f "${package_json_abs}" ]]; then
|
||||||
@@ -39,9 +39,9 @@ fi
|
|||||||
npm --prefix "${script_dir}" version "${bump}" --no-git-tag-version > /dev/null
|
npm --prefix "${script_dir}" version "${bump}" --no-git-tag-version > /dev/null
|
||||||
version="$(node -p "require('${package_json_abs}').version")"
|
version="$(node -p "require('${package_json_abs}').version")"
|
||||||
|
|
||||||
tag="post-encrypt-v${version}"
|
tag="encrypt-v${version}"
|
||||||
commit_msg="chore(release): post-encrypt ${version}"
|
commit_msg="chore(release): encrypt ${version}"
|
||||||
tag_msg="release: @hugo-fixit/post-encrypt ${version}"
|
tag_msg="release: @hugo-fixit/encrypt ${version}"
|
||||||
|
|
||||||
if git -C "${repo_root}" rev-parse -q --verify "refs/tags/${tag}" > /dev/null; then
|
if git -C "${repo_root}" rev-parse -q --verify "refs/tags/${tag}" > /dev/null; then
|
||||||
echo "Tag already exists: ${tag}" >&2
|
echo "Tag already exists: ${tag}" >&2
|
||||||
@@ -52,7 +52,7 @@ git -C "${repo_root}" add "${package_json_rel}"
|
|||||||
git -C "${repo_root}" commit -m "${commit_msg}"
|
git -C "${repo_root}" commit -m "${commit_msg}"
|
||||||
git -C "${repo_root}" tag -a "${tag}" -m "${tag_msg}"
|
git -C "${repo_root}" tag -a "${tag}" -m "${tag_msg}"
|
||||||
|
|
||||||
echo "Released @hugo-fixit/post-encrypt ${version}"
|
echo "Released @hugo-fixit/encrypt ${version}"
|
||||||
echo "Created commit: ${commit_msg}"
|
echo "Created commit: ${commit_msg}"
|
||||||
echo "Created tag: ${tag}"
|
echo "Created tag: ${tag}"
|
||||||
echo "Next: git push origin main --follow-tags"
|
echo "Next: git push origin main --follow-tags"
|
||||||
@@ -72,7 +72,7 @@ function parseArgs(argv: string[]): CliOptions {
|
|||||||
|
|
||||||
function printHelp(): void {
|
function printHelp(): void {
|
||||||
consola.log(`Usage:
|
consola.log(`Usage:
|
||||||
post-encrypt [options]
|
fixit-encrypt [options]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--input <dir> Input directory containing HTML files (default: public)
|
--input <dir> Input directory containing HTML files (default: public)
|
||||||
@@ -81,10 +81,10 @@ Options:
|
|||||||
-h, --help Show this help message
|
-h, --help Show this help message
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
post-encrypt
|
fixit-encrypt
|
||||||
post-encrypt --input dist
|
fixit-encrypt --input dist
|
||||||
post-encrypt --verify
|
fixit-encrypt --verify
|
||||||
post-encrypt --dry-run`)
|
fixit-encrypt --dry-run`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectHtmlFiles(targetDir: string): string[] {
|
function collectHtmlFiles(targetDir: string): string[] {
|
||||||
@@ -6,7 +6,7 @@ import { fileURLToPath } from 'node:url'
|
|||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
const BENCH_DIR = '/tmp/post-encrypt-bench'
|
const BENCH_DIR = '/tmp/fixit-encrypt-bench'
|
||||||
|
|
||||||
const PASSWORD_HASH = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|
const PASSWORD_HASH = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ function bench(files: number, templatesPerFile: number, templateSize: string): v
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
consola.info('=== post-encrypt benchmark ===\n')
|
consola.info('=== fixit-encrypt benchmark ===\n')
|
||||||
|
|
||||||
consola.info('--- Test 1: 1 small template/file, scaling file count ---')
|
consola.info('--- Test 1: 1 small template/file, scaling file count ---')
|
||||||
for (const n of [10, 50, 100, 500, 1000]) {
|
for (const n of [10, 50, 100, 500, 1000]) {
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
# @hugo-fixit/post-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:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx @hugo-fixit/post-encrypt
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also install it globally and run the CLI directly:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install -g @hugo-fixit/post-encrypt
|
|
||||||
post-encrypt
|
|
||||||
```
|
|
||||||
|
|
||||||
Typical build flow:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
hugo build
|
|
||||||
npx @hugo-fixit/post-encrypt
|
|
||||||
npx @hugo-fixit/post-encrypt --verify
|
|
||||||
```
|
|
||||||
|
|
||||||
### Options
|
|
||||||
|
|
||||||
| Option | Description | Default |
|
|
||||||
| --------------- | -------------------------------------------------- | -------- |
|
|
||||||
| `--input <dir>` | 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/post-encrypt --help
|
|
||||||
|
|
||||||
# Encrypt content in the default public/ directory
|
|
||||||
npx @hugo-fixit/post-encrypt
|
|
||||||
|
|
||||||
# Encrypt content in a custom directory
|
|
||||||
npx @hugo-fixit/post-encrypt --input dist
|
|
||||||
|
|
||||||
# Verify encryption without modifying files
|
|
||||||
npx @hugo-fixit/post-encrypt --verify
|
|
||||||
|
|
||||||
# Dry run to see which files would be changed
|
|
||||||
npx @hugo-fixit/post-encrypt --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
1. Scans all `.html` files in the input directory
|
|
||||||
2. Finds `<template data-password="...">` 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)`
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT
|
|
||||||
Generated
+6
-6
@@ -67,6 +67,12 @@ importers:
|
|||||||
specifier: ^9.4.1
|
specifier: ^9.4.1
|
||||||
version: 9.4.1
|
version: 9.4.1
|
||||||
|
|
||||||
|
packages/encrypt:
|
||||||
|
dependencies:
|
||||||
|
consola:
|
||||||
|
specifier: ^3.4.2
|
||||||
|
version: 3.4.2
|
||||||
|
|
||||||
packages/integration:
|
packages/integration:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@hugo-fixit/shared':
|
'@hugo-fixit/shared':
|
||||||
@@ -79,12 +85,6 @@ importers:
|
|||||||
specifier: ^11.3.6
|
specifier: ^11.3.6
|
||||||
version: 11.3.6
|
version: 11.3.6
|
||||||
|
|
||||||
packages/post-encrypt:
|
|
||||||
dependencies:
|
|
||||||
consola:
|
|
||||||
specifier: ^3.4.2
|
|
||||||
version: 3.4.2
|
|
||||||
|
|
||||||
packages/shared:
|
packages/shared:
|
||||||
dependencies:
|
dependencies:
|
||||||
consola:
|
consola:
|
||||||
|
|||||||
Reference in New Issue
Block a user