一行代码缺失,千万美元蒸发: SecondFi 钱包 Ed25519 签名漏洞全解密
SecondFi 钱包事件一份面向开发者的加密学事后剖析背景2026 年 6 月 21 日至 23 日SecondFi原 YoroiCardano 钱包中的一个致命漏洞导致约 1610 万 ADA当时价值约 240 万美元从 374 个用户钱包中被盗。根源仅仅是在 Ed25519 签名实现中少写了一行代码。作为开发者我们常常把加密库当作黑盒来用。这次事件残酷地提醒我们如何使用加密原语和原语本身同样重要。让我们一步步拆解到底出了什么问题、为什么会发生以及如何避免重蹈覆辙。技术拆解Ed25519 签名本该怎么做Ed25519 是 RFC 8032 定义的一种确定性签名方案。与 ECDSA其随机数重用已是众所周知的灾难不同Ed25519 的设计初衷就是彻底消除随机数失败的风险, 它从私钥材料和消息中确定性地派生出临时随机数nonce。对于 Cardano 的扩展 Ed25519 变体钱包存储一个 64 字节的扩展私钥分为两部分kL第 0–31 字节签名标量kR第 32–63 字节秘密随机数后缀每个钱包独有永不公开正确的签名流程如下r SHA-512(kR || M) mod L # 随机数由秘密 消息派生 R r * B # R 是公开的 k SHA-512(R || A || M) mod L # 挑战标量 S (r k * kL) mod L # 签名分量最终签名是(R, S)对。这个设计安全的原因确定性同一消息 同一密钥 同一签名无需依赖 RNG秘密参与随机数r依赖kR而kR永远不会离开设备可验证任何人都可通过[S]B R [k]A验证无需知道私钥SecondFi 实际做了什么SecondFi Android 10.0.3 版本在从 BIP32-Ed25519 派生层向签名适配器层传递数据时遗漏了关键的kR秘密前缀。只有签名标量被传给了底层签名器。有缺陷的实现计算随机数的方式是r SHA-512(M) mod L仅此而已。没有任何秘密成分只有交易体哈希, 而这是链上公开可见的。为什么这是灾难性的当随机数可以公开计算时攻击者只需一条链上签名就能恢复私钥。给定任何交易中的公开值M被签名的消息交易体R公开随机数点A公钥S签名分量攻击者计算r SHA-512(M) mod L # 和漏洞签名器一样 k SHA-512(R || A || M) mod L # 和验证器一样 s (S - r) * inverse(k) mod L # 恢复私钥一条签名一笔交易你的私钥就归别人了。安全研究员 Charles Guillemet 现场演示了这一点他从主网上拉取签名仅凭链上信息就重建了私钥。时间线日期事件6 月 8 日SecondFi Android 10.0.3 发布包含有缺陷的签名器6 月 12 日早期用户交易已经开始泄露密钥6 月 21–23 日两个独立攻击者团伙系统性清空 374 个钱包6 月 22–23 日SecondFi 承认问题进入维护模式6 月 22 日SecondFi 紧急将约 1.29 亿 ADA 转移至第三方托管机构6 月 24 日补丁发布7 月 22 日SecondFi 宣布永久关闭根本原因未经审计的 SDK漏洞是在 6 月 8 日引入的当时一个名为trantor的未经审计的第三方实验性 SDK由一名独立开发者发布在 npm 上替换了 EMURGO 此前审计过的签名模块。这是一个关键的教训绝不能在生产环境中用未经审计的代码替换经过审计的加密代码, 尤其不能跳过完整的安全审查。Tibane Labs 的取证报告证实有漏洞的签名器正是trantorSDK它替换了经过验证的 EMURGO 构建版本。问题不在于 SDK 本身的意图而在于它如何与 Cardano 扩展 Ed25519 签名流程集成, 秘密前缀根本没有通过适配器层传递。代码级分析有漏洞的实现简化版importhashlib# 漏洞完全省略了秘密前缀 kRdefflawed_sign(private_key_scalar,message):# 缺失kR秘密随机数前缀# 本应是r SHA512(kR || message) mod L# 有漏洞随机数只由消息派生rSHA512(message)%L# 可公开计算Rr*B kSHA512(R||public_key||message)%L S(rk*private_key_scalar)%Lreturn(R,S)正确的实现RFC 8032importhashlibdefcorrect_sign(extended_secret_key,message):# extended_secret_key kL (32 字节) kR (32 字节)kLextended_secret_key[0:32]kRextended_secret_key[32:64]# 正确随机数由秘密前缀 消息派生rSHA512(kR||message)%L# 秘密且不可预测Rr*B kSHA512(R||public_key||message)%L S(rk*kL)%Lreturn(R,S)概念验证玩具示例下面这个简化的 PoC 展示了漏洞原理importhashlib L2**127-1# 不是真正的 Ed25519 阶仅为演示defH(*parts):hhashlib.sha512()forpinparts:h.update(pifisinstance(p,bytes)elsestr(p).encode())returnint.from_bytes(h.digest(),little)%Ldefinv(x):returnpow(x,-1,L)# 受害者的私钥玩具示例secret_s98765432123456789public_Asecret_s# 真实 Ed25519 中 A s * BMbcardano tx body hash, toy example# 漏洞签名器前缀被丢弃随机数仅由消息决定rH(M)Rr# 真实 Ed25519 中 R r * BkH(R,public_A,M)S(rk*secret_s)%Lprint([受害者签名])print(A ,public_A)print(R ,R)print(S ,S)# 攻击者从公开数据恢复私钥r_publicH(M)recovered_s((S-r_public)*inv(k))%Lprint(\n[攻击者])print(恢复出的私钥:,recovered_s)print(匹配:,recovered_ssecret_s)修复方案应该怎么做1. 使用经过审计的库永远不要自己造加密轮子。使用成熟、审计过的库Rusted25519-dalek标准且经过审计的实现JavaScript/TypeScriptnoble/ed25519或tweetnaclPythonpynacllibsodium 绑定对于 Cardano请使用Cardano Serialization Libraryemurgo/cardano-serialization-lib它经过审计并遵循正确的扩展 Ed25519 规范。2. 在所有层级保留秘密前缀在通过适配器层传递密钥时确保完整的扩展私钥kL和kR两者都保留// 正确传递完整的 64 字节扩展私钥fnsign_transaction(extended_secret:[u8;64],message:[u8])-Signature{letkLextended_secret[0..32];letkRextended_secret[32..64];// kR 必须用于随机数派生letrsha512(kR,message);// ...}3. 绝不用未经审计的代码替换已审计代码trantorSDK 在 6 月 8 日替换了 EMURGO 的审计实现。这种变更本应触发完整的安全审查加密正确性验证测试分阶段发布并伴随监控4. 实施加密正确性的回归测试测试随机数派生是否正确#[test]fntest_nonce_derivation_includes_secret_prefix(){letsecretgenerate_test_secret();letmessagebtest message;letsig1sign(secret,message);letsig2sign(secret,message);// 确定性同一密钥 同一消息 同一签名assert_eq!(sig1,sig2);// 不同消息应产生不同随机数letsig3sign(secret,bdifferent message);assert_ne!(sig1,sig3);// 关键验证随机数不是简单的 SHA512(message)// 这需要访问内部状态或已知答案测试}5. 审计所有第三方依赖trantorSDK 由一名独立开发者发布从未被审计。在集成任何加密依赖之前审查源代码检查已知漏洞验证维护者的信誉考虑进行全面安全审计开发者的核心要点Ed25519 设计上是确定性的——随机数由SHA-512(secret_prefix || message)派生。如果省略秘密前缀随机数就变成了公开可计算的。当随机数可预测时一条签名就足以恢复你的私钥。这比 ECDSA 随机数重用更糟糕, 后者通常需要两条签名。漏洞是通过用未经审计的代码替换已审计代码引入的。加密代码不是“即插即用”的, 集成方式至关重要。一旦密钥在链上被泄露它就永远泄露了。区块链交易是不可逆的。EMURGO 警告用户将受影响的助记词导入其他钱包并不能降低风险, 被泄露的地址必须彻底放弃。攻击窗口只有短短两周6 月 8 日至 6 月 21 日但已有 374 个钱包被清空。当漏洞如此容易利用时攻击者可以行动得极快。最后的思考这不是一次复杂的攻击。没有零日漏洞没有钓鱼活动没有智能合约漏洞也没有助记词被偷。攻击者只是读取了区块链然后做了一些算术。正如 MyCrypto 创始人 Taylor Monahan 所指出的这比 2011 年早期的比特币钱包漏洞还要严重。这是一次流程上的失败, 在未审查的情况下替换审计过的加密代码未能测试集成然后将其推送给数百万用户。SecondFi 将永久关闭。374 名用户失去了他们的资金。一位支持 Cardano 九年的用户损失了为退休而积攒的 998,000 ADA。所有这一切只是因为少写了一行代码。

相关新闻

Windows 11与VSCode终端美化全攻略:从字体配色到Oh My Posh实战

Windows 11与VSCode终端美化全攻略:从字体配色到Oh My Posh实战

1. 从“黑框框”到高效工作台:为什么我们需要美化终端? 每次打开Windows 11那个经典的黑色命令提示符(CMD)或者PowerShell窗口,你是不是也感觉有点“复古”?一个简单的白字黑底界面,字体可能还…

2026/10/3 3:26:01 阅读更多 →
Python图像边缘检测实战:从Sobel到Canny算法原理与调优指南

Python图像边缘检测实战:从Sobel到Canny算法原理与调优指南

1. 项目概述:从“看见”到“看清”边缘在计算机视觉的世界里,让机器“看见”只是第一步,让它“看清”物体的轮廓和结构,才是理解图像内容的关键。图像边缘检测,就是实现这一目标的基础技术。简单来说,它就像…

2026/10/3 8:24:14 阅读更多 →
滑翔伞机翼(Wingsuit

滑翔伞机翼(Wingsuit

为你带来具有高度物理拟真性、空气流体力学模拟、动态风阻判定以及实时物理形变的殿堂级单键高燃街机游戏——「赛博原力:滑翔伞机翼(Wingsuit / 重力势能滑翔、上升热气流与极限低空擦墙)」。前面我们写过了太空漂移、刚体连缀、…

2026/9/25 19:48:02 阅读更多 →

最新新闻

BranchIP:自适应等变计算驱动的原子间势能建模新范式

BranchIP:自适应等变计算驱动的原子间势能建模新范式

1. 项目概述:为什么“自适应等变计算”正在重构原子间势能建模的底层逻辑BranchIP这个名字乍看像某个冷门开源库的代号,但拆开来看——Branch(分支)、IP(Interatomic Potential,原子间势能)——…

2026/10/5 13:59:21 阅读更多 →
自己动手,三分之一预算:开源驾驶舱openrig铝型材DIY全攻略

自己动手,三分之一预算:开源驾驶舱openrig铝型材DIY全攻略

你有没有算过一笔账:一套像样的模拟赛车驾驶舱,成品买下来普遍要8000到20000元,好一点的直接奔着5万去了。但如果自己动手,用开源图纸和铝型材拼一台,成本可以压到三分之一以下,刚性还不输成品。这就是open…

2026/10/5 13:59:21 阅读更多 →
OpenRig开源开放式机架:从设计到组装,打造高效散热DIY工作站

OpenRig开源开放式机架:从设计到组装,打造高效散热DIY工作站

OpenRig 这名字拆开看就是 Open Rig,开放式机架。我做这个项目从画第一张草图到实机点亮,前后折腾了两个多月,期间推翻了三次结构方案,废掉一版亚克力切割件,最后才定下来现在这套既兼顾散热、又方便维护、还能随意扩…

2026/10/5 13:59:21 阅读更多 →
CARM:LLM强化学习中取消响应的精准掩码方案

CARM:LLM强化学习中取消响应的精准掩码方案

1. 项目概述:为什么在LLM强化学习中,“取消响应”会成为训练灾难的隐形推手?最近在做几个数学推理和代码生成类任务的RLHF微调时,我反复遇到一个特别诡异的现象:模型明明在监督微调(SFT)阶段表现…

2026/10/5 13:59:21 阅读更多 →
OpenShell实战:让大模型通过自然语言驱动本地Shell执行代码

OpenShell实战:让大模型通过自然语言驱动本地Shell执行代码

1. 项目概述1.1 它到底是什么OpenShell这个名字,乍一听像是个终端模拟器,或者某个开源Shell的变体。但实际上,它做的事比“Shell”这两个字所暗示的要大得多——它是一套把自然语言转换成可执行代码,并在本地环境中直接运行的开源…

2026/10/5 13:59:21 阅读更多 →
落地页文案的10个转化技巧:用ai-design-skills写好标题公式与CTA

落地页文案的10个转化技巧:用ai-design-skills写好标题公式与CTA

落地页文案的10个转化技巧:用ai-design-skills写好标题公式与CTA 【免费下载链接】ai-design-skills 项目地址: https://gitcode.com/gh_mirrors/ai/ai-design-skills ai-design-skills 是一套面向 Claude Code、Cursor 等 AI 编程工具的落地页设计技能库&a…

2026/10/5 13:58:20 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 5:06:42 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 3:06:17 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 11:40:45 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 20:14:29 阅读更多 →