Skip to content

调研:网站登录弹出填充、密码生成、管理界面(2026-11-16) ​

结论:没有一条路径能覆盖所有浏览器和系统。v1 做 Manifest V3 浏览器扩展(Chrome / Edge / Firefox),通过 native messaging 小程序连到 Rust 后台进程。密码生成放在 Rust 核心里,管理界面用 Tauri v2。各系统自带的自动填充以后逐个加。

A. 自动填充 ​

浏览器扩展 + native messaging:跨平台主路径 ​

  • KeePassXC-Browser(GPL,只能参考):
    • 用 NaCl box,三对密钥:每次会话的客户端密钥、每次会话的宿主密钥、用户只需确认一次的长期身份密钥(associate)。
    • 一个很小的代理程序把 stdio 转发到本地 socket。
  • Bitwarden(GPL,只能参考):
    • 扩展生成 RSA 密钥对,桌面端用它加密一把共享密钥发回来,用户核对指纹。
    • 转发程序是用 Rust 写的。
  • Native messaging 的规则:
    • 宿主清单里要列出允许的扩展 ID,不能用通配符。
    • 调用方的 origin 作为 argv[1] 传入。
    • 宿主发给浏览器的单条消息上限 1 MB。
    • 清单在 macOS 和 Linux 上放在各浏览器自己的目录,在 Windows 上写注册表。
  • 识别登录表单(都是启发式):
    • KeePassXC 把用户名和它之后的第一个密码框配对,尊重 autocomplete=username/new-password,还能识别"一格一位"的 TOTP 输入框。
    • Bitwarden 把 autocomplete 标记和关键词组合起来判断:登录、注册、改密码、银行卡,再加提交按钮的关键词。
  • 页面内弹出菜单的隔离:
    • Bitwarden:封闭的 shadow root 里放一个扩展页面的 iframe,用 popover="manual" 浮在页面最上层,z-index 设为 2147483647;再用 MutationObserver 监视 html 和 body,页面一改透明度或可见性就关掉菜单。
    • KeePassXC:封闭的 shadow root,加最小透明度检查和 isTrusted 检查。
    • 这些都是为了应对 DEF CON 33 披露的 DOM 点击劫持,当时 11 个密码管理器里有 10 个中招。
  • 域名匹配:
    • KeePassXC 要求主域名相同:要么主机名完全一致,要么网站主机名以 .条目主机名 结尾。端口和协议也要检查。
    • Bitwarden 用 tldts,提供多种模式:Domain(默认)、Host、Starts-with、Exact、Regex、Never。
  • Safari 没有 stdio 宿主。扩展必须打包在 Xcode App 里,消息经 sendNativeMessage 发给 App 扩展。
  • Linux 上 Flatpak 和 Snap 版浏览器用不了 native messaging(Ubuntu 的 Firefox Snap 例外),相关 portal 至今没合并。

系统级自动填充(以后再加) ​

macOS / iOS: ASCredentialProviderViewController。

  • 支持范围:密码从 macOS 11 起,通行密钥从 14 起,验证码从 15 起。原生 App 里填密码也走同一个扩展。
  • 代价:要写 Swift 沙盒 .appex,加 App Group 和描述文件。用 Developer ID 分发即可,不必上 App Store。
  • 参考:Bitwarden 的这个扩展目前在代码里只支持通行密钥。KeePassium(GPL)和 Strongbox(AGPL)有完整实现。

浏览器用不用 macOS 的系统 provider:

浏览器情况
Safari用
Chrome没找到证据表明它会用第三方 provider 填密码(未核实)
Firefox / Edge / Arc没找到证据(未核实)

Windows 11: 从 2025 年 11 月起有通行密钥插件 API。只支持通行密钥,要求 MSIX 打包,没有填密码的 API。

Linux: 没有系统级 API,只能靠浏览器扩展。

B. 密码生成 ​

可以直接复用的数据和库:

  • apple/password-manager-resources(MIT):
    • password-rules.json:各网站的密码规则。
    • shared-credentials.json:共用账号的域名组。
    • change-password-URLs.json:改密码页面地址。
    • websites-that-append-2fa-to-password.json:要求把验证码接在密码后面的网站。
    • 做法:把这些数据收进仓库,用 CI 定期更新。
  • password-rules-parser 1.1.0(Apache-2.0,1Password 出品):解析上面的规则,也能解析页面上的 passwordrules 属性。

随机数和强度:

  • rand 0.10。注意改名:OsRng 变成了 SysRng,thread_rng() 变成了 rand::rng()。用 random_range 做无偏采样。
  • 保证每类字符的最少数量:先把必需的字符放进去,再整体打乱。
  • 口令短语用 EFF 长词表(CC-BY-3.0,要注明出处)。
  • 生成的密码显示精确熵值(log2);用户自己输入的密码用 zxcvbn 3.1.1(MIT)估算强度。
  • 参考 Bitwarden 生成器的选项:每类字符最少几个、排除易混淆字符(I O l 0 1)。

C. 管理界面 ​

别人怎么选:

项目界面技术
KeePassXCQt
BitwardenElectron
KeePassium / Strongbox原生
Padloc(AGPL)有 Tauri 版

用 Tauri 的密码管理器大多是个人小项目。

Tauri v2(MIT/Apache):

  • 版本:最新稳定版 v2.12.5(2026-10),v3 在 alpha。
  • 安全:v1 和 v2 都经过 Radically Open Security 审计。
  • 权限:capability 系统能限制 webview 能调用哪些 IPC。

UniFFI(MPL-2.0,可以作为依赖):

  • 版本 0.32。
  • 使用者:Firefox、Bitwarden SDK、Proton Pass 移动端。
  • 成熟度:可用于生产,但升级时可能有破坏性变化。

推荐的 v1 架构 ​

后台进程:

  • 监听 Unix socket 或 Windows 命名管道,并校验调用方进程。

Native messaging 宿主:

  • Rust 写的 stdio 转发程序,校验 argv[1] 里的 origin。
  • 配对:X25519 + XChaCha20-Poly1305,在界面上确认一次。用的是 KeePassXC 的思路,但代码自己写。

浏览器扩展: Manifest V3,TypeScript,一套代码支持 Chrome / Edge / Firefox。

  • 匹配逻辑放在 Rust 核心里,不放在扩展里。默认按 eTLD+1 匹配,用 psl crate(MIT,包含私有段);另有主机后缀匹配和精确匹配;再加上 PMR 的共用账号域名组。
  • 页面内菜单:封闭 shadow root + 扩展页 iframe + popover,并检测页面篡改。只在用户真实点击后填充,绝不在页面加载时自动填。
  • 提交表单后,在隔离的横幅里提示保存或更新。

生成器: 放在核心里,扩展、管理界面和 agent 都调用同一份。

管理界面: Tauri v2,只是后台进程的一个客户端。

  • 明文留在 Rust 侧,按需显示或复制。
  • 剪贴板由 Rust 负责定时清空。
  • CSP 和 capability 要配严。

要注意的坑 ​

  • 点击劫持: 透明度和可见性监视、封闭 shadow DOM、iframe + popover 顶层、isTrusted 检查。触发填充的那次点击绝不能落在页面自己的元素上。
  • 子域名:
    • 条目 example.com 可以匹配 a.example.com,反过来不行。
    • 用 PSL 私有段,保证 x.github.io 不会匹配 y.github.io。
    • 统一 punycode,检查端口,禁止 HTTPS 降级到 HTTP。
  • iframe: 跨域 frame 只有在它自己的 origin 和凭据匹配时才填,否则给出警告。
  • HTTP Basic 认证: 用 webRequest.onAuthRequired 加 webRequestAuthProvider 权限;代理认证也要处理。
  • TOTP 填充: 处理 one-time-code、"一格一位"的输入框,以及要求把验证码接在密码后面的网站。
  • Native messaging 的限制: 单条消息 1 MB 上限;Linux 的 Flatpak / Snap 浏览器用不了;Windows 上要写注册表。
  • Tauri 打包 macOS .appex: 没有现成办法,要自己写嵌入和重签名的步骤(未核实)。

文档对应提交 80b7c2d · 由仓库 docs/ 自动生成