Lockra:电脑和手机通用的开源两步验证与密码管理器

0 阅读18分钟

两步验证码通常大家习惯存在手机里。手机换了或者丢了,账号要重新绑定或者找回。微软的 Authenticator 和 Google 身份验证器倒是都能云同步和恢复,只是不支持细粒度的密钥设置(比如加密算法、时间间隔),也没有电脑版:坐在电脑前登录时,还是得先把手机拿出来。

Lockra 是我做的一个开源(Apache-2.0)、免费的两步验证器和密码管理器,主要用在电脑上:Windows、macOS 和 Linux 都有安装包,Android 手机上也有同一个应用(iOS 版在计划中)。验证码和密码保存在每台设备的加密文件里,Lockra 没有用户账户,也没有能读取你账号和密码的服务器。

它主要做这几件事:

  • 多端通用的两步验证码:电脑和手机上是同一批账号,同一时刻显示同一个验证码,断网也照样算得出来。
  • 密码管理:登录项和验证码放在同一个保险库里,一个主密码打开,一份备份全部保存。
  • 浏览器里自动填充:Chrome、Edge 和 Firefox 的扩展填入用户名和密码,分几页的登录也只要填一次。
  • 验证码关联填充:登录项关联了验证码时,填完密码接着填验证码,愿意的话填好就自动提交。
  • 同步、迁移和备份恢复:设备之间端到端加密同步;能从 Google 身份验证器和 Microsoft Authenticator 迁入,也能迁回去;自动备份到你选的文件夹,需要时合并或整体恢复。

电脑和手机上的 Lockra 验证码页:左边是手机,右边是电脑,两边的密钥相同,同一时刻的验证码也相同

本文截图和录屏中的账号、网站都是虚构的示例数据。

一分钟看 Lockra

Lockra 文档首页有一段一分钟的录屏,演示了一次完整的使用。它从注册一个示例网站开始:扩展按网站的密码规则生成密码,填好密码和确认密码两个框,Lockra 随即保存这个登录项。接着截下网站开启两步验证时显示的二维码,Lockra 从剪贴板读出它,关联到这个登录项。登录时从输入框旁的菜单选账号,下一页的密码自动填入,然后填入验证码并提交。最后是命令面板、密码生成器和几套主题。录屏里二维码截屏的闪光、指针和蓝框是后期加上的。

Lockra 一分钟录屏:用生成的密码注册、添加验证码,再分几页登录

多端通用的两步验证码

验证码页最上面是「最近使用」:最近复制过的账号以大号字显示验证码,圆环里是剩余秒数,旁边是下一个验证码。下面按分组列出所有账号,筛选按钮可以只看「收藏」、某个分组或「未分组」,列表也可以换成卡片。

「最近使用」和「保险库状态」两张卡片下面,是筛选按钮和按分组排列的账号

复制只要点一下那一行,或者用方向键选中后按 Enter。屏幕下方的提示会写明复制的是哪个账号;30 秒后,如果剪贴板里还是这个验证码,Lockra 就把它清掉,之后复制的其他内容不受影响。在 Windows 上,验证码不会进入剪贴板历史和云剪贴板。每个验证码的最后 5 秒会变成琥珀色,下方同时显示下一个。

操作上也支持按键操作:按 / 跳到搜索框,输入几个字母后按 Enter,复制的就是第一个匹配项。在应用的任何页面按 Ctrl K(macOS 上是 ⌘K)会打开命令面板,同样输入名字、按 Enter 复制。Ctrl L 立即锁定,Ctrl N 手动添加账号。

命令面板:输入 cl,只剩 Cloudflare 一个账号,按 Enter 复制它的验证码

外观有 8 个主题,新安装默认用本文截图里的「澄空」,系统切到深色时跟着换成「澄空 · 夜」。

安装包覆盖 Windows 10 和 11、macOS 11 及以上和 Linux 系统,x64 与 ARM64 都有(ARM 版 Windows 需要 11)。文档给每种系统准备了一条命令的安装脚本,安装前会用该版本的 SHA256SUMS 校验。之后有新版本,标题栏会提示,应用内更新只接受带 Lockra 签名的安装包。

解锁和锁定

每次都输入主密码的话可能也不太方便。在带 Touch ID 的 Mac 或者支持 Windows Hello 的电脑上,打开「设置 › 安全 › 使用 Touch ID 解锁」(Windows 上是「使用 Windows Hello 解锁」),之后解锁页会自动请求指纹、面容或 PIN。主密码始终可以解锁。

「设置 › 安全」:Windows Hello 解锁开启后,「在本机记住」也一并打开;自动锁定和清空剪贴板的时间在这里调

5 分钟没有操作,Lockra 就锁定,时间可以在 1 到 60 分钟之间调,也可以设为从不。锁定会从内存里清掉解密后的账号。要查看某个账号的密钥,需要再输一次主密码,2 分钟后自动隐藏;显示期间,Windows 和 macOS 会把窗口排除在截屏和录屏之外。

密码管理

登录项和验证码放在同一个保险库里:一个主密码打开,一份备份全部保存,电脑和手机上都能用。每个登录项有标题、用户名和邮箱、密码、适用的网站、备注和自定义字段,还可以关联一个验证码账号;在电脑上,详情栏里同时显示密码和关联账号的当前验证码。

密码页:按分组排列的登录项,右侧是选中的 GitHub 登录项,显示用户名、以圆点显示的密码和关联账号的验证码

每个登录项可以单独选保护级别:「直接填充」是默认的;「填充前验证」要先输入主密码,或者用 Touch ID、Windows Hello、指纹验证,才会填充或显示;「不交给扩展」的登录项,浏览器扩展完全看不到,搜索里也没有。重要的登录项建议选「填充前验证」。改了密码,旧密码会进入这个登录项的密码历史。

密码生成器在应用里任何地方按 Ctrl G 打开,可以生成 4 到 128 个字符的随机密码,也可以从 EFF 的词表里取 3 到 20 个单词组成口令。从登录项的表单打开时,它会按 Lockra 已知的这个网站的密码规则生成。命令面板(Ctrl K)也能搜到登录项,输入名字按 Enter 就复制密码。

原来存在浏览器或其他密码管理器里的密码,可以从 Chrome、Edge、Firefox、Safari、Bitwarden、1Password、LastPass 和 KeePass(KDBX 4)导入,也可以导出成 KeePass 数据库或明文 CSV 文件。

手机上的「密码」页,以及 GitHub 登录项的页面:用户名、密码和验证码

手机上可以查看、复制和编辑登录项。手机没有浏览器扩展,也不会把密码填进别的应用,需要时复制后粘贴。

浏览器扩展:自动填充密码和验证码

扩展适用于 Windows、macOS 和 Linux 上的 Chrome、Edge 和 Firefox。它本身不保存任何密码:每次填充都经过端到端加密的本机通道,向同一台电脑上正在运行的 Lockra 请求,能不能填、填哪个登录项都由 Lockra 决定。第一次使用时,扩展和 Lockra 各显示一个 6 位代码,核对相同后在 Lockra 里输入主密码批准,配对一次即可。

填充可以从工具栏的弹窗、快捷键 Ctrl Shift L,或者点输入框时出现的 Lockra 菜单开始。先输用户名、下一页再输密码的登录,只要在第一页填一次:下一页出现密码框时,Lockra 接着填入同一个登录项的密码;登录项关联了验证码的话,再把验证码填进之后页面的验证码框。开启「填充后自动提交」后,填入密码才提交表单,关联了验证码的登录项要等验证码填好才提交,只要用户名的那一步不提交。

提交表单时,扩展会问要不要把新密码保存到 Lockra,或者更新已有登录项的密码。在注册表单里,它按网站的密码规则生成密码,填好所有新密码框,并立即在 Lockra 里添加这个登录项。浏览器自带的保存密码提示可以交给 Lockra 接管;浏览器在输入框下方列出它保存的密码时,Lockra 的菜单改在输入框上方打开。

扩展目前还没有上架商店:Chrome、Edge 和 Brave 从 Lockra 的发布页下载扩展包,以解压方式加载;Edge 加载项和 Firefox 附加组件的页面还在准备,Firefox 版要等页面上线才能安装。扩展只在 Lockra 运行时可用,所以 Lockra 可以在关掉窗口后留在托盘里。

另外,在「设置 › 通用 › 快捷搜索」里可以设一个全局组合键,在任何应用上面打开 Lockra 的命令面板,复制登录项的用户名、密码或验证码。Wayland 上应用不能设全局快捷键,要在桌面环境里把 lockra-desktop --palette 绑定到一个按键。

迁入、迁出和备份恢复

账号在 Google 身份验证器里的话,先在手机上依次轻点「转移验证码 › 导出验证码」,它会为选中的账号生成一组二维码。用另一台设备拍下这些二维码或者保存为图片,再把图片拖进电脑上 Lockra 的窗口。

导入预览:这批导出码共两张,Lockra 提示还缺第 2 张;使用 MD5 的旧账号标为不支持

保存之前,Lockra 先列出预览:哪些账号是新的,哪些已经在保险库里,哪些同名但密钥不同,哪些用了不支持的算法,一批导出码里还缺哪一张。确认后才保存。

Microsoft Authenticator 没有导出功能。只有在已 root 的 Android 手机上,Lockra 才能读取它的数据库,工作和学校账号无法迁出。往回迁不需要 root:Lockra 能生成给 Google 身份验证器的迁移二维码,也能给 Microsoft Authenticator 的每个账号单独生成一张。

备份是一个加密的 .lockrabackup 文件,在「备份」页随时可以手动保存。更推荐打开「自动备份」:选一个文件夹,此后每次修改 3 秒后,Lockra 就往里写一份新的备份,默认只留最近 10 份。文件夹选在 OneDrive、Google Drive 或 iCloud 云盘的同步目录里,备份就由网盘带到别处,Lockra 自己不用联网。

备份页:自动备份写进 OneDrive 的同步文件夹,保留 10 份;恢复时可以合并,也可以整体替换

在电脑上开始同步

打开「设置 › 同步」,选择「开始同步」。「存储类型」默认是「Lockra 中继」,服务商默认是「Lockra 内置中继」,地址和密钥都不用填。确认这台设备的名称,输入主密码,再选择「开始同步」。

在电脑上开始同步:默认使用 Lockra 内置中继,表单里只剩设备名称和主密码

第一次用,建议从内置中继开始:什么都不用准备,手机扫码就能加入。如果手上已经有 NAS、存储桶等资源,就可以按照文档换成自己的存储或中继服务器,做法在后面「自己部署同步」一节。

开始同步后,「设置 › 同步」会提醒保存恢复密钥,格式是 LKS1- 加 14 组、每组 4 个字符。它要和主密码分开保管,只有所有设备都丢失、需要恢复同步空间时才用得上。选择「显示恢复密钥…」并输入主密码可以查看,也可以「保存到文件…」;保存或者选择「我已记下」之前,这条提醒会一直显示。

同步开启后的「设置 › 同步」:顶部是恢复密钥的提醒,下面是存储、本机名称和设备列表

手机扫码加入

Android 版适用于 Android 8 及以上的 ARM64 手机,从 GitHub 发布页下载 APK 安装(Google Play 版正在准备上架)。手机上的验证码页和电脑上一样,几处差别和手机的用法有关:切到其他应用、回到主屏幕或锁屏时,保险库立即锁定;Lockra 的界面始终不能被截屏或录屏;开启「使用指纹解锁」后,保险库的密钥保存在手机的安全硬件里。

Android 应用的验证码页、添加账号页和同步页

在电脑上选择「邀请其他设备」,输入主密码,或者用 Touch ID、Windows Hello 验证,Lockra 会显示一个二维码,两分钟后自动隐藏。用中继同步时,二维码旁边还有「复制配对链接」。

电脑上的邀请:用手机扫描二维码,或者复制配对链接发给新设备

手机上打开「设置 › 同步 › 加入已有的同步」,输入这部手机自己的主密码,选择「扫码加入」,扫描电脑上的二维码。新装的手机可以在欢迎页选择「从同步加入」。手机里原有的账号会并入同步空间,电脑上的账号随后同步过来。

手机上的「加入已有的同步」:可以扫码、粘贴配对链接,或者用恢复密钥恢复

两台设备不需要同一个主密码,各自保留自己的。手机开了指纹解锁时,加入和邀请都可以用指纹代替主密码。

两台设备怎么保持一致

两边的验证码一样,是因为密钥一样。验证码由每个账号的密钥和当前时间在本机算出,不需要网络;同步做的只是把账号连同密钥带到另一台设备上。所以同步完成以后,即使断网,两边显示的验证码也相同,前提是两台设备的时间都准。

用中继同步时,解锁的设备会在中继上保持一个等待中的请求,另一台设备一写入,改动大约一秒后就到。除此之外,Lockra 在前台时每分钟同步一次,每次修改 3 秒后也会同步,并提示改动来自哪台设备,比如「已从 Pixel 8 同步:新增 2 个,修改 1 个」。

两台设备同时改动也不会互相覆盖:各自新增的账号都保留;同一个账号在两边都改了,以较晚的修改为准;删除会同步到所有设备,除非删除之后它又被改过。

登录项和账号在同一个同步空间里同步,浏览器扩展的网站名单也跟着同步。

自己部署同步

不想让同步经过开发者的服务器,有两条路:放在你自己的存储上,或者自己运行一个中继。

自己的存储可以是 S3 兼容的存储桶(AWS S3、Cloudflare R2、Backblaze B2、阿里云 OSS、腾讯云 COS、MinIO),也可以是 WebDAV(坚果云、Nextcloud、群晖 NAS)。在「开始同步」里选好存储类型和服务商,Lockra 会填好地址和访问方式,剩下要填的是存储桶、区域或服务器地址,以及账号和密钥。地址必须以 https:// 开头,本机地址除外;凭据存进加密的保险库,之后不再显示。

用群晖 NAS 同步:存储类型选 WebDAV、服务商选群晖 NAS,填服务器地址、用户名、密码和文件夹

NAS 或 MinIO 用的如果是自签名证书,手机会连不上:Android 版只信任系统自带的证书颁发机构,不认用户自己安装的证书。给域名申请一张 Let's Encrypt 这类公开签发的证书就行;电脑端则信任操作系统信任的证书。

也可以自己运行中继,需要一台设备能访问的 Linux 服务器(x64 或 ARM64,小型虚拟机就够),一个域名,以及中继前面的 HTTPS,因为 Lockra 只通过 https:// 连接中继。仓库里有一份 Docker Compose 文件,同时启动中继和 Caddy,由 Caddy 从 Let's Encrypt 申请证书。把域名解析到服务器、开放 80 和 443 端口之后,在服务器上运行:

git clone --depth 1 \
  https://github.com/sunerpy/lockra
cd lockra
export RELAY_HOST=relay.example.com
docker compose \
  -f deploy/relay/compose.yaml up -d

RELAY_HOST 是中继要用的域名。第一次启动会先在服务器上从源码构建中继镜像,然后 Caddy 为这个域名申请证书。停止并移除容器用 docker compose -f deploy/relay/compose.yaml down;同步空间保存在 Docker 卷 relay-data 里,删掉这个卷,中继上的同步空间就没了,设备上的账号不受影响,下次同步时会重新写入。

中继跑起来以后,在第一台设备的「开始同步」里保持「Lockra 中继」,服务商选「自建中继」,填上中继地址。邀请码和配对链接里带着这个地址,其他设备只需扫码或粘贴链接加入。

自建中继:服务商选「自建中继」,中继地址填自己的域名,其余步骤和内置中继相同

中继能看到什么

对设备来说,中继只是另一种存储,写进去的文件和写进 S3、WebDAV 的完全相同:账号、密钥、设备名称和时间离开设备之前已经用 XChaCha20-Poly1305 加密,文件大小按 4 KiB 取整。中继能看到这些加密文件、同步空间里有几台设备、它们什么时候写入,以及连接时的网络地址;看不到账号、密钥、设备名称、恢复密钥和主密码。

内置中继的服务器即使被取走或被要求交出数据,能交出的也只有加密文件、几个标识和设备身份值的指纹,无法解密你的数据。

实现上的几个选择

Lockra 的核心是 Rust 写的(lockra-core 等几个 crate),不含任何平台代码:验证码计算(RFC 4226 / RFC 6238)、保险库加密、Google 迁移码和 Microsoft Authenticator 数据库的解析、备份、同步都在这里。桌面端和 Android 端都是 Tauri 2 的壳,界面是 React,钥匙串、剪贴板、生物识别、应用内更新和同步传输这些原生能力,以端口的形式由壳注入核心。

保险库是一个文件:主密码经 Argon2id(64 MiB 内存、3 轮)派生密钥,内容用 XChaCha20-Poly1305 加密,任何一个字节被改动,Lockra 都拒绝打开。

同步这部分最费心思的是「没有锁」。每台设备只写自己的那一个快照对象,别的设备只读;存储里的状态是所有快照的合并。因为没有两台设备会写同一个对象,所以不需要锁,也不依赖条件写。WebDAV 本来就没有可靠的条件写,这样 S3 和 WebDAV 的行为就一致了。合并按账号「后写者胜」,时间戳用混合逻辑时钟 (wall_ms, counter, device):跟着墙钟走,但在一台设备上永不回退。HOTP 的计数器是例外,取所有版本里的最大值,已经出现过的验证码不会在任何设备上再出现。合并满足交换律、结合律和幂等。

浏览器扩展这边,扩展只经浏览器的 native messaging 和同一台电脑上的 Lockra 通信,内容端到端加密,不向别的地方发送任何东西。网页的地址以浏览器报告的为准,从不采信网页对自己的描述;网页也不能替你点 Lockra 的菜单,菜单显示满 300 毫秒、没被遮挡也没移动时,点击才算数。1 分钟内取了超过 10 个密码或验证码之类过于频繁的请求,会让这个扩展被暂停,直到你在 Lockra 里恢复它。

S3 兼容存储和 WebDAV 通过 OpenDAL 访问;中继是单独的 lockra-relay 二进制,不链接进应用。测试方面,crate 的行覆盖率下限是 90%,前端各包是 85%,低于下限构建就失败。

适合谁

如果你主要在受信任的电脑上使用两步验证码和密码,又想让 Android 手机上有同一批账号和登录项,不想每次都在电脑前掏出手机看验证码,也不想把密码交给某个在线账户,那么 Lockra 适合你。

下载和文档

• 文档(安装、密码、浏览器扩展、同步、自建中继):firlab.app/lockra/zh

• 密码与浏览器扩展:firlab.app/lockra/zh/p…

• 源代码和安装包:github.com/sunerpy/loc…