口号无法核对,流量可以
很多人判断一个「在线加密」页是否安全,靠的是页面上的一句话:本地计算、零上传、端到端。这些句子可以出现在任何站点上,包括把文件直接 POST 到服务器再代为加密的站点。它们不是证据。
你真正能当场看到的,是当前标签页发出了哪些请求。浏览器开发者工具的 Network 面板会列出方法、地址、查询串、请求体,以及部分访问统计。如果你刚选中的文件名、口令,或一段只有你知道的「金丝雀」明文出现在这些位置,所谓本地加密就不成立。
反过来,Network 里没有明文,只能说明这一次操作没有把这些字段当作业务数据发出去。它不能证明内存里没有明文、扩展程序没有读取剪贴板,也不能证明下一次版本更新后行为不变。核对的价值在于:把不可检验的宣传,收成一次可重复的观察。
「本地」具体指哪一层计算
「浏览器本地」不是「这个域名看起来很安全」,而是「加解密发生在你正在看的这个标签页里」。对 AES-256-GCM 来说,常见的正确路径是调用 Web Crypto API:密钥派生、加密、认证标签都在浏览器提供的密码学接口里完成,而不是把原文交给远端接口代算。
文件加密的典型过程是:你通过文件选择器选出一个本机文件,脚本把它读成内存中的二进制块,按块加密,再触发浏览器下载密文。下载下来的 .lock 或 .enc 是结果文件,不是上传回执。单文件上限如果写成 5 GB,指的是本机流式处理能力,不表示服务器收了 5 GB 原文。
还要把「业务上传」和「页面自己会发出的请求」分开。打开即用的工具站通常仍会加载样式和脚本,也可能发送不含正文的访问统计。这些请求的存在,不能用来指控「文件被上传了」;但统计请求的 query 或 body 里如果出现了你刚输入的口令或待测密码,那就是另一回事。
把计算边界写成可核对的句子,会比形容词更有用:密码生成、密码检测、隐私清洗和文件加解密的明文与密钥默认不离开浏览器;阅后即焚只允许密文出站,解密密钥放在 URL 的 # 片段。MakePwd 按这个边界实现工具,并且全部打开即用、没有账号。承诺仍然只是承诺。下面用 Network 把它收成检查项。
不要用真实密钥、证件或未脱敏表格做实验。准备一个可以丢弃的小文件,口令用一次性长句。核对的是流量,不是把隐私再暴露一遍。
用 Network 做一次可重复检查
先准备一枚不会出现在真实业务里的标记。文件名可以用 canary-local-2026.xlsx,口令用一段随机长句,正文里写一句只有这次实验才有的话。金丝雀的作用是搜索:在 Network 的过滤器里粘贴它,命中即失败。
打开开发者工具,切到 Network,勾选 Preserve log,过滤 XHR / Fetch。不要只看「成功的请求」——被取消或返回 4xx 的请求同样可能已经带上了明文。
然后做一次完整操作:选文件、输入口令、点加密或生成。结束后先不要关面板,按下面三处看。
- 在过滤器里粘贴金丝雀字符串,先看有没有红色命中。有命中就停下来读那条请求,不必再往下做「感觉上像本地」的判断。
- 没有命中时,再逐条打开 XHR / Fetch,对照请求行、查询串和请求体。静态资源、字体和脚本可以忽略。
- 单独过滤访问统计路径,打开 query 与 body。页面标题和路径可以出现;刚输入的口令、待测密码、清洗前原文和文件内容不应出现。
看请求行
完整 URL 里的 path 和 ? 后面的查询值得逐字看。id 这类定位字段可以出现;文件名、口令、待测密码、# 后面的密钥不应该出现。把地址栏整串和请求行对比:井号之后的部分如果进了请求行,说明实现把 fragment 错用成了 query,或脚本主动读取后写进了请求。
看请求体
POST / PUT 的 payload 是第二处。文件加密如果声称本地完成,请求体里不该有原文件二进制,也不该有口令。阅后即焚可以有密文字段,那是预期出站的数据;你要确认它看起来不像你刚输入的原文。密码检测页如果把待测密码 POST 出去,无论目的写成「查泄露」还是「算强度」,都已经离开了本机。
单独看分析上报
访问统计经常被忽略。主接口干净、上报却带着输入框全文,这次操作仍不能算「明文留在浏览器」。过滤统计路径时,不要假设「分析脚本一定无害」——它只是另一类出站请求,检查方式与业务接口相同。
勾选 Preserve log。加密完成后如果页面跳转或刷新,未勾选时第一条带明文的请求可能已经被清掉,你会得到虚假的「面板是空的」。
问号会进 HTTP,井号默认不会
URL 有两段常被混在一起。问号后面的查询会进入 HTTP 请求行,服务器、反向代理和访问日志都能看见。井号后面的片段默认由浏览器留在本地,用来给当前页的脚本读,不随这次文档请求发给服务器。
因此,一次性密文链接如果把密钥放进 #,接收方打开 s.html?id=...#密钥 时,服务器按设计只能看到 id,看不到密钥。这不是额外的加密协议,而是浏览器对 fragment 的默认行为。它有边界:你把完整地址贴进工单、群聊或某些会丢掉 hash 的跳转页,密钥就从「不进 HTTP」变成「出现在别人的屏幕和日志里」。
核对方法同样具体:创建一条测试焚链,看创建请求的 body 是否只有密文;打开阅读页时,看文档请求和后续接口的 URL 是否只含 id。地址栏里 # 后面的内容不应出现在这些请求里。阅读页对接收方公开,不需要登录。
| 看哪里 | 会不会进 HTTP | 怎样算通过 |
|---|---|---|
| 页面口号 | 不涉及 | 不能当证据,只作对照 |
| 请求行 / query | 会 | 无金丝雀、无口令、无 fragment 密钥 |
| POST body | 会 | 无原文;焚链只允许密文 |
URL # 片段 |
默认不会 | 地址栏有、请求行没有 |
| 访问统计 | 看实现 | 无输入框原文 |
你能证明什么,不能证明什么
这次检查能支持的结论很窄,写清楚反而更有用。
能支持:在你使用的这个浏览器、这个版本、这一次操作里,明文、口令和 fragment 密钥没有作为已观察到的 HTTP 业务数据或分析原文离开标签页。
不能支持:没有别的标签页或扩展在读剪贴板;硬盘上的下载目录是安全的;对方收到密文后不会截图;密码检测覆盖了全网泄露库。如果检测只做本地熵和一份公开弱口令 Top 列表,它只能回答「像不像常见弱口令」,不能回答「从未出现在某次泄露中」。那不是全网 HIBP 撞库。范围怎么写、怎么当场核对名单行数,见本地弱口令名单能证明什么,为什么它不是全网泄露查询。
也不要把它理解成渗透测试。你没有检查 WebSocket、Service Worker 缓存,也没有逆向混淆脚本。目标是让自己能向同事解释:我打开了 Network,用金丝雀搜过,请求行和 body 是干净的。这比转发一句「官网说不上传」更接近工程讨论。
把同一套步骤用在打开即用的工具上
若你希望用一个把计算边界写清楚的页面来练习,可以从 MakePwd 的文件加密盒开始。打开即可使用,无需注册。选一个不含真实隐私的小文件,口令用金丝雀,加密后下载 .lock。同时盯着 Network:你应看到静态资源和可能的访问统计,不应看到原文件或口令作为业务字段。算法按站点说明是 AES-256-GCM,在 Web Crypto 里算,单文件不超过 5 GB。
阅后即焚适合练第二项:创建一条无害测试文本,确认出站的是密文;阅读页对接收方公开,链接形态是 s.html?id={id}#{key}。密码检测适合练「输入框内容会不会进统计」——待测密码按产品说明不上传,比对发生在本地名单。
这些练习的目的不是证明某一个站点「绝对安全」,而是让你把同一套核对步骤用熟。换任何声称本地加密的页面,步骤不变:金丝雀、Preserve log、请求行、请求体、统计上报。
下次核对时记住的三件事
第一,看流量,不看口号。第二,密文出站可以接受,密钥和原文不行。第三,换浏览器、换版本、换功能后重新做一遍金丝雀搜索。能重复的观察,才值得写进你们自己的安全说明。
如果你还要继续追问「为什么密钥可以放在井号后面」,请读URL 的井号后面为什么适合放密钥,以及什么时候会失效。本文只把「明文有没有离开这个标签页」收成可以当场做完的检查。