上一篇文章讨论了如何保护 ETH 2.0 的取款密钥 (withdrawal key) ,并总的介绍了 ETH 2.0 验证者所使用的几个密钥 对 。在阅读本文之前,建议先阅读一下这篇文章。同样地,我们预设读者对验证者有最基本的了解,包括但不限于 “验证者是什么”,“他们为什么需要密钥”,以及 “他们通常需要什么操作” 等概念。
在 ETH 2.0 中,验证者密钥被用来确定相关消息是哪位验证者发出的 。验证者要发送这些消息才能获得奖励(并避免遭受惩罚)。
验证者密钥的风险很难衡量:验证者密钥本身无法用来访问资产。因此,即使攻击者获得了你的验证者密钥,也无法直接盗取资产。但是,他们可以通过敲诈勒索 1 等方式间接获利,更有甚者,比起自己获利,他们更想让你蒙受损失 2 。因此,我们通常认为验证者密钥的安全需求很高。
- 图 1 :验证者的安全需求 -
但是,不像取款密钥那样 (你可以离线保存起来),验证者密钥要能够随取随用 ,因为验证者在每个 epoch (大约 6.5 分钟)都要签署多个消息。因此,验证者密钥的访问需求也很高。
- 图 2 :验证者密钥的访问需求 -
因此,我们发现自己陷入了两难困境:从传统上来说,同时满足安全性和可访问性需求是很难实现的,因为提高安全性往往会降低可访问性,反之亦然。
- 图 3 :验证者密钥的双重需求 -
为满足对安全性和可访问性的双重需求,我们需要采取更高级的措施,在不作重大妥协的前提 下,较高程度地满足这两方面的需求。这可以通过分层来实现。本文的目的是探究每一层所提供的功能,并了解哪些功能适用于或不适用于验证者设置。
Eth2 中的密钥对都有一把公钥和一把私钥。出于本文的写作目的,全篇所用的 “key(密钥)” 一词指代的都是通常叫做私钥的那把;如果指代的是公钥,会有明确的说明。
(译者注:validator key 和 withdrawel key 都是密钥对,都分公钥和私钥。公钥是用来在 Eth1 链上注册的,可公开;私钥则是验证者自己实际使用的,不可公开,公开则自己的资产和验证者都完全被他人掌控了。)
首先,我们需要定义攻击者和用户的目标。在知道为什么要保护验证者密钥之后,我们就可以思考每个功能可以在多大程度上实现这一目标。首先, 攻击者的目标可以被定义成:
攻击者的目标是,签署某一条消息时能签出与目标验证者公钥相对应的签名(即能伪造验证者对某一条消息的签名)。
当然了,如果这是唯一的目标,那么直接毁掉验证者密钥就能阻止攻击者了。但是,这对用户来说一点帮助也没有。因此,我们需要考虑的第二个目标,也就是用户的目标,可以被定义成:
用户的目标是只签署理想消息,不签署不良消息。
就本文的目标而言,理想消息指的是能够获得奖励的消息,不良消息指的是会触发 罚没事件 3 的消息。
请注意,攻击者要想实现其目标,只需要签署任意一条消息即可,而用户的目标是持续性的。这种不对称性是安全系统的一大特征,即,攻击者只需赢一次就够了,而用户需要每次都赢。
为此,我们需要一个由不同分层或者说独立功能组成的系统,提供增强型安全性或增强型可访问性,而且可以将二者结合起来,共同达到较高水平。一个良好的安全模型需要具备多个分层,每个分层都会(单独或与其它分层结合起来)提供某种保障或其它分层的备份,并且有足够多的分层提供可访问性,从而确保用户的目标可以实现。请注意,本文聚焦于技术保护:其它层面(例如,操作层面和社会层面)上的安全性都不属于本文的讨论范围内, 虽然它们在任何安全模型中都是至关重要的部分,应该采取相应解决方案。
为了探讨验证者密钥的保护方式,我们先来做个简单的演示:
- 图 4 :验证者密钥 -
与 ETH 2.0 的所有密钥一样,验证者密钥也是一串数字 4 。如果验证者在不采取任何保护措施的情况下存储了验证者密钥,攻击者很容易就能获得该密钥并实现其目标。以下几类人能够获得验证者密钥:
任何有权访问运行验证者客户端的计算机账号的人
任何被授权访问运行验证者客户端的计算机的人
任何可以物理访问运行验证者客户端的计算机的人
任何有权访问运行验证者客户端的计算机的数据的人(例如,备份数据)
这样一来,用户就无法实现其目标(即,不签署不良消息)。因此,我们首先要通过加密的方式来保护验证者密钥:
- 图 5 :加密验证者密钥 -
我们可以通过多种方式加密验证者密钥,例如, EIP-2335 标准 5 。一旦验证者密钥被加密,除非攻击者掌握加密口令(passphrase) ,否则无法解密出密钥 6 。这样就可以很好地保护验证者密钥(无论是将它存储在验证者客户端还是数据备份内)。
乍看之下,攻击者似乎无法通过任何方式来实现其目标。然而,用户也没有办法实现其目标,因为他们再也无法签署理想消息:无论是对于用户还是攻击者来说,经过加密的密钥都是没用的,因为用户必须先将该密钥解密,然后才能用它来签署消息。这样一来,验证者进程就一定要包含访问解密口令这一步骤。即然验证者进程可以访问解密口令 ,那么攻击者也可以访问该口令 ,尤其是在解密口令被存储在验证者客户端的情况下,因为验证者客户端有可能遭到攻击。
因此,这种改变本身不算上策。不过,如果我们将它与第二层结合起来,就能提供更有力的保护:
- 图 6 :远程口令 -
如果解密口令是远程存储的,加密验证者密钥会带来更强大的保护 7 。由于口令不再存储于验证者客户端内,攻击者无法从磁盘数据中获得未加密的私钥。攻击者只能发动更加复杂的攻击,例如,从内存中获取解密后的密钥,或模仿验证者客户端进程来获得解密密钥。
虽然攻击难度更大了,但是复杂攻击依然有可能获得验证者密钥。此外,用户依然可能在不经意间签署不良消息。因此,我们可以通过增加一个远程签名器层来为用户提高安全性和可访问性。
- 图 7 :远程签名器 -
远程签名器分离了验证者客户端的核心功能:确定要放到消息中的数据、签署消息并将该消息发送至 ETH 2.0 网络。第一个和第三个功能仍保留在验证者客户端手中,第二个功能由远程签名器来实现。远程签名器还引入了 罚没保护机制 ,可以确定哪些是理想消息,哪些是不良消息,并予以签署或拒绝。
如何阻止攻击者将攻击目标从验证者客户端转移到远程签名器呢?首先,签名器可以具备比验证者客户端更高的安全性。验证者客户端需要执行许多任务,包括与 ETH 2.0 网络的其它组成部分(如信标节点)通信。这些通信可以为攻击者提供信息和攻击界面 。由于签名器只与验证者客户端通信,它们的活动受到很多限制,这就为双方的服务器带来了更高的安全性。
其次,远程签名器为用户带来了其它好处。现在,同一个远程签名器可以与多个验证者客户端通信,使得我们能够创建具备高可用性的验证者客户端基础设施。远程签名器确保验证者客户端不会签署任何不良消息。
然而,事实上,远程签名器存在单点故障问题:如果远程签名器遭到攻击,或出现故障,用户就连理想消息也签名不了 。有没有一种方法可以让远程签名器更能抵抗攻击,同时又不会失去上述任一好处?
- 图 8 :门限签名 -
我们还可以在上述层次的基础上再构建一层门限签名,进一步增强安全性和可访问性。验证者密钥需要用 Shamir 密钥分割流程来处理 ,即,使用验证者私钥生成多个密钥,然后将它们发送给远程签名器 。
- 图 9 :Shamir 密钥分割 -
现在,每个远程签名器都持有由验证者私钥生成的密钥了, 而且只需几个远程签名器就可以创建有效签名, 也就是所谓的 门限签名 (threshold signature) 。假设有 3 个远程签名器 ,其中 2 个远程签名器提供个人签名来生成一个聚合签名,如下图所示:
- 图 10 :生成聚合签名 -
门限签名的表达式通常写成 m/n ,也就是说,假设总共有 n 个签名,需要任意 m 个签名来生成一个有效签名。如果门限值是 2/3,那么使用任意两个签名即可生成一个有效签名。
引入门限签名之后,即使有一个服务器 8 出故障,用户也能签署理想消息,而且也不会增加用户无意间签署不良消息的概率。鉴于硬件、软件和操作失败的可能性不可消除 ,门限签名确实是一个具有抗逆性的验证基础设施应有的功能。
虽然门限签名机制会带来额外的安全性,但是它有两大缺点。第一,分发密钥并不能预防长期攻击:假设门限值是 2/3 ,如果有一个签名器反水,整个机制就会留下永久的漏洞,只要再有一个签名器反水,攻击者就可以达成目标。第二,攻击者有可能在密钥分发过程开始前抢先获得该密钥,从而导致整个机制丧失意义。分布式密钥生成可以一举解决这两个问题:
- 图 11 :分布式密钥生成 -
分布式密钥生成是一个比较复杂的话题 。具体的运作方式不在本文的讨论范围内。但是,我们会提供一个简短的功能说明,来阐述它是如何克服简单门限签名的局限性的。
在分布式密钥生成开始前,用户先要决定门限值,例如 2/3 。他们可以选择 3 个远程签名器 ,并启动生成过程。这 3 个远程签名器会通过密钥管理器 9 生成自己的密钥,不与用户或其他任何一个签名器共享, 以及一些公共信息。将来自 3 个签名器的公共信息结合起来就能创建出一个合成公钥。
- 图 12 :创建合成公钥 -
只需 3 个签名器中的任意 2 个即可生成签名,类似简单的门限签名。
- 图 13 :一组签名器签署消息 -
如果有一个签名器不可用,例如,下线维护或遭到攻击,还可以通过另外两个签名器生成签名。
- 图 14 :另一组签名器签署消息 -
可以看出,分布式密钥生成与简单的门限签名具备相同的优势,可以避免最开始需要分发密钥的风险。但是,一个签名器被攻陷就会留下永久漏洞的问题仍然存在。那分布式密钥生成还有其它招数吗?
有的,就是 “密钥更新” 。密钥更新就是毁掉现有密钥,由每个签名器重新生成新的密钥。新生成的密钥保留原有密钥的特性,即,任意两个密钥可以结合起来生成一个有效签名。新的密钥与原有密钥不具有相关性,因此无法通过原有密钥计算出新的密钥。
- 图 15 :密钥更新 -
如果有一个签名器遭到攻击, 其它签名器可以触发密钥更新。新旧密钥无法结合起来生成一个有效签名。这样一来,被攻击者盗走的密钥就会变得毫无用处。
- 图 16 :攻击失败 -
密钥更新可以多次执行,以防多个签名器遭到攻击。
安全性是一个大概念。上文阐述了不同安全层的功能和优点,并没有提出任何完美甚至最佳解决方案。就保护验证者密钥而言,我们还需考虑很多要点,例如:
硬件钱包
支持 BLS12-381 的硬件钱包预计很快就会上线。硬件钱包可以替代下层所使用的简单磁盘存储系统。但是这样一来,我们可能无法引入分布式密钥生成之类的高级技术。
成本效益
凡是涉及安全性的方案都有可能为了提高一点安全性而花费大量资金。每个用户都需要决定自己想要防范的攻击,及其愿意为此付出的代价。
远程存储验证者密钥
上文已经讨论过了远程口令存储。但是,远程存储验证者密钥是否还会带来其它优势(还是正相反) ?虽然它不会增强安全性,但是在出现硬件故障的情况下,它可以让验证者客户端更快恢复,这点对于用户来说非常有利。但是,远程存储也会带来额外的风险,因为我们必需正确配置远程存储,确保只有那些获得许可的人能够访问密钥。
备份验证者密钥
虽然本文聚焦于如何保护验证者密钥不受攻击,但是实际上大多数验证者密钥丢失事件背后的原因都平平无奇 。最常见的就是存储密钥的硬件丢失。用户需要一个备份策略,而且他们需要知道的是,一旦攻击者获得了被备份的密钥,ta 就能对任意消息签出与验证者公钥相对应的签名 。我们应该采取适当的措施来确保攻击者无法访问已备份的验证者密钥。在理想情况下,这些密钥最好完全脱机存储,而且外人无法接触其存储设备。
多个验证者密钥
如果有多个验证者密钥,它们之间,或者与它们各自的取款密钥之间是否应该具备什么关系?例如,将多个验证者密钥备份成一个种子,这样确实使用起来比较方便,但是不会带来安全效益。用户应该考虑是否想在任意阶段单独控制验证者密钥,再进行相应的计划。
本文提供了多种方法来保护验证者密钥,同时确保它们可以用来履行验证职责。
每个用户都应该考虑他们想要提供的安全级别,以及他们应该采取的措施。应当考虑的是,验证者密钥不控制资金,因此窃取验证者密钥的攻击者无法直接获得任何利益 10 。
本文单纯从技术层面上探究了如何保护验证者密钥。我们还应该考虑运营和社会安全需求。若想全面保护验证者密钥,就得考虑到所有这些方面。
或者,你可以使用提供这类功能的质押服务。在综合考虑技术、风险和资金管理的情况下,Attestant 正在构建硬件、软件和操作服务,以提供机构级的质押服务,让你可以随时控制自己的资金。
脚注
“交出赎金,否则就让你遭到罚没。”
通过 “金手指攻击( Goldfinger attack )” 或者将适当规模的攻击与 ETH 衍生品相结合,这可能会对攻击者的财富产生间接影响。
罚没事件指的是,如果有验证者对 ETH 2.0 网络造成伤害,就会损失很大一部分质押物。
其范围在 1 和 52,435,875,175,126,190,479,447,740,508,185,965,837,690,552,500,527,637,822,603,658,699,938,581,184,512 之间。
至文本截稿时, EIP-2335 标准仍处于起草阶段,不过已经有很多 ETH 2.0 密钥生成器在使用该标准。
我们假设口令足够强大,无法暴力破解。
这个例子很好地体现了,如何将两个层次结合起来提供更高的安全性。
其它门限签名的变体可以提高冗余性。
我们使用密钥管理器一词来指代那些除签名之外还要执行更多操作的远程服务器。
还应该注意的是,潜在攻击者并不一定知道这一事实。
原文链接:
https://www.attestant.io/posts/protecting-validator-keys/
作者: Jim McDonald
翻译&校对: 闵敏 & 阿剑