零后端的静态网页加密保护工具——用密码把 HTML 变成「自解密页面」,部署到任何静态托管后,访客输入正确密码即在浏览器端实时解密,全程无需服务器。
StaticShield 把单个 HTML(或整站打包后)用 AES-256 加密成一份自包含的 .html:没有密码时只显示加密保护页,输入正确密码才在浏览器端还原原始内容。适合内部文档、付费内容预览、临时私密页面等「门禁式」访问控制。
- 单文件 / 多文件网页加密:单个 HTML 直接加密;
--bundle可把整站(HTML + css/js/图片)内联打包后加密 - 本地 CLI + Web GUI:命令行批量处理,或浏览器图形界面(本地后端,支持多客户端并行)
- 浏览器端实时解密,零后端:产物是自包含 HTML,部署到 GitHub Pages / 对象存储 / Nginx 等任意静态托管即可
- 随机密码生成:CSPRNG 生成强密码(默认 8 位,含数字 + 大小写字母),告别弱密码
- 记住我 / 分享链接 / 密码提示:本机免重复输入;URL Hash 自动解密链接;可选提示文案
- 重叠加密:对已加密产物再次加密,多层独立密码逐层剥解
- 卡片风解密页:默认沿用原网页 favicon 作 Logo,自定义错误提示(非原生 alert),配色统一
| 项 | 值 |
|---|---|
| 对称加密 | AES-256-CBC(PKCS#7 填充) |
| 密钥派生 | PBKDF2-SHA256(默认)/ SHA-512,迭代 1,000,000 次 |
| 完整性 | HMAC-SHA256(Encrypt-then-MAC,先验签后解密,防篡改) |
| 解密端 | 浏览器 WebCrypto,零依赖 |
| 加密端 | 本地 Node.js 脚本(CLI)+ 本地 Web GUI(浏览器图形界面) |
| 运行环境 | Node.js ≥ 18(CLI / GUI 后端),现代浏览器(解密) |
获取工具(零运行时依赖,无需 npm install):
git clone <仓库地址> staticshield && cd staticshield # 或直接下载源码环境要求:Node.js ≥ 18(内置 WebCrypto)。
# 加密单个文件(交互输入密码,不回显)
node encrypt.js page.html
# 多文件 + 指定密码 + SHA-512 + 输出目录
node encrypt.js a.html b.html -p MyPwd123 --sha512 -d ./dist
# 记住我 7 天 + 生成分享链接 + 提示文案
node encrypt.js secret.html --remember 7 --share --hint "我的生日"
# 多文件网页打包加密(HTML + 独立 css/js/图片)
node encrypt.js index.html --bundle -p MyPwd123
# 生成随机密码并用于加密(12 位,自动打印密码)
node encrypt.js page.html --gen-pwd 12
# 仅生成一个随机密码(默认 8 位)
node encrypt.js --gen-pwd
# 打开图形界面(Web GUI)
node encrypt.js --gui加密后生成同名 .html(自解密页面)。直接部署或双击打开,输入密码即可查看。若输出与源文件同路径,会自动改名为 xxx.encrypted.html 以免覆盖源文件。
[加密] 原始 HTML ──(密码 + AES-256 + PBKDF2 + HMAC)──▶ 自解密 .html
[部署] 上传到任意静态托管(GitHub Pages / 对象存储 / CDN / Nginx …)
[解密] 访客打开页面 ──▶ 输入密码 ──▶ 浏览器 WebCrypto 还原原始 HTML
加密端(CLI / GUI 后端)与解密端共用同一份 WebCrypto 加密核心(src/crypto-core.js),产物格式一致、单点维护。
| 参数 | 说明 | 默认 |
|---|---|---|
<filename> |
待加密 HTML 文件,支持多个 | — |
-p, --password <pwd> |
加密密码;未提供则交互式提示输入(不回显) | 交互输入 |
--sha512 |
使用 PBKDF2-SHA512 | PBKDF2-SHA256 |
-d, --directory <dir> |
输出目录 | 当前目录 |
--remember <days> |
记住我过期天数,0 = 永不过期 |
不启用 |
--share |
额外生成可自动解密的分享链接(密码置于 URL hash) | 关闭 |
--hint <text> |
密码提示文案 | 空 |
--logo <path> |
自定义解密页 Logo(默认取原网页 favicon) | 原网页 favicon |
--bundle |
先把 HTML 引用的本地 css/js/图片内联成单文件再加密(多文件网页) | 关闭 |
--gen-pwd [n] |
生成 n 位随机密码(默认 8,含数字 + 大小写字母)用于加密;不带文件时仅生成 | 关闭 |
--gui |
启动本地 GUI 后端(127.0.0.1)并打开浏览器 | 关闭 |
-h, --help |
显示帮助 | — |
当网页是「index.html + 独立 css/ + js/ + 图片」的多文件结构时,直接加密 index.html 会丢失或暴露这些资源。加 --bundle,工具会先把 HTML 引用的本地相对路径资源全部内联成单个自包含 HTML,再走加密:
<link rel=stylesheet>→<style>(递归内联 css 内@import与url())<script src>→ 内联<script>,严格保持原加载顺序与其他属性<img/source/audio/video/track>.src、<video poster>、srcset、favicon →data:URIhttp(s)、CDN 等绝对 URL 原样保留;相对路径沙箱约束在源网页目录内,防路径遍历
解密端无需任何改动(打包后仍是单 HTML)。代价是产物体积增大(图片 base64 膨胀约 33%)。
node src/build-gui.js # 由源码生成 gui/index.html(改前端源码后需重新生成)
node encrypt.js --gui # 启动本地后端(127.0.0.1)并打开浏览器--gui 启动一个仅绑定 127.0.0.1 的本地服务,浏览器访问后:
- 单文件:选一个 HTML → 设密码 → 加密下载
- 整个文件夹:选网页所在文件夹(含 index.html + css/js/图片)→ 后端打包内联(同
--bundle)→ 加密下载 - 密码框旁「🎲 生成」按钮可即时生成随机密码(可改位数)
多个客户端(标签/设备)可同时访问并行加密,文件不离开本机,终端 Ctrl+C 停止服务。
Web GUI 必须通过本地服务访问;直接双击
gui/index.html无法工作(前端需调用后端 API)。
- 卡片风格输入框(主背景
#ddcdef、按钮#9932cc、错误#8b0000),默认显示原网页 favicon 作为 Logo - 密码显示/隐藏切换(眼睛图标);错误时卡片内自定义提示 + 抖动反馈(不使用原生 alert)
- 自动解密优先级:URL Hash 密码 → 本机「记住我」→ 手动输入
- 解密成功:清除 URL hash → 用原 HTML 替换当前文档 → 恢复原始
<title>
- PBKDF2 百万次迭代 + 随机 salt,显著抬高暴力破解成本
- HMAC 先验后解:密文被篡改则验签失败,避免 padding oracle 类风险
- 加密/签名密钥隔离:PBKDF2 派生 64 字节,前 32 为 encKey、后 32 为 macKey
- 随机 IV/salt:相同文件 + 密码每次产出不同密文
- 分享链接走 URL Hash:密码不随 HTTP 请求发送到服务器;解密成功后清除 hash。但链接本身即含密码,请按需分享
- 记住我不存原始密码:仅存 PBKDF2 派生密钥材料 + 过期时间于本机 localStorage,过期自动清除;公共设备请勿勾选
- 同源注意:记住我的派生密钥存于
localStorage,可被同源脚本读取。同一托管域下若托管多个加密页或存在 XSS,存在被跨页读取的可能;高敏感场景请勿勾选记住我
⚠️ 浏览器端解密意味着密文会下发到客户端,StaticShield 适用于「门禁式」访问控制(防直接查看/抓取),不构成对资深逆向者的绝对防护。
忘记密码能找回吗?
不能。工具本身无后端,密码不存储于任何服务器,PBKDF2 为单向派生——丢失密码即内容无法恢复。建议用 --gen-pwd 生成后妥善保存。
安全性如何? 采用 AES-256 + PBKDF2 百万次迭代 + HMAC 验签,对标业界标准。但密文会下发到客户端浏览器,属「门禁式」访问控制(防直接查看/抓取),无法阻止资深逆向者;绝密内容请使用更强的访问控制方案。
支持哪些部署平台?
任何能托管静态文件的位置:GitHub Pages、GitLab Pages、Vercel/Netlify 静态、对象存储(S3/OSS/COS)、Nginx/Apache,甚至直接双击本地打开(file://)。
多文件网页(带 css/js/图片)怎么办?
用 --bundle(CLI)或 Web GUI「整个文件夹」模式,工具先内联打包成单 HTML 再加密。
能加密多大的文件? 理论上无硬性限制,但产物是单 HTML(图片经 base64 膨胀约 33%),超大站点体积会明显增大,更适合单页或中小型站点。
产物能在纯 HTTP 下解密吗?
不能。浏览器 WebCrypto 仅在安全上下文(https://、localhost、file://)下可用;纯 HTTP 部署会提示需 HTTPS。请通过 HTTPS 访问。
staticshield/
├── encrypt.js # CLI 入口
├── src/
│ ├── crypto-core.js # 同构加密核心(Node + 浏览器共用,单点维护)
│ ├── render.js # 产物 HTML 渲染(同构,CLI 与 GUI 共用)
│ ├── decrypt-ui.js # 浏览器解密运行时(内嵌进每个产物)
│ ├── template.js # 组装产物(Node,调 render)
│ ├── bundle.js # 多文件网页打包内联(Node)
│ ├── password.js # 随机密码生成(同构 CSPRNG)
│ ├── favicon.js # 提取原网页 title/favicon(Node)
│ ├── cli-args.js # CLI 参数解析
│ ├── gui-logic.js # Web GUI 前端逻辑
│ ├── server.js # Web GUI 本地后端(HTTP,127.0.0.1)
│ └── build-gui.js # 由源码生成 gui/index.html
├── gui/
│ └── index.html # 生成的 Web GUI(由 build-gui.js 产出)
└── package.json
单点维护:crypto-core.js(算法)、render.js(产物结构)、bundle.js(打包)、password.js(密码生成)各一份,CLI 与 Web GUI 后端都复用它们,避免两套实现不一致。改 src/ 下源码后,CLI 产物自动用最新核心/UI;改 GUI 前端源码需重跑 node src/build-gui.js。
node src/build-gui.js # 重建 Web GUI(修改前端源码后执行)以下浏览器交互行为建议人工抽测验证:
- 基础解锁:打开加密产物 → 输入正确密码 → 原页面还原、title 恢复
- 错误反馈:输错密码 → 卡片内红色提示 + 抖动(非 alert)
- 密码显隐:点击眼睛图标 → 明文/密文切换
- 分享链接:打开
xxx.html#pwd=<密码>→ 自动解密并清除地址栏 hash - 记住我:勾选解锁 → 关闭再打开 → 免密自动解密;
--remember 0为永久 - 重叠加密:对产物再次加密 → 逐层输入密码还原
- Web GUI:
--gui启动 → 单文件模式加密下载 → 切换「整个文件夹」选多文件网页 → 产物可被正常解密
MIT
项目地址:github.com/wangshengithub/staticshield · MIT License