开源 · MIT · 六端覆盖

你的验证码,
只属于你

本地优先,不登录也能用。验证码密钥先写进设备上的加密保险库,飞行模式下照常出码。 登录只是打开一个开关:把保险库端到端加密后同步到你自托管的 Go 服务——服务端只存密文,拿不到主密码,也解不开任何一条账号。

不需要邮箱、手机号,也没有「先注册以继续」。

开源可审计MIT 协议,每一行都能自己读
零知识加密服务端永远只看到密文
离线可用飞行模式下照常出码
自托管同步Go 写的同步服务,跑在你机器上
核心功能

该有的都有,多余的没有

围绕「把密钥管好」这一件事做扎实。标准兼容、导入方式、跨端一致,以及那些用久了才知道重要的细节。

TOTP / HOTP 全标准兼容

RFC 6238 与 RFC 4226。SHA-1 / SHA-256 / SHA-512、6 或 8 位、自定义周期都能算;别的验证器导出的码,直接搬过来。

RFC 6238 · 4226

二维码与 otpauth URI 导入

扫标准二维码,或粘贴一段 otpauth:// 链接。issuer、label、算法、位数、周期一并读进来,不用手动补字段。

otpauth://

六端一致体验

Android / iOS / Windows / macOS / Linux 共用同一份加密保险库。换设备不用重新扫一遍码,登录同步后直接接着用。

5 个平台 · 1 份保险库

分组、搜索与置顶

几百条账号也不慌:按标签分组、按名称即时搜索、把每天要用的那几条钉在顶部。键盘快捷键也能走完全流程。

标签 · 搜索 · 置顶

自动锁定与剪贴板清除

切到后台或闲置一段时间自动上锁;复制验证码后在设定秒数内清空剪贴板。主密码只存在于内存,不写进磁盘。

内存中的主密码

加密导入导出与备份

导出的备份文件本身仍是密文,只有同一把主密码能解开。明文不落文件、不进云盘,换机迁移不靠截屏和扫码。

密文进 · 密文出
本地优先

不登录,
也能用得很好

第一次打开 Oathkey,你只需要设一个主密码。Argon2id 从它派生出密钥,在本机建一个加密保险库,然后——全部功能立即可用:导入、出码、分组、备份。没有账号体系挡在中间。

想多设备同步时再打开登录。它做的事只有一件:给那份密文找一个存放位置。保险库的本体始终在设备上,服务端拿到的永远是一个解不开的 blob。

登录是可选开关,不是使用门槛。
  • 无账号、无邮箱、无手机号、无设备绑定
  • 断网、飞行模式、内网隔离环境全部照常工作
  • 卸载同步服务,本地数据一点不受影响
vault.oathkey 已解锁
GGitHub482 913
GGoogle205 774
CCloudflare661 038

3 条记录 · 存储于本机 · 文件已加密

点一下「锁定」看看状态切换:数据没动,只是钥匙被收起来了。

加密原理

密钥怎么变成密文

整条链上只有两端:你的设备,和一台只负责存字节的服务器。中间没有「可信第三方」这个位置。

紫色链条 · 仅设备可见 灰色链条 · 服务端可见
01
主密码由键盘输入,只存在于内存;不落盘、不上传
设备
02
Argon2id → masterKey加盐 KDF,m = 64 MiB / t = 3 / p = 4,拖慢 GPU 爆破
设备
03
HKDF-SHA256 拆出两把钥匙 authKey 向服务端证明「你知道主密码」vaultKey 真正加密保险库,从不离开设备
设备
04
XChaCha20-Poly1305 → 密文每次写入用 24 字节随机 nonce,AEAD 自带完整性校验
设备
越过这条线,服务端才开始看得见
05
密文上传 → 服务端数据库只收到密文 blob、随机 ID 与版本号;没有主密码,没有 vaultKey
服务端

authKey 与 vaultKey 由同一把 masterKey 派生,但用途完全隔离:服务端拿到前者也推不出后者。

六端支持

一台设备开始,六台设备接着用

原生客户端共享同一份加密数据格式。以下为最低版本占位,具体以首个预览版的发布说明为准。

Android

Android 8.0+ / API 26

Material 3 · 生物解锁

iOS

iOS 15.0+ / iPhone & iPad

SwiftUI · Face ID

Windows

Windows 10 1903+ / x64 & ARM64

Windows Hello

macOS

macOS 12 Monterey+ / 通用二进制

Touch ID · 菜单栏速取

Linux

glibc 2.28+ / AppImage · deb · rpm

Wayland · 密钥环集成

浏览器扩展

Chrome / Edge 116+ · Manifest V3

一键填充 · 与原生端共用 Rust core
产品演示

从扫码到出码,四步走完

下面是界面示意动画,用来说明产品如何工作。官网不接收密钥、不计算验证码,画面里的数字都是预设的演示值。

Oathkey 本地模式

扫一次码,密钥就只留在这台设备上。

这是界面演示动画:画面中的验证码、账号与密文均为预设示意值,不是真实计算结果。本页没有输入框、不读取剪贴板、不发起任何网络请求;真实的密钥处理只发生在你安装到设备上的客户端里。

下载

拿一份,自己跑起来

客户端尚未完成签名发布,下面的按钮暂时统一指向 GitHub Releases 占位页。

预览版本,发布通道筹备中。各应用商店的上架状态会在正式发布后更新,此处不冒充已上架。

自托管同步服务一个 Go 二进制 + 一个卷,没有外部依赖
docker run -d --name oathkey-sync \
  -p 8787:8787 \
  -v oathkey-data:/data \
  -e OATHKEY_DATA_DIR=/data \
  ghcr.io/oathkey/sync:latest

镜像名、端口与环境变量为占位示例,以正式发布的自托管文档为准。服务只接收与返回密文 blob。

常见问题

先把不好听的部分说清楚

忘记主密码怎么办?

找不回来,我们也没法帮你找。主密码不上传、不落盘,服务端没有副本,因此不存在「重置密码」的通道——零知识架构里留这个后门就等于没加密。可行的只有两条路:用事先导出的加密备份配合原主密码恢复,或从一台仍处于解锁状态的旧设备重新导出。这是刻意的取舍,请在设主密码时就用密码管理器记好。

换设备如何迁移?

在新设备登录同一个自托管服务,密文同步下来后用原主密码解锁即可;或者完全离线,用加密备份文件导入。两种方式都不需要把明文交给任何服务器,也不涉及重新扫一遍二维码。旧设备不需要在线,密钥本来就是随密文一起搬走的。

不登录会丢数据吗?

不会。保险库本体就在设备上,登录只影响「是否额外多一份云端密文副本」。真正会删掉数据的是卸载应用或清除应用数据,以及设备本身损坏且没有备份。所以哪怕一直不登录,也建议定期导出一份加密备份放到你信得过的地方。

服务端被拖库会怎样?

攻击者拿到的是一堆 XChaCha20-Poly1305 密文、随机 ID 和版本号。没有 vaultKey 解不开,也推断不出账号数量、服务商或归属人;authKey 只是个认证凭据,推不出加密密钥。需要做的是轮换服务端凭据、检查日志,本地数据不受影响。

与 Google Authenticator 的区别?

后者把密钥存在设备里、迁移主要靠扫码或账号云同步,且缺少可用的加密备份与检索能力。Oathkey 的保险库始终是密文,支持分组搜索、置顶、自动锁定、加密导入导出,六端共用同一份数据;同步走你自己部署的服务,服务端零知识。另外,代码是 MIT 开源的,可以自己审。

数据到底存在哪里?

只有两个位置:本地设备上的加密数据库(密文),以及可选的自托管 Go 服务里一份同样加密的 blob。没有第三种位置,没有分析 SDK,没有遥测上报。主密码只在你解锁时存在于内存中,锁定后立即丢弃。