全部文章

阅读约 7 分钟

为什么你的密钥永不离开设备

在 CardanoWall 中,签名、封存和解密全部在本地完成——网关负责发布证明、存储密文,但其设计就是永远不接触你的私钥。

在 CardanoWall 中,你的私钥始终留在自己的设备上。负责签名、封存、试探解密和验证的软件都在本地运行;托管网关的设计宗旨,就是永远不接收你的身份种子、签名密钥、接收方密钥,以及用于解密封存文件的任何材料。

即便没有这些机密,网关仍有大量工作可做。它可以给出报价、接收已加密的密文用于存储、提交 Cardano 交易、为记录建立索引、追踪你的余额。这些都不需要那些用来证明作者身份或打开封存载荷的密钥。这种分工是刻意为之:服务帮你把证明送出去,机密则由你自己保管。

我们说的是哪些密钥?

一个 Label 309 身份从单个值起步:一个 32 字节的「身份种子」。从这颗种子出发,任何符合标准的软件都能派生出该身份实际使用的密钥,它们承担三种角色:

  • 一个用于「签名」记录的 Ed25519 密钥;
  • 一个用于「接收」经典封存记录的 X25519 密钥;
  • 一个用于接收后量子封存记录的混合后量子密钥。

派生过程是确定性的。同样这 32 字节,在任何符合标准的客户端中都会产出同样的三对密钥。正因如此,种子才具有可移植性——也正因如此,它才是唯一值得严加守护的东西。任何人只要持有种子,就能恢复该身份、以它的名义签名,并解密寄给它的封存记录。所以种子必须保密,以下的一切都由这一点推导而来。

客户端在本地做什么?

凡是会接触到私钥的操作,都由客户端来处理:

  • 生成或导入身份种子;
  • 从中派生签名密钥和接收密钥;
  • 对记录签名;
  • 在上传前加密文件;
  • 构建封存信封中按接收方划分的密钥槽,用以封装内容密钥;
  • 对收到的记录做试探解密,找出寄给你的那些;
  • 解密密文并重新计算明文哈希;
  • 验证签名和记录结构。

Web 应用、桌面应用、命令行工具,以及任何基于 SDK 构建的软件,在如何存储密钥、如何解锁密钥上各有不同。但贯穿它们的原则始终不变:私钥材料不会被发送到网关。

那网关又做什么?

网关运行的是发布流水线。它可以:

  • 计算报价;
  • 接收已加密的密文,并返回一个内容寻址的 URI;
  • 接受一份准备好的证明记录;
  • 提交 Cardano 交易并等待确认;
  • 处理链重组,并在发布永久失败时自动退款;
  • 把记录索引进一个共享的信息流;
  • 追踪你的账户余额;
  • 对外暴露其 API 并发出生命周期事件。

这些都是实打实的工作,也是绝大部分运营任务所在。但其中没有任何一项需要能解密你封存内容的密钥。网关是一个传输与运营层。它不是你的身份保险库,其设计也无意扮演这一角色。

这种分离为什么重要?

因为一份证明应当无需信任协助创建它的服务,就能被验证。

如果某个托管服务持有你密钥的唯一副本,这个服务就会成为你的信任根。一旦它停止运营、变更条款、遭遇入侵,或冻结了你的账户,你签名、解密乃至验证的能力都可能受制于它。这正是 Label 309 着力规避的处境。

一份 Label 309 记录可以从公开数据中得到验证。验证方只需要交易元数据、可选的内容字节,以及一个公开的 Cardano 浏览器——全程不需要任何签发服务器。封存记录可由密钥持有者打开。已签名记录可对照其签名密钥进行核验。网关能让发布变得轻松许多,但按照设计,它不会仅仅因为协助过把一份载荷送上链,就有能力读取其中妥善封存的内容。

这正是「一个服务告诉你它有一份证明」和「一份能独立成立的证明」之间的区别。

网关能读取我的封存文件吗?

如果客户端正确地封存了内容,那就不能——网关能看到的永远只有密文。

下面说明封存记录是如何组织的。公开的链上记录承诺的是「明文哈希」——这个哈希,加上区块时间,就构成了时间证明。加密载荷本身永远不上链;它存放在一个内容寻址的 URI 处(例如 ar://)。内容密钥会被封装给一个或多个接收方公钥,每个接收方对应一个密钥槽。接收方(或发送方)取回密文,在本地解密,并重新计算明文哈希,以确认它与链上承诺相符。

网关能看到一份封存记录的存在,也能观察到密文大小、上传时间、账户活动、交易状态和公开元数据。但它的设计无法看到明文,而且没有正确的私钥,密文就始终不可读。这里有两点诚实的提醒:封存保护的是机密性,而非匿名性——可观察到的元数据仍然是元数据;而一个解密了文件的接收方,事后总能选择泄露明文。加密保护的是传输途中和静态存储中的字节,而不是一个获授权的读者接下来会做什么。

网关能伪造一份有效的证明吗?

它在设计上做不到让一份无效的证明通过独立验证。

验证方会检查链上记录、记录结构、各项哈希、各项签名,以及——对于一份它能打开的封存记录——重新计算出的明文哈希。如果某个网关在交易上撒谎、篡改了记录字节、丢掉了一个签名,或指向了与所承诺哈希不符的字节,独立验证方应当能够发现。

这是一个精确的承诺,不该被夸大。一个网关在寻常的运营层面「仍然」可能行为不当:它可能发布失败、延迟交易、返回错误、误报自身状态、发生宕机,或给你糟糕的体验。它不该做到的,是把一份无效证明变成一份能对照公开数据干净通过验证的证明。便利性可能失灵;但密码学层面的主张并不依赖网关是否诚实。

Web 应用具体又如何?

Web 应用是运行在浏览器中的软件,这一点塑造了它的信任模型。

相关的边界包括浏览器、加载进来的应用代码、任何已安装的扩展、设备本身,以及解锁流程。浏览器固然便利,但它和一个桌面保险库,或一个由你自己掌控构建产物的命令行工具,并不是同一种环境。在一个「已解锁」的会话中,一段恶意脚本可以读取内存中的机密;严格的内容安全策略、最少量的脚本,以及一个显式的解锁步骤,能降低这种暴露,但没有哪个 Web 应用敢声称能将其彻底消除。

这正是存在专门桌面客户端的原因之一,它面向那些希望本地存储、并对密钥保管方式拥有更紧密掌控的人。这条不变量贯穿每一个客户端——网关不需要你的私钥——尽管每个客户端保护这些密钥的方式各不相同。要更完整地了解这条界线划在何处,请看 CardanoWall 能看到什么、不能看到什么

桌面应用又如何?

CardanoWall Desktop 是一个开源的跨平台应用,从一开始就围绕一个本地加密保险库构建。

一个 Rust 核心掌管身份保险库、密码学、同步引擎、试探解密和验证,而 webview 只负责渲染界面。种子和派生出的私钥不会作为普通的 JavaScript 字符串交给 webview;当内容需要预览时,解密后的字节会通过一条专用通道流式传给视图,而不是以字符串形式穿过页面。机密既不会发送到网关,也不会进入渲染层。

这种架构收窄了攻击面,却没有将其抹除。一个被攻陷的操作系统、一个恶意依赖、一个键盘记录器,或经用户批准安装的恶意软件,仍然可以击溃本地安全防线——这是任何桌面钱包都背负的同样诚实的限度。把密钥挡在网关和渲染层之外是一项有意义的改进,而非针对一台完全被攻陷主机的保证。要了解它的具体运作方式,请看 CardanoWall Desktop 概览和离线证明

命令行工具和 SDK 又如何?

它们之所以重要,是因为它们让同样的模型脱离网站也能用。

开发者可以把种子留在本地、在本地对记录签名、在本地封存文件,并通过任意网关提交。持续集成系统可以用范围受限的 API 凭证来发布,同时把身份材料置于团队自己的掌控之下。一家公司可以构建自己的客户端,或把 Label 309 融入既有软件。无论你选用哪种接口,这种分工都保持不变:网关负责发布,客户端持有机密。

命令行工具和 SDK 都是开源的,且与网关无关,所以这条边界是你可以亲自审视的,而不是只能凭信任去接受的。

哪些东西永远不该发给网关?

以下这些,永远不要发给网关——也不要发给任何网站:

  • 你的 L309-SEED-1… 身份种子;
  • 十六进制形式的原始种子;
  • 签名私钥;
  • X25519 接收私钥;
  • 混合后量子接收机密;
  • 用于解密封存内容的口令;
  • 你本想保密的明文。

网关合法需要的,可能是公钥、公开签名、公开的记录字节、密文、报价标识符、API 令牌和账户标识符。这些都不是私有的身份材料。规则很简单:如果某个工作流要求你把一个机密粘贴到某处,就停下来,问问为什么。

还有哪些地方需要你自己留心?

本地密钥的安全程度,取决于它周围的环境。密码学能把网关挡在你的机密之外;但它无法保护一颗被用户复制进攻击者控制的表单里的种子。所以你仍然需要:

  • 保护好你的身份种子,并为它保留一份真实的备份;
  • 在封存任何敏感内容之前,先核验接收方的接收地址;
  • 远离钓鱼网站;
  • 对浏览器扩展保持审慎;
  • 让你的设备保持更新;
  • 在合适的场景启用磁盘加密;
  • 理解解密后的文件是如何被缓存的;
  • 运行桌面工具和命令行工具的可信构建版本;
  • 为共享或团队工作流制定密钥管理策略。

这些失效模式值得直言不讳,因为它们并不对称。若同时丢失种子「和」你的解锁要素,该身份未来便无法再用——不过你已经发布的任何证明,仍会从公开数据中永远验证通过。而一颗「被盗」的种子意味着整个身份的沦陷:应对之策是创建一个新身份并停用旧的,而不是去重置密码。这里没有「重置」一说;这正是「没有托管方」所要付出的代价。

这对一项开放标准为何重要

一项开放的证明标准,不应依赖某一个受信任的运营方。

如果 CardanoWall 明天就消失了,一份 Label 309 记录也应当依然有意义。如果一家公司运行着自己的网关,它的记录也应当依然符合标准。如果你把种子导出到另一个符合标准的客户端,它也应当派生出完全相同的密钥。而这一切,只有在边界保持清晰时才成立:记录是标准的,验证是独立的,网关是可替换的,客户端持有机密,而你始终可以自己备份身份根。

所以「密钥永不离开设备」并不是一句口号。它是让一份存在性证明可移植的关键之一——一份你可以带着越过任何单一服务(包括我们自己)的证明。

一句话版本

网关帮你发布证明,客户端持有机密。

私钥不会被发送到网关。内容在上传前就已加密。解密在本地完成。验证不依赖于信任某个服务的一面之词。这就是 CardanoWall 所立足的安全形态——也是 Label 309 旨在保持开放的形态。

延伸阅读

securityidentitycardanowall