比特币杂志
核心问题:libsecp256k1,比特币的加密核心

比特币圈内人士常说“不要相信,要验证”或“私钥不在手上,币就不是你的”,有时甚至声称比特币“有数学支撑”。但这些格言最终究竟意味著什么?这些复杂的数学原理又是如何付诸实行的呢?大多数读者肯定知道,比特币设计的一个基本要素是公钥密码学,更具体地说是数位签名,它无需中心化机构即可证明所有权。但鲜为人知的是,支撑这种椭圆曲线数学运算的底层软体是什么?为了确保以最安全、最高效的方式运行,并持续改进,又付出了哪些努力?让我们深入了解「libsecp256k1」的精彩历史和发展历程。这个库最初只是一个小型业余项目,但经过多年的发展,它已成为保护价值数万亿美元资产的共识规则的重要组成部分。
创世纪
出于我们尚未完全清楚的原因,中本聪选择了一条名为「secp256k1」的椭圆曲线来创建和验证比特币的数位签章。比特币客户端的初始版本使用了广泛应用的OpenSSL程式库来进行交易签名和验证。从软体工程的角度来看,依赖第三方函式库似乎是一个合理的方案(尤其是像椭圆曲线这样具有领域特定性和复杂性的函式库)。
虽然最初选择了使用加密技术(例如加密演算法),但后来发现由于签章解析程式码的不一致性,这个选择存在问题。在最坏的情况下,这甚至可能导致意外的链分裂。当时的一个教训是,OpenSSL 并不适合像比特币这样对共识要求极高的系统。后来,BIP66 解决了这个问题,它确保了 ECDSA 签名的严格编码。之后,在 2016 年初发布的 Bitcoin Core v0.12 中,OpenSSL 依赖项被 libsecp256k1 取代。
但回顾一下,libsecp256k1 计划的最初动机主要是出于对潜在加速效果的好奇。 2012 年的某个时候,比特币核心开发者 Pieter Wuille(网名「sipa」)偶然发现了 Hal Finney(因在 2009 年收到中本聪的第一笔比特币交易而闻名)在 bitcointalk 论坛上的一个帖子。
在题为「加速签名验证」的文章中,讨论了一种利用所谓「自同态」(更具体地说是利用所谓的GLV方法,即Gallant-Lambert-Vanstone方法)的优化方案,而这种自同态只有某些椭圆曲线才允许,secp256k1恰好是其中之一。 Hal Finney本人使用OpenSSL原语实现了该方案,后来甚至将其作为PR提交给了Bitcoin Core。尽管它展现了强大的性能,但…
速度提升了约 20%,但最终由于担心程式码复杂性增加以及无法保证所涉及的加密技术是可靠的,该功能从未合并。
Pieter Wuille 决定从零开始建立一个新的库,其「secp256k1」程式码库的初始提交可以追溯到 2013 年 3 月 5 日。仅仅一周后,该库就能够验证完整的区块链(当时区块高度约 225000),又过了一周,签名功能也得以实现。经过一段时间的测试,该程式库最终得以在 Bitcoin Core 中取代 OpenSSL,首先用于签章功能。
钱包(版本 v0.10,2015 年)以及最终用于共识机制中的 ECDSA 签名验证(版本 v0.12,2016 年)。这些努力绝对值得:根据 Core 中的 PR 描述,使用 libsecp256k1 进行签名验证的速度「提升了 2.5 到 5.5 倍」。讽刺的是,这还不包括先前提到的内同态优化,因为出于专利侵权的考虑,该优化预设并未启用。直到 2020 年专利到期后(在版本 v0.20 中启用),该优化才得以激活,并带来了约 16% 的显著速度提升。
随著时间的推移,该专案吸引了其他几位贡献者。这自然包括从一开始就与 Pieter 在 Blockstream 密切合作的人员,即当时的首席技术长 Gregory Maxwell 和研究员 Andrew Poelstra。 2015 年,Jonas Nick 和几年后的 Tim Ruffing 也加入了进来,他们都是 Blockstream 的研究员,并且多年来一直担任 libsecp256k1 的维护者。他们负责制定新的加密演算法。
他们制定协议(包括详细的安全证明),并透过实施和审查将其付诸实践,因此称他们为「全端密码学家」非常贴切,正如蒂姆·拉芬喜欢这样描述自己一样。
偶尔,甚至比特币领域之外的密码学家也会做出贡献。
libsecp256k1。其中一个值得注意的例子是 Peter Dettman,他是 C#/Java 加密库 BouncyCastle 的维护者之一,至今仍不时提出各种效能改进建议。他的主要贡献之一是在 2021 年使用「safegcd」演算法实现了模逆运算,从而安全地提升了效能,该演算法基于 Daniel J. Bernstein 和 Bo-Yin Yang 的一篇论文。
为什么要重新发明轮子?
libsecp256k1 的目标是为 secp256k1 曲线上的加密操作提供最高品质的函式库,其主要目的是服务更广泛的比特币生态系统——Bitcoin Core 只是它的主要客户端。 libsecp256k1 的 API 设计稳健可靠,难以被滥用,以防止使用者执行不安全的操作(例如,自行编写加密方案),从而避免在最坏的情况下造成资金损失。它专注於单一椭圆曲线,并将功能限制在特定操作上。
对于比特币而言(即主要用于交易的签名和验证),程式码运行速度更快,审查也更简便,与其他实现方式相比,维护负担更轻,整体品质更高。 libsecp256k1 使用 C 语言编写,不依赖任何其他函式库,因此仅使用专为该专案编写的内部程式码。正因如此,它也适用于微控制器等资源受限的设备,而微控制器通常用于硬体钱包。
三思而后行
libsecp256k1 从早期就非常重视品质保证,并在多年来不断改进和完善。如今,它的测试程式码覆盖率接近 100%,只有满足这项标准的新模组才有机会被合并。除此之外,还有一种特殊的品质保证形式,称为「穷举测试」。其基本思想是针对曲线上所有可能的值来测试库的功能。由于实际的 secp256k1 曲线包含约 2^256 个点,因此无法进行穷举测试。为此,我们使用了一条特殊的、规模小得多但非常相似的曲线,其阶数仅为两位数或三位数,因此可以在合理的时间内轻松完成测试。测试的另一个重要部分是确保恒定时间行为,这对于签名尤其重要,我们将在下文中看到。
施诺尔:一个全新的世界
我们将工作重心从品质保证转向新功能,过去十年 libsecp256k1 以及整个比特币协议的一个重要里程碑是引入了 Schnorr 签名。作为 2021 年底启动的 Schnorr/Taproot 软分叉的重要组成部分,Schnorr 签章相比 ECDSA 签章具有诸多优势,包括在标准假设下具有可证明的安全性、更加紧凑,以及支援许多其他构造,例如金钥和签章聚合,从而实现更有效率的多重签章方案。 BIP340 规范和实作皆由 libsecp256k1 的现任三位维护者 Pieter Wuille、Jonas Nick 和 Tim Ruffing 共同完成。
libsecp256k1 对您的节点和网路都很有好处
毋庸置疑,验证数位签章是比特币共识引擎中最重要(如果不是最重要)且安全至关重要的程式码路径之一。无论锁定脚本中包含多么复杂的脚本路径和额外的支出条件,最终交易中很可能至少会涉及一次签名检查,以确保交易确实是由被花费代币的所有者创建的。对于如此关键的操作,我们希望程式码尽可能健壮、经过充分测试且效能卓越。快速签章验证对于快速交易和区块传播至关重要,同时也能加快网路新参与者的初始区块下载 (IBD) 速度。我们先前已经提到,大约十年前 libsecp256k1 首次取代 OpenSSL 时,速度提升了约 5 倍。随著时间的推移,效能得到了进一步提升,最近的一项调查显示,使用最新版本的 libsecp256k1 进行 ECDSA 签章验证的速度比 OpenSSL 快约 8 倍。
签字可能很危险,所以务必谨慎。
到目前为止,我们主要关注的是libsecp256k1的验证功能,因为它对节点运行器和矿工的性能至关重要。另一方面(coin并无双关之意!)是签名,即为交易创建数位签名以便支出资金的过程。这个过程的脆弱之处在于它涉及私钥材料。如果这些材料以任何方式泄露,最坏的情况下可能会导致资金的灾难性损失,因此必须在实现层面格外谨慎。 libsecp256k1试图透过避免资料依赖分支来抵御所谓的“侧通道攻击”,即避免根据输入的资料执行不同的程式码片段。这是一项不小的任务,对于现代编译器而言需要额外的努力,因为现代编译器有时“过于智能”,它们会在编译软体时尝试优化程式码,并添加一些我们明确不希望看到的资源节省分支。这并非仅仅是理论上的担忧,而是已经发生过不只一次,需要发布补丁程式(例如 0.3.1 和 0.3.2 版本)。我们还使用名为「valgrind」的工具测试了重要的恒定时间特性,该工具最初是为调试记忆体问题而开发的。透过使用它来寻找操作敏感资料的程式码中的任何分支,我们可以侦测是否有潜在的侧通道攻击风险。
另一种泄露机密资讯的方式是无意中将其留在记忆体中。覆盖记忆体区域以确保其被擦除听起来很简单,但必须以一种能够防止编译器在编译过程中因程式码最佳化而干扰的方式来完成这项工作。我们采取了非常谨慎的措施来确保这种情况不会发生。
一些幸运的意外
在库的开发过程中,不只一次出现了意想不到的有趣情况。 2014 年,Pieter Wuille 和 Gregory Maxwell 已经开始著手为该库编写一套全面的测试套件。为了提高可靠性,他们采取的策略之一是使用特殊的随机输入,将库内部函数的行为与其他实作进行比较验证。这导致 OpenSSL 在进行平方运算时出现错误结果,这是一个严重的安全漏洞,已提交为 CVE-2014-3570(「Bignum 平方运算可能产生错误结果」)。
几年后,Pieter Wuille 提出了一种新的方法,用于计算先前提到的用于计算模逆的「safegcd」演算法所需迭代次数的界限(或极限)。这使得该界限得以缩小,从而加快了计算速度。但这还不是全部。 Gregory Maxwell 几乎是偶然地发现了 Bernstein 和 Yang 演算法的另一个变体,其界限更低,从而在签名和验证方面都实现了另一个显著的加速。
值得一提的是,「safegcd」实现的正确性(即安全性)已使用名为「Rocq」(原名「Coq」)的特殊定理证明软体和「可验证C」程式逻辑进行了形式化验证。这项令人印象深刻的工作由Russell O'Connor和Andrew Poelstra完成,他们指出libsecp256k1的整个函式库都可以用同样的方法进行验证。

密码学仍在不断发展
我们现在已经证明,libsecp256k1 主要用于创建和验证比特币交易中的数位签名,并尽可能以最安全、最高效的方式实现,但这还不是全部。每当有其他提案涉及基于 secp256k1 曲线的加密操作(理想情况下,这些操作应以 BIP 的形式形式化),并且被认为对整个比特币生态系统有益时,相关程式码很可能被纳入该库的开发范围。在这种情况下,只要开发者有足够的时间进行实作和审查,这些提案很有可能最终会被整合到 libsecp256k1 的发布版本中。先前,ElligatorSwift 模组就曾出现过这种情况,该模组对于实现节点 P2P 通讯的加密至关重要[参见 BIP324;此处有深入讨论]。最近,MuSig2 也采用了类似的方案,MuSig2 是一种基于 Schnorr 签章的金钥聚合方案,它能够以节省空间且保护隐私的方式建立 n 对 n 多重签章。目前,我们正在努力添加一个用于静默支付的新模组。静默支付是保护隐私的静态可重复使用位址,无需在付款前进行任何互动。此外,还有更多功能即将推出:例如 Schnorr 签章批次验证、DLEQ 证明、FROSTETC。让我们拭目以待 libsecp256k1 未来十年的发展!
对 libsecp256k1 有兴趣的读者可以查看并试用 secp256k1lab,这是一个用 Python 实现的 secp256k1 曲线,旨在用于原型设计和实验。 5

千万不要错过拥有《核心特刊》的机会——其中收录了许多核心开发人员撰写的文章,解释了他们自己参与的项目!
本文为《比特币杂志》最新一期印刷版「核心特刊」的编按。我们在此分享,旨在让读者提前了解本期杂志探讨的观点。
[1] https://gnusha.org/pi/bitcoindev/55B79146.70309@gmail.com/
[2] (#2061, https://github.com/bitcoin/bitcoin/pull/2061 )
[3] https://delvingbitcoin.org/t/comparing-the-performance-of-ecdsa-signature-validation-in-openssl-vs-libsecp256k1-over-the-last-decade/2087?u=thestack
[4] [ https://www.arxiv.org/abs/2507.17956 ]
[5] https://github.com/secp256k1lab/secp256k1lab/
这篇文章《核心问题:libsecp256k1,比特币的加密心脏》最初发表在《比特币杂志》上,作者是Sebastian Falbesoner 。






