hexo-post-webauthn-encrypt
v0.1.0
Published
A Hexo plugin that encrypts post HTML and decrypts it with WebAuthn PRF or an optional password.
Maintainers
Readme
hexo-post-webauthn-encrypt
hexo-post-webauthn-encrypt is a Hexo plugin for encrypting selected post content at build time.
The generated static HTML contains ciphertext instead of plaintext post content. Readers decrypt the post in the browser with a WebAuthn PRF-capable passkey or, when enabled for a post, a password fallback.
Features
- Encrypts rendered Hexo post HTML during generation.
- Supports WebAuthn PRF / FIDO2 wrapping keys.
- Supports optional per-post password fallback.
- Fails the Hexo build when an encrypted post has invalid encryption config, avoiding accidental plaintext publishing.
- Injects the required browser assets automatically.
- Provides an optional passkey registration page for generating wrapping keys.
- Refreshes common Hexo theme integrations after decrypting content, including Fluid, NexT, and Tocbot.
How It Works
During after_post_render, the plugin encrypts the rendered post HTML with a random content encryption key. That key is then wrapped by one or more configured WebAuthn PRF keys and, when a post password is present, by a PBKDF2-derived password key.
At runtime, the browser unlocks one wrapped content key through WebAuthn PRF or password verification, decrypts the post HTML with Web Crypto, and inserts the decrypted content back into the page.
Config
The plugin accepts the existing local-blog config shape:
encryption:
enabled: true
cache: 1440
salt: "64-character-hex-string"
keys:
- "64-character-hex-string"
register:
enable: true
path: /register/New projects may use post_encrypt instead:
post_encrypt:
enable: true
field: encrypted
cache: 1440
salt: "64-character-hex-string"
keys:
- "64-character-hex-string"
password:
enable: true
iterations: 10000
webauthn:
enable: true
rpId:
register:
enable: true
path: /register/
assets:
autoInject: true
path: post-webauthn-encryptPost Front Matter
---
title: Private Post
encrypted: true
password: optional-password
---When encrypted: true is present, invalid encryption config fails the Hexo build instead of publishing plaintext.
Browser Support
WebAuthn PRF requires browser and authenticator support for the PRF extension. Password fallback can be enabled for readers who do not have compatible passkeys or authenticators.
Theme Compatibility
The plugin sets page.encrypt = true after encrypting a post. Fluid already renders that branch without wrapping the encrypted container in .markdown-body.
After browser-side decrypt, the plugin inserts the decrypted HTML into .decrypted-content.markdown-body and calls Fluid.boot.refresh() when Fluid is present. It also attempts compatible refresh hooks for NexT and Tocbot.
Security Notes
- Keep
salt,keys, and postpasswordvalues out of public source repositories. - Generated static HTML contains ciphertext and wrapped content encryption keys.
- Anyone with a valid wrapping key or post password can decrypt the post offline.
- This plugin protects published static content from casual reading, but it does not replace server-side access control.
