先记结论:阅后即焚能支持的结论很窄——达到阅读次数或过期之后,服务器上的密文没了,再按同一个编号取不到原文。它不能支持「接收方没截图」「群里没有第三人打开过」「聊天备份里没有完整链接」。核对方法是对照两次打开和 Network,而不是把页面上的「已焚毁」当成对方设备干净的证明。
一句话先回答搜索意图
阅后即焚证明的是托管方手里的密文被删掉了,不是接收方的屏幕、剪贴板和聊天记录被擦掉了。第一次成功取出密文后,再打开同一条链接,阅读页会提示已被焚毁或已过期;按 HTTP 410 Gone 的语义,目标资源在源站上已经不在,而且这种情况多半是永久的。这只能回答「服务器还交不交得出来」,回答不了「对方有没有留下副本」。
这篇文章给开发者、运维,以及要把一次性口令、API Key 或恢复码发给同事之前,想先分清「链接失效」和「对方没留存」的人。它不代替 阅后即焚 的操作说明,也不重复「怎么生成一条链接」。你要带走的是:烧掉的是哪一层、刷新失败能证明什么、截图为什么在范围外、用两次打开和 Network 怎么当场对照。
「已焚毁」和「对方没留下副本」不是一回事
日常说法把三件不同的事揉成一句「这条消息看完就没了」。第一件是服务器不再保存密文:编号对应的记录被删除,再请求只得到焚毁或过期。第二件是当前标签页不再显示明文:关掉页面、点「从本页清除」,或脚本在离开页面时把文本框清空。第三件是接收方的设备上没有任何副本:没有截图、没有复制、没有把完整链接转发给别人、没有把明文贴回聊天。
阅后即焚只对第一件有强制力,对第二件最多做到「这个标签页里的展示区被清掉」,对第三件没有强制力。页面可以写「拦不住复制或截图」,那不是谦虚,而是边界:浏览器不能禁止另一台手机对着屏幕拍照,也不能在对方点了「复制明文」之后,再去擦掉系统剪贴板和聊天软件的本地库。
所以「我刷新了一下,已经打不开了」只能支持很窄的结论:你这一次按编号取密文,服务器没有再交出来。它不能支持「只有他一个人看过」「他没有截图」「工单里不会再搜到这串口令」。要把后几句写成可核对的事实,必须换一层观察:看对方有没有把明文或完整 URL 带出这个标签页,而不是只看发送方自己的第二次打开。
服务器烧掉的是哪一层
零知识焚链把「定位」和「解密」拆开。链接形态是 s.html?id={id}#{key}:问号后只有编号,密钥只在井号后面。RFC 9110 规定请求的目标 URI 不含 fragment,浏览器向服务器要文档时会丢掉 # 及之后的部分。服务器按设计只能看到编号,看不到密钥,也看不到明文。
创建时,浏览器用 Web Crypto 做 AES-256-GCM:随机 32 字节密钥,12 字节 IV,明文在本机收成密文后再 POST /secrets。出站字段是密文、过期时间和阅读次数;密钥只出现在随后拼好的分享链接里。单条上限 32 KB。过期可选 1 小时、24 小时、7 天,或只在阅读后焚毁;阅读次数 1–10,默认 1 次。创建和阅读都打开即用,没有账号,也没有「谁打开过」的登录身份。
阅读时,服务器在成功交出密文并达到设定次数后,删除这份密文。发送方再打开,看到的是「已被焚毁」或「已过期」。这证明:托管方不再持有那串密文字节。它不证明:密钥从未出现在聊天记录里,明文从未出现在对方屏幕上,或者中间没有第三人用同一条完整链接点过「打开并查看」。
密钥一直在拿得到完整 URL 的人手里。把 https://…/s.html?id=…#… 整串贴进群,等于同时交出编号和钥匙。服务器即使已经烧掉密文,也挡不住「当时已经打开过的人」把明文留下来;如果次数还没用完,后来点开的人仍然能取到密文。烧掉密文,解决的是「托管方长期保存明文或密文」这一层,不是「看见整串链接的人」这一层。
刷新失败能证明什么,证明不了什么
第二次打开失败,至少要先分清三种提示。第一种是已被焚毁:密文已经不在,原因可能是读满了设定次数,也可能是编号本来就无效。第二种是已过期:到了创建时选的 TTL,即使没人读过,服务器也会删。第三种是缺少 # 后的密钥:编号可能还在,但本机解不开;不少聊天软件会截断井号后面的内容,接收方看到的是「缺少片段密钥」,这和「已经被别人读走」不是同一件事。
410 Gone 的意思是:源站上的目标资源不再可用,并且这种情况很可能是永久的。阅读页把 410 再拆成「焚毁」和「过期」:响应里如果带 expired,对应 TTL;否则按焚毁处理。404 在实现里也按焚毁展示,因为对接收方来说,结果一样——再也取不到密文。网络失败不能算焚毁:点过「打开并查看」之后才断网,且创建时只允许读一次,密文可能已被取走,但你这一次没在本机解开。
因此,「我这边刷新打不开」能支持的结论是:现在按这个编号,服务器不交出密文。它不能支持:打开的人是指定的那位同事;他没有复制;他没有截图;群里的预览或安全扫描没有先消耗次数。没有账号体系,就没有「已读回执」可以点名。次数是服务器侧的计数,不是对接收方设备的审计。
不要用真实口令、API Key 或未脱敏连接串做实验。准备一句只有这次才有的测试文本。核对的是状态接口、取密文的请求和第二次打开的提示,不是把凭证再暴露一遍。
截图、复制、聊天记录为什么在范围外
明文一旦画在屏幕上,保护范围就从「服务器有没有密文」变成「对方终端上发生了什么」。系统截图、录屏、另一台手机拍照,都不向托管方发请求,阅读页无法拦截,也无法事后通知。这不是某一家产品没做完,而是浏览器和操作系统不把「禁止对方记录屏幕」交给普通网页。
复制同样在范围外。阅读页可以提供「复制明文」,也可以在离开页面时清空文本框;清空的是这个 DOM 节点,不是系统剪贴板,更不是聊天软件的草稿箱。macOS 和部分输入法还带剪贴板历史。你看见「已从本页清除」,只说明当前标签页不再显示那句话,不说明这句话没有进过剪贴板。
聊天记录是另一条独立的留存。完整链接如果出现在群消息里,群历史、搜索、多端同步和将来的导出都能再次看见井号后面的密钥。即使服务器已经烧掉密文,链接本身仍是「曾经有效」的证据,有时也足够让不知道次数已用尽的人反复点开、误判成「链接坏了」。密钥层在 HTTP 请求里可以仍然干净——Referer 按规范不得带 fragment——但对「能打开聊天记录的人」来说,这层保护已经没了。
工单、邮件和浏览器历史也一样。地址栏显示过的 # 片段,通常会进本地历史;开了同步的浏览器,还可能把同一条记录送到其他设备。清掉标签页不等于清掉历史。阅后即焚减少的是服务器保存时间,以及「同一条密文被反复取出」的机会;它不是数字版权,也不是取证报告。
状态查询为什么不消耗次数
如果第一次打开落地页就取走密文,聊天软件的链接预览、邮件安全网关和部分企业扫描器,可能先于接收方把仅有的一次读完。接收方点开时只看到「已被焚毁」,密钥其实从未交给预览主机——烧掉的是阅读次数,不是 fragment 的保密性。上一篇写过井号为什么默认不进 HTTP;这一篇只盯次数:预览请求和「真正取出密文」必须拆开,否则「已焚毁」连「接收方看过」都证明不了。
FastPwd 的阅读页把这两步拆开。打开页面时只请求 /secrets/{id}/status,询问密文还在不在,不取走密文;接收方点「打开并查看」之后,才 GET /secrets/{id} 取密文,并用井号后的密钥在本机解密。缺少 # 密钥时,页面不会去取密文,以免浪费仅有的次数。创建页和阅读页都不需要账号。
预览机器人通常只会拉落地页,不会替你点按钮;这能降低「预览即焚毁」的概率,但不能保证所有扫描器都停在落地页。你在 Network 里应当能看见:先有一条 status,后有一条取密文;只打开、不点击时,不应出现取走密文的成功响应。次数仍然是服务器侧的计数,不是 fragment 的一部分。
| 你看见的现象 | 能支持的结论 | 不能支持的结论 |
|---|---|---|
| 第二次打开提示已被焚毁 | 现在按这个编号取不到密文 | 接收方没截图、没复制 |
| 提示已过期 | 到了 TTL,服务器已删除 | 一定有人成功读过 |
| 提示缺少片段密钥 | 地址里没有 # 后的密钥 |
密文一定已被取走 |
| 只打开页面、未点按钮 | status 查询不应消耗次数 | 所有预览机器人都不会取密文 |
| Network 里 POST 只有密文 | 这一次创建没把原文当业务字段发出 | 完整链接贴进聊天后仍只有你看得见 |
| 本页已清除明文 | 当前标签页不再显示那句话 | 剪贴板和截图里也没有 |
当场对照:两次打开、status、Network
口号不能当证据。准备一句可丢弃的金丝雀,例如 canary-fp-20260905-burn-vs-shot,不要复用真实口令。创建时把阅读次数留在默认的 1,过期用 24 小时即可。
- 在创建页写入金丝雀,生成链接。打开开发者工具的 Network,勾选 Preserve log。把金丝雀和井号后的密钥分别粘进搜索框:
POST /secrets的请求体里应只有密文、过期时间和阅读次数,不应出现原文或密钥。 - 用同一条完整链接打开阅读页,先不要点「打开并查看」。Network 里应出现
/secrets/{id}/status,不应出现成功取走密文的GET /secrets/{id}。页面应停留在等待确认。 - 点「打开并查看」。此时才应按编号取密文,并在本机用 AES-256-GCM 解开。成功后的说明会写:服务器已删除这段密文,或——若你把次数调到大于 1——达到设定次数后才会删除。
- 刷新阅读页,或换一个全新的浏览器上下文再打开同一条链接。默认读 1 次时,应看到已被焚毁;再搜 Network,取密文的请求应得到 410 或按焚毁处理的响应。金丝雀不应再作为明文出现在任何请求体里。
这四步只证明一件事:在你控制的两次打开之间,服务器上的密文从「还在」变成「不在」。它们证明不了:假如这是发给同事的真实口令,对方没有截图。要把「对方会不会留下」收成工作习惯,只能写进交接说明:不要截图、不要把明文贴回群、口令用完立刻轮换——而不是指望页面上的「已焚毁」替你做终端审计。
完整链接和密文不要走同一条渠道。网盘或邮件传 .lock,口令改走阅后即焚;阅后即焚的完整 URL 也不要再贴进那个网盘文件夹的备注。把钥匙和箱子放在同一条消息里,烧掉密文也救不回已经看见整串的人。
三种把「已焚毁」读过头的情况
第一,把过期当成有人读过。创建时选了 1 小时,同事第二天才点开,提示是已过期。服务器同样删了密文,但删除原因是 TTL,不是阅读次数用尽。过期未读的内容无法找回,也不等于「已经被打开过」。
第二,把缺少片段当成已被焚毁。微信、部分邮件客户端会截掉 # 后面的内容。接收方打开的是 s.html?id=…,没有密钥。阅读页在缺少密钥时不会取密文。你这边稍后打开完整链接,内容可能还在。这时应让对方要回含井号的整串,而不是立刻认定「有人先看过了」。
第三,把本页清除当成全局清除。阅读页可以在离开时清空文本框,也可以用 history.replaceState 去掉地址栏里的片段。这只影响当前标签页的展示和后续刷新是否还带密钥。系统截图、剪贴板历史、聊天备份和浏览器同步历史,都不在这个清空范围里。
常见问题
对方刷新后看到「已被焚毁」,是不是说明他没留下内容?
不是。这只说明服务器上的密文已经不在,再次按编号取不到原文。截图、复制、录屏、聊天备份和把完整链接转发给第三人,都不经过这次删除。已焚毁不是「对方设备干净」的证明。
聊天软件的链接预览会不会先把内容烧掉?
预览通常只打开落地页。阅读页会先查询密文还在不在,不取走密文;点「打开并查看」才按编号取密文。预览机器人多半不会替你点按钮,但不能保证所有扫描器都停在落地页。次数是服务器侧的计数。对照方法是:只打开、不点击时,Network 里不应出现成功取走密文的请求。
阅后即焚能证明是谁打开的吗?
不能。创建和阅读都不需要账号,服务器也不按登录身份标记阅读者。你能核对的是:这一次取密文之后,编号还在不在。不能从「已焚毁」反推打开的人是谁,也不能把它写成已读回执。
创建和阅读需要注册吗?明文会不会上传?
不需要注册。明文在当前标签页用 AES-256-GCM 加密后再上传密文;密钥放在链接的 # 片段。用金丝雀搜 Network:请求体里应只有密文,不应出现原文或井号后的密钥。超过 32 KB 或整份文件,请改用 文件加密盒 在本机处理,不要把焚链当网盘。
把同一句金丝雀用打开即用的工具对照一次
若你希望用一个把计算边界写清楚的页面来练习,打开 FastPwd 的 阅后即焚 即可,无需注册。写入上面那句金丝雀,阅读次数留 1,生成后按第四节做完两次打开。同时盯着 Network:你应看到创建时的密文 POST、阅读页的 status、点击后的取密文,以及第二次打开时的焚毁响应;不应看到原文或井号后的密钥作为业务字段。
必须把口令交给同事时,才走这条通道。随机口令可以先在 密码生成器 里本地生成,长度 6–128 位、默认 16 位;低于 8 位会提示安全性较低。生成过程不上传。整份合同、证件扫描件或超过 32 KB 的材料,改在 文件加密盒 里用同一套 AES-256-GCM 收成 .lock / .enc,单文件不超过 5 GB;口令仍然单独走焚链,不要写进网盘备注。
下次发送前记住三件事。第一,已焚毁证明的是服务器上的密文没了,不是对方没截图。第二,只打开落地页不应消耗次数;点「打开并查看」才取密文。第三,完整链接贴进聊天后,井号后的密钥对「能看见消息的人」已经明文可见。能重复的观察,才值得写进你们自己的交接说明。
延伸阅读
井号后面为什么默认不进 HTTP,以及把完整链接贴出去时会丢掉哪一层保护,见 URL 的井号后面为什么适合放密钥,以及什么时候会失效。「本地加密、不上传」不能当证据,要用金丝雀搜 Network,见 浏览器本地加密怎么核对明文没有离开本机。若还要把工单正文里的证件号在离开本机前掩码,见 把工单和日志贴进 AI 之前,怎么先核对哪些字段会离开本机。