揭秘Shamir秘密共享漏洞与ZKDocs发布:提升密码学实现安全

本文披露了影响多个阈值签名库的Shamir秘密共享实现漏洞,包括私钥泄露和节点崩溃风险,同时介绍了新发布的密码学文档项目ZKDocs,旨在帮助开发者避免非标准化密码原语的实现陷阱。

披露Shamir秘密共享漏洞并宣布ZKDocs - Trail of Bits博客

Filipe Casal, Jim Miller
2021年12月21日
密码学, 漏洞披露, 零知识

Trail of Bits公开披露了两个影响币安阈值签名方案库(tss-lib)及其大多数活跃分叉的Shamir秘密共享实现的漏洞。以下是受影响代码库的完整列表:

  • 币安的tss-lib
  • Clover Network的threshold-crypto
  • Keep Network的keep-ecdsa
  • Swingby的tss-lib
  • THORchain的tss-lib
  • ZenGo X的curv

这些漏洞允许恶意用户窃取其他用户的私钥或使其节点崩溃。利用这些漏洞非常简单:攻击者只需在密钥生成协议或重新共享协议开始时配置恶意ID。

什么是阈值签名方案?

阈值签名方案是一种强大的密码学协议,允许一组用户生成和控制私签名密钥。用户可以共同对消息生成数字签名,但无人能单独签名。

许多人熟悉多重签名(multisig)协议的概念,主要用于加密货币钱包,只有在收到足够多用户签名后才执行交易。这些方案的主要区别在于:在多重签名方案中,每个用户拥有个人私钥/公钥对用于签名;而在阈值签名方案中,每个用户持有同一密钥的一个份额。使用多重签名方案时,签名数量与用户数量成正比;使用阈值签名方案时,只产生一个组签名。

阈值签名很复杂。这些方案如何工作的高级技术细节超出了本文范围,但如果您好奇这些方案在实际中如何工作或它们与其他方案(如多重签名)的比较,可以找到几篇更详细描述它们的博客文章,例如这里这里

什么是可验证秘密共享(VSS)?

秘密共享是一种密码学协议,用于将秘密密钥(或其他秘密数据)拆分为密钥份额。这些密钥份额应看起来完全随机,因此它们本身不透露有关底层秘密的任何信息。但当足够多的份额组合时,可以恢复原始秘密。最常见的秘密共享技术是Shamir秘密共享方案,它利用了多项式的特性。

Shamir方案的高级思想是:对于n个用户,您希望至少t个(其中t ≤ n)通过组合他们的份额来恢复秘密。为实现这一点,我们在有限群上生成一个次数为t-1的随机多项式p,常数项设置为秘密值。

然后,通过在n个不同点(每个用户一个点)评估多项式来创建秘密份额。一个点(甚至几个点,取决于t的值)不透露有关多项式的任何信息。但是,如果用户组合足够多的点,他们可以使用多项式插值恢复原始多项式。由于秘密值编码在多项式中,恢复多项式即恢复秘密。

阈值签名方案使用秘密共享来生成在多个用户之间共享的签名密钥,但在实践中,大多数方案必须使用更高级的秘密共享版本,称为可验证秘密共享(VSS)。通常,用户不能假设运行这些协议的其他人是诚实的。VSS允许用户验证他们收到的份额是诚实地生成的。最常见的VSS方案由Feldman开发。他的方案使用与Shamir方案相同的技术生成份额(即,使用秘密作为常数项生成随机多项式),并创建额外值使这些份额可验证。

从零到英雄

我们披露了两个影响不同阈值签名方案实现中Feldman可验证秘密共享的漏洞。这些漏洞并非某些无法预见的新颖分析的结果;相反,这些漏洞源于秘密共享的少数已知弱点之一。我们今天强调它们,不仅因为受影响的供应商数量,而且因为它们代表了非标准化密码学中同一反复出现问题导致的一系列关键漏洞:缺乏文档和指导。

第一个漏洞与如何生成秘密份额有关。由于我们将多项式的常数项定义为秘密值,因此在生成份额时,多项式点的x值为非零至关重要。如果我们在0点创建份额,则多项式评估为常数项,完全泄露秘密值:

大多数实现通过在多值(1, 2, …, n)处评估多项式来完全避免这种可能性,其中n是所需份额的数量。然而,一些实现在特定值处评估多项式;例如,币安的实现在每个用户的唯一ID值处评估多项式。以这种方式设计的实现必须验证这些ID为非零;大多数成功做到了这一点。然而,一些实现忘记了这些共享方案在有限群上操作,因此必须在模群阶下执行此零检查!如果未执行此检查,秘密值会立即泄露给将其唯一ID设置为群阶的恶意用户。如果群阶为q,则:

受影响的实现检查了用于生成这些秘密份额的用户ID为非零,但未在椭圆曲线群阶下执行此检查。

从零到崩溃

第二个漏洞与模算术运算的错误处理有关。根据签署消息的用户组,用户计算拉格朗日系数,即形式为IDi / (IDi – SelfID)的项的乘积。由于我们在有限域上工作,我们使用(IDi – SelfID)的模逆来计算除法。如果用户的IDi模等于当前用户的ID(SelfID),则减法将模等于零——但零没有模逆!易受攻击的实现未验证模逆,并会因空解引用而崩溃。

我们在审计中经常发现这些漏洞;如果不仔细注意模算术细节,很容易错过它们。大多数时候,甚至存在验证,但如果未在有限域的上下文中检查参数,这些验证是不充分的。

使用通用大整数类进行模算术时,请采取以下步骤:

  1. 在验证(如比较)之前,始终模约简数字。
  2. 始终验证模逆和模平方根等运算。根据API,要么检查返回值,要么捕获错误以确保函数不会崩溃。
  3. 如果您仍然不确定或想要第二意见,请联系我们进行审计。

ZKDocs

今天,我们发布ZKDocs,这是我们为非标准化密码原语编写的文档。我们希望它通过提供这些协议的全面实现细节和安全考虑,帮助开发者在未来避免这些漏洞。

随着我们发现更多这些漏洞的实例,我们开始思考它们为何发生以及如何防止它们在未来发生。不幸的是,对于非标准化密码协议,负担落在开发者身上,以弄清楚所有低级实现细节和安全陷阱。要了解资源有多有限,尝试搜索有关Feldman可验证秘密共享方案(同类中最常见的方案!)的信息。您可能找到的唯一结果是维基百科文章和Feldman 1987年的原始论文。除此之外,您可能能够找到一些Stack Overflow讨论或旧的讲义。但仅此而已。

这些方案很复杂!由于可用的文档和指导如此有限,我们不应惊讶这些类型的漏洞最终在实践中发生。通过ZKDocs,我们旨在填补这一空白。例如,要阅读有关我们发现的与零份额相关的第一个漏洞的更多细节,请查看ZKDocs中的秘密共享部分!

ZKDocs的“Shamir秘密共享方案”部分

协调披露

  • 2021年10月19日:在tss-lib中发现秘密数据泄露
  • 2021年10月21日:向币安报告
  • 2021年11月1日至12月3日:内部发现影响Clover、Keep Network、Swingby、THORChain和ZenGo X的问题
  • 2021年12月6日:向Clover、Keep Network、Swingby、THORChain和ZenGo X报告

截至2021年12月20日,币安、Keep Network、Swingby、THORChain和ZenGo X已使用所需修复修补了他们的实现。唯一的例外是Clover,他们未回复我们的电子邮件。

我们要感谢币安、Keep Network、SwingBy、THORChain和ZenGo X团队与我们迅速合作解决这些问题。

如果您喜欢这篇文章,请分享: Twitter LinkedIn GitHub Mastodon Hacker News

页面内容
什么是阈值签名方案?
什么是可验证秘密共享(VSS)?
从零到英雄
从零到崩溃
ZKDocs
协调披露
近期文章
使用Deptective调查您的依赖项
系好安全带,Buttercup,AIxCC的评分轮正在进行中!
使您的智能合约超越私钥风险
Go解析器中意外的安全陷阱
我们审查首批DKLs23库的收获
来自Silence Laboratories的23个库
© 2025 Trail of Bits。
使用Hugo和Mainroad主题生成。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计