PA PassAfer

为什么要把加密计算放在浏览器里

密码生成、审计与文件加密若走服务端,明文会在传输、日志和内存里多停留几层。本地 Web Crypto 把敏感计算压回本机;打开 Network 面板,你自己就能核对这次操作有没有把秘密送出去。

打开一个「在线密码生成器」,点生成,再打开开发者工具的 Network 面板——如果请求体或查询参数里出现了刚生成的口令,说明明文已经离开你的设备。这一步不需要相信任何品牌承诺,浏览器自己会把流量摊开。

把计算放在浏览器里,不是为了听起来更「去中心化」,而是为了把明文窗口压在本机:少一层传输、少一份服务端日志、少一次运维人员误读内存转储的机会。下面按威胁模型、可核对步骤和能力边界把这件事说清楚。PassAfer 的工具栈按这个原则设计;本文不讲产品总览,只回答一个问题:敏感计算为什么不该默认交给服务器。

服务端代算会扩大什么窗口

所谓明文窗口,指的是明文(或可直接还原明文的密钥)在哪些环节真实存在。服务端代算时,窗口通常不只是「你点了提交」那一瞬间,而是一条很难事后抹掉的链条:

  • 浏览器到源站的 TLS 会话——服务端进程看到的是解密后的请求,不是密文。
  • 反向代理、WAF、APM、错误追踪里的请求体采样;一次 500 就可能把表单打进崩溃报告。
  • 应用日志、慢查询、访问日志里的 query string;有人习惯把密钥放在 ?key=,等于写进 access log。
  • 数据库、对象存储、临时磁盘上的中间文件,以及备份与异地副本。
  • 运维、客服、入侵者拿到上述任一副本的时间——窗口已经发生过,承诺「用完即删」改变不了这一点。

法律管辖和供应商分包会让「我们不会看」变成难以审计的句子。你能核对的是协议与流量,不是对方机房里的内部规范。

密码生成尤其刺眼:你要的是一串还没在任何系统里出现过的秘密。若生成发生在别人的机房,这串秘密的第一份副本就不在你手里。之后你把它贴进生产配置、CI 变量或密码管理器,泄露源已经多了一个你看不见的节点。

密码审计同样:把常用密码提交给远端「测强度」,等于把最敏感的复用口令交给第三方。公开泄露库查询可以做成 k-anonymity 一类协议;PassAfer 的 Password Audit 选择更硬的约束——待测密码不上传,强度估算与 Top 泄露列表比对都在浏览器本地完成。你要验证的不是「对方声称没存」,而是请求里根本没有这串口令。

文件加密,若走「上传 → 服务端加密 → 再下载」,口令与文件内容至少在服务端内存里完整出现过。本地流式加密则让服务端没有明文可接:它甚至不需要知道你加密的是照片还是磁盘镜像。

不要把「用了 HTTPS」当成本地计算

TLS 保护的是传输路径上的窃听者,不是对端服务器。服务端代算时,对端本来就要读明文。本地计算要解决的是:对端根本不该看到这份材料。

「本地」到底指哪一层

「本地」很容易被用成口号。需要拆开,否则网盘上的「仅你可见」也会被说成本地加密。

本机进程,而不是「存在某云账号里」

PassAfer 所说的本地,指计算发生在你的浏览器标签页:随机数来自 crypto.getRandomValues,对称加密走 Web Crypto API。密钥材料在短生命周期的 CryptoKey 对象里,默认不作为分析字段外发。结果可以复制、导出或下载到磁盘;页面关掉后,内存中的明文按浏览器生命周期回收,而不是在远端再留一份。

这和「把文件丢进仅自己可见的网盘」不是一回事。网盘服务端通常能读对象明文,除非你先在本机封好再上传密文。本地优先问的是:明文有没有在你的设备之外以可用形式出现过。

算法与文件上限是可核对的事实

初版对称加密算法只有 AES-256-GCM(认证加密:密文被改过,解密会失败)。文件加密盒对单文件做流式处理,上限 5 GB,输出 .lock(首选)或 .enc,避免把整份视频一次性装进内存。这些数字写在需求里,不是营销形容词;页面上若出现未实现的算法切换,应以产品说明为准,而不是自行脑补。

本地不等于「全部公开可用」

计算位置和登录权限是两件事。未登录访客可以使用随机字符与可读密码(Passphrase)的生成、复制与导出;Password Audit、隐私清洗、Burn-Link 创建、文件加密盒和密码库需要登录后解锁。把「本地」理解成「谁都能用所有工具」,会和权限矩阵冲突。

能力 未登录 敏感材料是否默认上传
随机 / 可读密码生成 可用 不上传;在浏览器生成
添加至密码库 登录引导
Password Audit 登录引导 待测密码不上传;本地强度 + 泄露列表
Clean Link / 脱敏 登录引导 URL 与文本本地处理;不写 analytics
Burn-Link 创建 登录引导 上传的是密文 blob,不是原文
Burn-Link 阅读 对接收方公开 密钥在 URL 的 # fragment,不随 HTTP 发给服务器
文件加密盒 登录引导 文件与口令不上传;本机流式 AES-256-GCM

Burn-Link 是唯一需要服务端暂存的路径,但暂存的是密文。解密密钥放在 URL 的 # 段:fragment 不会随 HTTP 请求发给服务器,access log 里通常只有路径。阅读页对接收方公开——否则对方还得先注册,一次性传密就做不成。首次阅读后密文按设计焚毁。服务端零知识不等于「什么都不存」,而是「存了也解不开」。fragment 的细节会另文展开;本篇只需建立这条约定。

用 Network 面板核对敏感内容是否外传

口号无法自证。下面是一套不依赖信任的核对步骤,用浏览器自带的开发者工具即可。目标不是证明「全世界没有侧信道」,而是拆穿「点一下就把明文 POST 走」的在线工具。

01

从无需登录的密码生成器开始。打开密码生成页,保持登出。随机字符与可读密码都应能直接生成。这一步把「账号体系」和「生成是否外传」分开,避免把登录请求误判成口令上传。

02

打开 Network,勾选 Preserve log。Chrome / Edge / Firefox 均可。过滤器可先用 Fetch/XHR,再扫一遍全部请求。Preserve log 避免页面跳转清空记录。注意 sendBeacon 与 Service Worker 发起的请求也会出现在面板里。

03

生成一串容易辨认的口令。把长度调长一些,生成后复制到记事本。在 Network 搜索框粘贴这串口令,或其中一段不会碰巧出现在 JS 源码里的子串。

04

看 URL、Query、Request Payload 有没有命中。若没有任何请求命中该子串,说明至少在「生成」这一下,明文没有作为 HTTP 内容外传。静态脚本里出现无关字符串不算;要找的是你刚生成的那一串。

05

登录后的工具用同一方法。Password Audit、隐私清洗、文件加密盒需要登录。登录后用仅供测试的假密码或小文件再搜一遍。审计页不应把待测密码发到远端;清洗页不应把原文 POST 出去;文件盒不应把明文以 multipart 上传。

06

Burn-Link 要看密文与 fragment。创建(需登录)时发往服务器的应是密文,不是你输入的原文。完整链接里密钥在 # 之后;去掉 fragment 再看 Network,请求路径里不应出现密钥。接收方打开阅读页不必登录。

这一步能证明什么,不能证明什么

Network 验证的是:这次操作有没有把明文放进 HTTP。它看不到同源脚本读内存、恶意扩展,或已被 XSS 插入的页面。对拆穿大量「在线工具」已经足够;不要把它理解成形式化证明。

哪些计算必须本地,哪些例外要说清楚

必须留在本机的,是一旦外传就不可撤回的材料:新生成的口令、待测的旧口令、待脱敏的原文、文件明文、对称密钥。这些东西进了别人的日志,你删页面也删不掉对方那份。

可以离开设备的,只有在密码学上对服务端无用、或属于账号体系本身的数据。例如 Burn-Link 的密文 blob、登录所需的用户名与登录密码、以及不含秘密的静态资源。不要把「登录」和「上传工具明文」混为一谈:登录是权限分级——未登录即可生成密码,降低上手成本;审计、清洗、焚链创建、文件盒和密码库在登录后解锁。登录凭证走的是账号体系,与「生成出来的那串新密码是否上传」不是同一件事。

文件加密盒的输出是你下载到磁盘的 .lock / .enc。之后用网盘、U 盘或邮件传的是密文文件。若你把密文传到某网盘,该网盘仍然看不到口令与原文——前提是口令没有写在同一次传输或同一封邮件的明文里。本地加密改变的是「网盘管理员默认能打开你的照片」这件事,不是物理保管责任。

隐私清洗(Clean Link 与 Data Redaction)同样把 URL 和文本留在浏览器里处理:剥离 UTM / 广告参数、掩码电话与证件号,结果给你核对后再外发。原文不上传,也不作为 analytics 事件内容。若清洗过程把整段工单 POST 到服务器再返回「已脱敏」,明文窗口已经在服务端打开过了,脱敏就只剩展示层。

浏览器本地加密的边界与误区

本地优先降低的是服务端与传输路径上的暴露,不是一台被木马控制的电脑。把边界写进预期,比把 AES 三个字母印在页脚更有用。

页面被注入时,算法帮不上忙

XSS 或被劫持的脚本可以读取输入框。Web Crypto 保护的是「诚实页面里的密钥操作」,不是「恶意脚本已经进了同源」。依赖的是同源策略、内容安全策略与前端供应链完整性。看到「AES-256-GCM」不要推导出「所以 XSS 无效」。

扩展、公司代理、肩窥

浏览器扩展和公司 SSL 解密代理仍可能看到页面内容。Network 面板在「公司代理注入根证书」时,你看到的是代理之后的世界。设备丢失、屏幕共享、肩窥,本地计算无法防御。这些是端点安全问题,应和「服务端不该持有明文」分开处理。

「不上传」不是「不上网」

页面本身、脚本、登录请求仍会发出。核对的是敏感字段有没有出现在请求里,不是把网线拔掉。PassAfer 也不会把待测密码、清洗原文或文件内容当作分析事件上报——事件里不应出现秘密本身。

不要把能力写过界

初版算法就是 AES-256-GCM,不要指望页面上出现可切换的 RSA 或未交付的国密选项。不要把 Burn-Link 阅读页写成必须登录。不要声称服务端也能看到明文或密钥——那与产品事实相反。本地优先的诚实写法是:敏感计算在浏览器完成;明文、密钥、文件默认不上传;焚链服务端只暂存密文。

想自己验证时,可以从哪一步开始

若你只想先确认「生成这一下有没有外传」,从密码生成器开始最合适:无需登录,随机字符与可读密码都能在本机完成,复制和导出也一样。打开 Network,按上文步骤搜一遍自己刚生成的字符串。这一步成本最低,也最容易形成「明文窗口」的直觉。

常见替代做法的局限很具体。明文邮件和即时通讯会把密钥留在双方历史记录、服务端归档和设备备份里;网盘默认对服务端可读,除非你先在本机加密;把密钥放在查询参数里,几乎一定会进 access log。这些路径不是「不够方便」,而是明文窗口被设计进去了。

若你要备份一份不能直接放网盘的文件,登录后使用文件加密盒:在浏览器里用 AES-256-GCM 流式加密,单文件不超过 5 GB,下载 .lock.enc。再对加密过程抓包,确认没有把原文件 POST 出去。需要一次性把短文本机密发给同事、又不希望密钥出现在服务器日志里时,再用 Burn-Link:本地加密,密钥放在 # 段,服务端只碰密文,阅读页对方不用注册。那是下一篇的主题;本篇只要求你先能回答:这次点击之后,明文还在不在你的标签页里。

PassAfer 的口号是「本地加密,安全随行」。随行的前提是:计算发生在你正在看的这个标签页里,并且你可以用浏览器自带的面板把这一点核对一遍。