作者:salvatoshi
来源:https://delvingbitcoin.org/t/a-simple-backup-scheme-for-wallet-accounts/1607
对任何非单签名的钱包账户来说,备份描述符都是极为关键的,因为弄丢描述符可能会有灾难性的后果(损失资金) —— 即使理论上来说足以复原钱包的种子词没有丢失。哪怕对简单的多签名钱包来说也是如此,因为仅仅弄丢一个 xpub 中的信息就有可能使钱包无法复原。
因为缺乏标准,人们自创了各种备份方案,甚至有人把它刻在金属板上。
我认为这不是个好办法,应该避免。描述符不是种子词,所以不管在理论上还是操作上,都应该有完全不同的处理办法。
在本文中,我会简要介绍背景,并简述我认为可被软件钱包采用的 钱包账户备份标准 的理想结构。
动机:机密性 vs. 隐私性
种子词要秘密保存,它是用来保护能够花费资金的密钥材料的。种子词访问限制如果被突破,就意味着攻击者获得资金的所有权(至少是相关的密钥所保护的具体控制权)。因此,能够触碰种子词对攻击者来说是非常有价值的,而且它们愿意投入更高的成本、更精心的攻击,因为可能有高昂回报。
因此,对种子词来说:
- 电子备份是高风险的:硬件签名器专门设计成在安全芯片中保存种子词,跟运行软件钱包的设备隔离。
- 种子词的冗余备份也是高风险的:种子词必须要物理装置保护,而在多个地点放置多个副本会让周全的保护变得更难。
描述符(以及它的小兄弟 xpub)则只需要隐私:触碰到它只会让一个攻击者可以打探你的资金。这当然也是坏事,但不像直接拿走你的资金那么有价值。攻击者可能会用它来获得关于你的信息、形成进一步的攻击,但 一旦发现攻击太过昂贵和复杂就会失去攻击兴趣。
对描述符来说:
- 电子备份是无法避免的:每一个使用这个账户的参与者都 必然 会在自己自己的软件钱包中使用一个电子备份。
- 额外的冗余备份的风险算不上什么。
因此,为描述符生成多个备份,无论是实体的、电子的,放在硬盘上还是放在云存储上,都是减少资金丢失风险的有效方法 —— 它不像种子词的冗余备份那样会给你带来更高的风险。
我建议使用像 liana 钱包这样的时间锁复原机制,以在实质上解决由种子词管理不当带来的资金丢失风险。
那么,要如何 正确地 备份描述符和钱包条款?
实体备份很简单 —— 你只需要打印机就性了。如果你有冗余备份,纸备份也挺好。在本文中我只关心电子备份。
电子备份的可欲属性
- 加密:这样一来,备份就可以放在不受信任的环境中,比如云服务商,甚至公开的论坛中。
- 具有访问控制:解密应该是目标参与者可以做到的事(一般来说是联合签名人的一个子集)。
- 易于实现:不应要求使用复杂的工具。
- 厂商独立:理想情况下,它应该能够使用任意硬件签名设备实现。
- 确定性:备份的结果对相同的载荷是一样的。并不关键,但有会更好。
一种简单的确定性加密备份方案(草稿)
我们可以单纯用每一个我们希望能够解密描述符的参与者 xpub 来加密载荷(在这里就是描述符本身)。
想法 1:可以做得更好一些,我们生成一个随机的 32 字节的对称密钥 $s$,用每一个公钥加密 $s$,然后用 $s$ 来加密载荷。这将备份的体积从 $O(n·|data|)$ 降到了 $O(n + |data|)$(其中 $n$ 为公钥的数量)。
译者注:当参与者(公钥)数量为 n,为保证每一个参与者都能解密,直接用每个人的 xpub 来分别加密要形成载荷的 n 个加密副本,因此是 $n·|data|$;但如果用一个对称密钥来加密载荷,就只会有 1 个载荷加密副本,另外,则是对称密钥 s 的 n 个(固定长度的)加密副本,因此是 $n + |data|$ 。
想法 2:对于任何已经知道描述符的参与者,就没什么好隐藏的。因此,机密性 可以降低到 对任何还没有拿到描述符的人保持机密。我们的每个联合签名人已经有一个公钥(就是他们在钱包账户中的 xpub),因此,我们可以复用这个密钥作为加密密钥。然而,使用非对称加密,在解密的时候就需要私钥。这是不合意的,因为私钥可会能放在不容易编程出定制化解密逻辑的安全芯片中。反过来,我们可以复用公钥自身的熵来生成一个对称密钥,并用它来 “加密” 共享的秘密值 $s$ 。那么,对于任何使用公钥 $p_i$ 的参与者 $i$,我们都这样派生其对称密钥 $s_i = \operatorname{sha256}(``\textrm{BACKUP_INDIVIDUAL_SECRET}” | p_i)$ 。这就避免了非对称加密,而且只需要能够从安全芯片中访问公钥 —— 这是所有的比特币签名设备都已具备的功能。
想法 3:这个过程中唯一的随机性是共享秘密值 $s$。为使之是完全确定性的,我们可以使用描述符的结合熵(combined entropy)来派生一个确定性的、每个知晓描述符的人都能知道的共享秘密值。假设该描述符中的不同 xpub 有 $p_1, p_2, \dots, p_n$(以字典顺序排列),一个简单的选择是:$s = \operatorname{sha256}(``\textrm{BACKUP_DECRYPTION_SECRET}” | p_1 | p_2 | \dots | p_n)$。
下一节则会将上述想法都整合起来。
方案
在下文中,将被备份的载荷 $data$ 是未定义的,但它将(至少)包括描述符或者 BIP388 钱包条款。操作符 “⊕” 表示的是按位 XOR(异或)操作。
- 设 $p_1, p_2, \dots, p_n$ 为 描述符/钱包条款 中的公钥,以字典升序排列。
- 令 $s = \operatorname{sha256}(``\textrm{BACKUP_DECRYPTION_SECRET}” | p_1 | p_2 | \dots | p_n)$
- 令 $s_i = \operatorname{sha256}(``\textrm{BACKUP_INDIVIDUAL_SECRET}” | p_i)$
- 令 $c_i = s \oplus s_i$
- 使用 AES-GCM 算法, 用对称密钥 $s$ 来加密载荷 $data$
最终的备份是 $c_i$ 的列表以及 $data$ 的加密副本。
解密
要解密一个备份的载荷时,特定公钥 $p$ 的主人要计算 $s = \operatorname{sha256}(``\textrm{BACKUP_INDIVIDUAL_SECRET}” | p)$,然后尝试用每一个 $c_i$ 计算出对称密钥 $c_i \oplus s$,并用对称密钥来解密载荷。
安全考虑
确定性加密,按照其定义,无法满足密码学中常用的“ 语义安全” 属性;但是,在我们这个语境下,可以安全地假设敌手无法获得明文,而且也没有别的明文会用同样的秘密值 $s$ 来加密。
未来的工作
我希望这能够给更加正式的规范带来启发,让软件钱包都采用相同的标准。