-
Notifications
You must be signed in to change notification settings - Fork 106
FAQ
Common questions, in order of how often they come up.
No. Encryption happens at hexo generate time on your machine. Decryption happens entirely in the reader's browser. The password the reader types never leaves their browser.
Yes — tag every post with a tag in your registry, or set a password: in every post's front matter. There's no "encrypt all" switch on the global config because it would be a footgun (your homepage / archives / RSS would silently break).
The encrypted body is opaque ciphertext, so search engines can't read or rank it. The page title, date, tags, and any text above the <!-- more --> cut are still indexed (they're plaintext in the HTML). If you don't want the post to be indexed at all, add noindex meta tags via your theme.
The encrypted body is ciphertext in the source. It's safe to share / view / save the source — it's useless without the password. The password prompt + abstract / preview text are visible in source like any other HTML.
There is no recovery. The plugin doesn't store the password anywhere — it derives a key from it at build time, encrypts with that key, and discards the key. If you don't remember the password, the post is permanently unreadable. Use a password manager.
Yes. Each post can have its own password: in front matter. Different posts with different passwords coexist on the same site without interference (per-post salt + nonce ensures they don't share key material).
In v3 they were different — one for "wrong password", one for "ciphertext was tampered with." v4 unifies them: AES-GCM authentication failure is cryptographically indistinguishable from a wrong password (and that's a security feature, not a limitation). wrong_hash_message is now an alias of wrong_pass_message with a deprecation warning. Use wrong_pass_message.
A fresh nonce is generated per encryption (12 random bytes). With AES-GCM, reusing a nonce is catastrophic (it leaks plaintext XOR), so the plugin always uses a fresh one. The ciphertext changes byte-for-byte every build as a result.
If you serve from a CDN, this means:
- Always purge after rebuild
- Or: configure short TTLs for
*.html - Or: configure your CDN to revalidate on every request (defeats the purpose of a CDN, but is correct)
The browser bundle (lib/hbe.bundle.<hash>.js) is content-hashed and only changes when the bundle source changes, so it caches forever — only the post HTML needs short TTLs.
99 % of the time: the deployed site is on plain HTTP. Web Crypto requires HTTPS (or localhost). See Browser Support.
Other causes:
- The page URL contains a hash fragment that your CDN strips (the bundle reads from the page DOM, not the URL)
- A service worker is serving a stale bundle that doesn't recognize the v4 wire format
The PBKDF2 KDF runs kdf.iterations rounds on each decrypt attempt (250 000 by default). On a 2024 laptop that's ≈ 30 ms. On a 2015 phone it can be 300+ ms. Lower iterations speed it up but weaken the brute-force resistance — see the Security Model page for the trade-off.
Yes — the plugin operates on the rendered HTML output, after Hexo's renderer is done. Any renderer Hexo supports works. The only constraint is that your renderer must produce valid HTML.
Yes. Drafts are rendered like normal posts; the encrypt filter runs the same way.
The filter is registered on after_post_render. Pages render through a different pipeline. It's possible in principle but not currently wired up. PRs welcome.
Use the hexo-blog-decrypt event. The page-load-time pass of those libraries skipped your encrypted post (they only saw ciphertext); you need to re-run them on the decrypted DOM. Worked examples on that page.
Yes — write a theme. The wiki has instructions for adding a new theme by copying lib/hbe.default.html.
No. This plugin works at Hexo-build-time. The browser-side bundle is plain vanilla JS with no framework dependency.
Because it's tight on purpose. Web Crypto does the actual encryption; the bundle is just DOM + UI plumbing + the KDF / decrypt orchestration. No CryptoJS, no polyfills, no animations library — the themes use pure CSS.
Actively maintained. v4 was a 2026 redesign; minor releases land as needed. Issues and PRs are welcome.