老站的笔记里有几篇不适合公开。迁移时,我给静态页面做过客户端解密,最后又把这项功能从主题里删掉了。

现在回头看,值得记录的不是“浏览器加密一定不安全”,而是我最初把几个不同的目标混在了一起:不让正文直接暴露、不被搜索引擎收录、只允许特定的人阅读,以及以后还能撤销访问。这几件事,需要的能力并不一样。

正确实现的客户端加密可以保护正文。下载到密文,不等于就能破解任意密码。我最终放弃它,是因为这套方案的维护边界和撤回能力不适合当前博客。

密文和遮罩,首先要分清

如果正文已经在 HTML、隐藏节点或 JavaScript 数据里,只是盖了一层密码表单,那就是界面遮挡。访问者不需要破解密码,直接读取页面源码或网络响应就可能找到全文。

客户端加密是另一回事。以口令派生密钥、再用 AES-GCM 加密正文为例,部署出去的是密文;读者输入口令后,在浏览器里派生密钥、验证并解密。Web Crypto 提供这类基础能力,但接口可用不代表整套发布流程就自动安全。

构建时:口令 → 密钥派生 → 加密正文 → 发布密文
阅读时:口令 → 相同的密钥派生 → 验证并解密 → 显示正文

盐、IV 和派生参数通常可以随密文公开,它们不等于口令。它们也各有规则,例如 AES-GCM 在同一个密钥下不能重复使用 IV。真正需要保密的密钥或口令,不能为了方便直接写进前端包。

离线猜密码,是这里最重要的限制

静态托管当然也有服务器,只是普通的静态文件服务不会替文章执行登录和授权判断。密文一旦允许下载,拿到副本的人就可以在自己的设备上尝试候选口令,不必每猜一次都请求我的站点。

这意味着,网页上增加一个“输错后等待”的倒计时,不能限制离线尝试。服务端的请求限速、日志和封禁,也管不到已经带走的密文副本。

但离线尝试并不意味着必然成功。常见短口令、重复使用的密码和容易联想到作者的词句,更容易被猜中;足够随机、不可预测的口令,配合正确的算法和实现,可能让猜测在现实中不可行。不能从“弱密码容易被猜中”,跳到“任何认真尝试的人都能解开”。

口令派生算法的作用,是提高每次猜测的成本。PBKDF2 的迭代成本、Argon2id 的内存和计算成本,都需要结合目标设备与实现评估。它们不会凭空给一个常见口令增加随机性,也不能用某台机器的一次计时,推导所有设备和攻击者的速度。

这里不再给出穷举时间表,也不把某个固定参数当作通用答案。服务器密码存储的建议同样不能不加区分地照搬成浏览器加密文章的完整配置。

页面之外,还有多少地方在发正文

我更在意的维护问题,是博客并不只生成一张文章页。

首页摘要、分类和标签列表、搜索索引、RSS,都可能带出正文片段。相邻导航、社交卡片和 JSON-LD 还会带出标题或简介,站点地图会公开文章地址。即使文章页只剩密文,搜索索引里的一段明文摘要,也足以让前面的加密失去意义。

这些信息需要分别处理:标题、地址和分类是否公开,是元数据策略;正文是否只以密文分发,是加密发布策略。二者不能靠一个“加密文章”开关含糊地解决。密文长度也可能透露内容规模,必要时需要额外的填充设计,不能顺手许诺连这些特征都能隐藏。

这次迁移保留的私有草稿,采用的是更直接的办法:不进入公开构建。它们没有被放进公开页面、搜索索引和订阅源,而不是先发布出去,再期待读者看不到。相关附件也要单独核对,仅不生成文章页,并不会自动保护公开资源目录里的图片和下载文件。

WASM 和混淆,不能替代密钥管理

把逻辑换成 WASM、压成二进制,或者混淆 JavaScript,可能影响体积、运行方式和分析成本,但不会自动建立访问控制。

如果解密密钥已经随页面一起发给所有人,换一种打包形式并不能改变这个事实。反过来,某个密码派生算法通过 WASM 实现,也不能仅凭“用了 WASM”就判断它没有价值;应当看具体算法、参数和实现,而不是文件后缀。

浏览器还必须信任它实际加载的解密代码。只把正文改成密文,并没有消除脚本来源、依赖和发布过程的风险。已经获准解密的人也可以复制明文,这不是在页面里禁用右键就能阻止的。

换密码以后,旧副本怎么办

假设有人已经保存了旧密文,后来我更换密码并重新部署。新的口令保护的是新版本,旧密文仍然可以用原来的口令解开。清理当前站点和 CDN 缓存,也无法保证删除别人设备上的副本。

这一点也不能夸大成“动态站就可以收回一切”。服务端权限可以限制后续请求,但已经交付的明文、下载文件和截图,同样不能远程抹掉。区别在于,我能否控制下一次内容交付,而不是能否让已经发生的阅读消失。

所以,如果我的需求包含撤销某个人的后续访问,持续把同一份密文公开分发就不是合适的默认方案。

我最后留下了什么

我把选择收得更明确了:准备公开的文章正常发布;不准备公开的笔记不进入静态产物;确实需要按人控制访问的内容,放到具有认证和授权的系统里。

noindex 仍然有用途,但它只是对遵循规则的搜索引擎提出不收录请求,不会阻止知道地址的人读取页面。robots.txt 也不是保密机制。给明文页面加这两个设置,不能把公开文件变成私有文件。

客户端加密并没有因此被证明“无用”。如果需求就是分发密文、由持有独立密钥的人解密,并且能够接受元数据公开和旧副本无法撤回,它可以是合理的设计。只是我不想让当前主题承担这套额外承诺,也不想每增加一个内容出口,都重新审核一次保密边界。

本文按 2026-10-26 的本机代码核对:当前主题没有正文加密功能。上面的流程用于说明取舍,不是当前站点的功能介绍,也没有附带本轮不存在的性能实测。

参考