层级:协议哲学。 派生机制见Me2eM:从种子短语到身份;保管实践见什么都不存的密码管理器。
你使用的每项服务都为你提供数据的”安全存储”。保存联系人——我们会同步。上传照片——我们会备份。输入银行卡——我们会记住以便下次方便使用。
Me2eM做的是相反的事:我们不存储你的种子。任何地方都不。以任何形式都不。
不是在云端加密存储。不是在浏览器中加密存储。不是部分存储。不是”可选带安全声明”。永远不,任何地方都不。
如果你丢了手机、重装浏览器、清除所有数据、在系统更新中沉没——你的种子不会受损,因为它从未在设备上。它在纸上、在你的保险箱里、在你脑海中。它会一直留在那里。
这篇文章讲的是为什么这是深思熟虑的架构决策,你为此付出的代价,以及为什么这个代价比替代方案更诚实。
种子是什么——用一段话说清楚
种子短语是来自 2048 元素固定字典的 12 或 24 个词。这些词编码了 128–256 位熵加上校验和。
从种子短语,用户的全部密钥树被确定性派生:根身份、隔离的上下文(Handle)、设备组件(SubHandle)、服务密码、加密密钥。不存储——计算,毫秒级,从相同的词得出。
12 个词 (纸面)
└─ 32 字节 seed (RAM 中瞬时存在)
└─ IdentityPrivateKey (HKDF)
└─ HandlePrivateKey("work") ← 按需计算
└─ HandlePrivateKey("personal") ← 按需计算
└─ SubHandlePrivateKey(...) ← 按需计算
一个种子 = 整个密钥宇宙。不需要其他载体。
为什么不存储种子——四个原因
原因一:存储成为目标
无论你把种子存储在哪里——云端加密、浏览器内、受保护的 enclave——那个地方都成为高优先级目标。不是针对你个人——而是针对存储运营商:所有用户的信封集中在一个地方。
慢速 KDF(Argon2id)只是提高尝试成本——它不消除威胁。攻击者离线工作,无限时长,并行处理所有信封。弱或中等密码会被暴力破解——这是经济问题,不是能力问题。
而且——最关键的是——信封没有撤销机制。被盗的信封无法”注销”。它将永远成为目标,只要它存在。
原因二:去中心化下无法撤销
去中心化系统中的撤销是利益的交汇:
- 想瞬间撤销被盗种子? 需要一个中心注册表,所有验证器都检查它。中心注册表 = 集中式故障点和信任点。违背协议哲学。
- 想更改种子? 用户必须发布新种子并通知所有联系人。联系人需要重新验证。没有基础设施——不可行。
在经典系统(JWT、OAuth)中撤销是可能的,因为服务器控制令牌签发。在去中心化系统中根密钥存在于用户手中——没有人能撤销它:没有注册表,没有中心,没有按钮。
不要混淆层级。种子不可撤销——但分支可撤销。 证明链允许所有者通过单个 jti 撤销,在所有服务中同时瞬间烧毁派生密钥——Handle 和子 Handle。去中心化不会回归:被撤销的不是根,而是根签发的委托。机制见关于即时撤销的文章。
原因三:虚假的安全比没有更糟
如果种子存储提供”云端安全备份”——用户开始认为种子不需要再写在纸上。而且他们想对了:既然有备份,为什么还要写?
但备份不是纸的替代品:
- 服务可能关闭(初创公司会倒闭)。
- 服务可能被攻破(没有人保证永恒安全)。
- 用户的密码可能很弱。
- 输入密码的设备可能已被入侵。
如果备份消失了——用户连同已经丢弃的纸一起丢失了种子。这是最坏的结果:双重故障点,而用户以为只有一个。
原因四:透明度是特性,不是缺陷
确定性派生提供了一个如果种子存储在别处就无法获得的属性:
用户永远知道密钥在哪里。 不是”在我们服务的某个云端”,不是”在加密备份中”,不是”在设备上”——而是在纸上。如果纸完好——身份就完好。如果纸丢了——身份就丢了。零不确定性。
用户获得什么
| 属性 | 如何工作 |
|---|---|
| 完全不依赖服务 | 服务可能消失——种子仍在。 |
| 无数据泄露 | 无可泄露——密钥是计算得出的,不是存储的。 |
| 无需同步的多设备 | 新设备上的同一种子 = 同一棵树。 |
| 无需恢复密码 | 种子 = 密码。密码 = 种子。零恢复实体。 |
| 完全匿名 | 无邮箱、无电话、无银行卡——种子不与个人绑定。 |
你付出的代价
诚实要求列出代价:
| 代价 | 原因 |
|---|---|
| 种子丢失 = 一切丢失 | 无恢复、无重置、无”忘记密码——发短信”。种子丢失——身份丢失。 |
| 责任在用户 | 写在纸上、安全存储、不拍照、不存云端笔记。 |
| 种子不能更改 | 无”重置密码”。如果种子被泄露——需要新身份(新种子),所有连接重建。 |
与替代方案对比
| 模型 | 恢复 | 脆弱性 | 服务依赖 |
|---|---|---|---|
| 服务密码 | “忘记密码?“→邮箱→短信→新密码 | 短信拦截、邮箱被攻破、内部人员 | 完全 |
| 云端加密种子 | 密码→云端→解密 | 云端被攻破 + 密码暴力破解 | 部分(需要云端访问) |
| 纸上种子(Me2eM) | 仅物理纸张 | 纸张需要存储 | 零 |
云端恢复是方便的选项,但其安全性取决于用户的密码。如果密码弱——离线暴力破解信封只是时间问题。如果密码强——用户需要像记住种子短语一样仔细记住它。这是 trade-off,不是解决方案。
用户应该做什么
创建种子短语后的实用清单:
✅ 必须:
- 用笔在纸上写下 12 个词——永远不要以数字形式。
- 读你写的内容。每个词检查两遍。
- 如果混乱——拿一张新纸重新写。
- 把纸存在不会因水、火、时间而毁灭的地方。
- 对于关键身份——金属板雕刻和另一份异地副本。
❌ 永远不要:
- 不要拍照种子短语。
- 不要存在云端笔记中。
- 不要发送到自己的 messenger。
- 不要存在密码管理器中——vault 存储正是我们要远离的模型(原因一)。
- 不要给任何人看——包括”支持”(他们永远不会要求)。
种子不是密码。种子是身份的唯一载体
密码可以重置。种子短语不行。
密码可以更改。种子短语不行(但可以创建新身份)。
密码由服务以哈希形式存储。种子短语不存储在任何地方——不在我们这里,不在任何其他地方,除了用户的纸。
区别是根本性的。密码是访问服务器账户的授权秘密。种子是派生整个用户身份的主秘密。
谁适合这种方法
✅ 适合:
- 重视主权、不信任集中式存储的用户。
- 设备自主运行无需云端的 IoT 场景。
- 需要确定性的开发者(所有设备上同一种子 = 相同密钥)。
- 需要匿名的用户。
❌ 不适合:
- 会丢失纸张且无法恢复的用户。
- 需要集中式撤销和恢复的场景。
继续阅读
- 为什么种子短语 UX 如此偏执——@me2em/react 包如何弥补人为错误
- Me2eM:从种子短语到身份——确定性密钥树
- 什么都不存的密码管理器——同样的保管模式在实践中
- 即时撤销:无状态世界中的撤销——为什么撤销不需要存储种子:分支可撤销,根不可撤销
@me2em/core在 npm 上——实现