ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

区块链密码学入门:哈希、签名与默克尔树如何构建信任

区块链密码学入门:哈希、签名与默克尔树如何构建信任 1. 去中心化账本凭什么让人相信密码学接管的“信任”从哪来在学习Web3之前我一直以为区块链上的数据都被“加密”得严严实实外人什么都看不到。真正开始看源码、拆区块、读智能合约之后才发现完全不是这么回事。区块链里所谓的密码学Cryptology绝大多数地方保护的不是“看不见”而是“改不了、赖不掉、假不了”。这一篇是“从零开始的Web3学习”系列的第五篇我打算从最基础的概念入手把区块链中的密码学聊透——哈希、签名、默克尔树以及它们为什么能构成一套可验证的信任体系。适合刚接触Web3、想补密码学底子或者准备往CTF密码学方向尝试的同学。要理解区块链先得搞清楚一个基础问题去中心化之后信任到底放在哪中心化世界里银行、机构、政府替你保管记录出了问题你可以找柜台、打官司、报仲裁。而区块链是一个公开的公共账本核心诉求是“记录谁欠谁、谁转移了价值”。当没有人承担“公正第三方”角色时就必须回答三个问题一条数据是不是被篡改过一笔交易是不是由你本人发起的你能不能对自己已经做过的承诺抵赖密码学在这个语境下不是方程游戏而是工程方案。古典密码学里凯撒、维吉尼亚做的事情是“把信息藏起来”现代密码学里公钥体系、哈希函数做的事情是“把信息钉死、把人认出来、把动作定责”。区块链作为面向全网的公开账本重点用到的恰好是后者。这也是很多人初学时的核心误区——把区块链和“加密”划等号然后到处找“解密”当然找不到因为它的设计目标根本不同。区块链真正用到的密码学工具数来数去就四样单向哈希函数、非对称加密主要是椭圆曲线、数字签名以及由哈希构造的默克尔树。这四样东西分别解决了“数据有没有被动过”“你是谁”“你认不认这笔账”“一整个区块的证据链怎么压缩”这四个问题。后面几章逐一拆开讲。另外想先说个学习心态上的建议。很多新人第一反应是“密码学这么难是不是要数学系才搞得定”。我的实际经验是做Web3开发需要理解的密码学深度其实很浅但非常硬核全是工程细节。你不需要会推导 secp256k1 的椭圆曲线方程但你需要清楚私钥到公钥到地址的生成链路、签名如何验证、哈希为什么不可逆。掌握这个度你就能读懂绝大多数链上协议和安全报告。2. 哈希函数给区块和交易打上“数字指纹”我问过不少想转Web3的朋友“哈希是什么”一半人答“加密”一半人答“摘要”。这两种说法都不准确。加密是可逆的哈希不可逆“摘要”也不够贴切因为安全哈希最关键的性质是让人无法构造碰撞。简单说输入任意长度的字节串输出固定长度的结果。这个输出通常叫摘要或者更形象一点——数据指纹。以 SHA-256 为例它的输出永远是256比特也就是32字节十六进制显示为64个字符。区块链里最常见的两个哈希算法是SHA-256比特币的区块头、交易ID都在用和Keccak-256以太坊地址生成、交易哈希、合约存储布局都在用。注意这里的 Keccak-256 并不是 NIST 标准化的 SHA3-256只是同一族算法里规格类似、填充参数不同的两个版本。如果你拿标准 SHA3 去算以太坊地址会得到完全不同的结果很多写工具的同学就在这个细节上报过错。安全哈希函数必须具备几个硬性性质单向性知道输入容易算输出知道输出无法反推输入抗碰撞性找不到两个不同输入产生同一个输出至少在现有算力下做不到雪崩效应输入改一个比特输出几乎每一位都发生变化。这里面有个特别反直觉的点单向性不是说“技术上不能倒着算”而是说穷举空间大到计算上不可行。256比特的哈希空间是 2^256 个可能值比宇宙中原子数量的估计值约 10^80还大几个数量级。就算全网算力一起开工想暴力找出两个碰撞输入按地球寿命的长度来算也完不成。这就是“安全哈希”和普通校验码比如CRC的本质区别。区块链在哪些地方用哈希归纳起来主要是三块第一交易ID。每笔交易被哈希后作为自己的ID全网的节点可以重算哈希验证交易内容未被修改。你转账 1 ETH 还是 100 ETH哈希完全不同稍微改一点点数据ID就变了。第二区块哈希与链式结构。每个区块头里保存着前一区块的哈希值。所以一旦有人篡改历史区块里的任何交易这个区块的哈希就会变后面所有区块头里的“前一区块哈希”全部对不上整条链当场断裂。这种“用哈希做指针”的设计是区块链不可篡改性的地基。第三工作量证明PoW。比特币要求区块头哈希满足一个难度目标比如算出来的值小于某个目标数。矿工不断修改区块头里的 nonce 字段相当于不停“翻牌”直到翻出一张合法的随机数。平均尝试次数由全网难度决定可能是几十亿次甚至更多。这个过程中没有任何捷径可走比拼的就是算力。我自己曾在本地跑过一个简化版 PoW深刻体会过这种“求解难、验证易”的不对称性。假设给定一段消息“hello from web3”要求哈希结果以5个零开头。我从 nonce0 开始一个一个试直到 nonce24793 才找到第一个满足条件的值。这个过程完全不可预测但验证却只需要一次哈希计算。这种不对称性就是 PoW 能充当共识机制的根本原因。学习哈希时有个常见坑在CTF里尤其爱考哈希长度扩展攻击Length Extension Attack。它只对 SHA-1、SHA-2 这类 Merkle-Damgard 结构的哈希有效原理大致是你拿到了“secret message”的哈希却不知道 secret 本身也可以继续往 message 后面拼接新内容并算出新的合法哈希。这样就能绕过某些“签名校验”。以太坊用的 Keccak-256 因为内部结构不同不受这种攻击影响但如果你自己设计校验逻辑建议直接使用带密钥的 HMAC或者至少把密钥放到数据后面而不是简单做“secret data”哈希。这类细节只有踩过一次坑才记得牢。3. secp256k1 与数字签名钱包地址和“私钥即一切”的由来第二个核心工具是非对称加密。区块链圈最出圈的一句话是 “Not your keys, not your coins”说的就是私钥的重要性。为什么私钥这么关键因为区块链上所谓的“所有权”本质上不是一个数据库里的账户字段而是一个数学事实只有拥有某地址对应私钥的人才能对这个地址发出的交易完成签名。这里涉及的曲线叫secp256k1它基于一个椭圆曲线方程 y² x³ 7并选取了一个特定的大素数有限域。它不是区块链发明的早在比特币诞生前就已在密码学界使用只不过比特币和以太坊把它变成了事实上的“链上标准”。作为 Web3 学习者你不需要会推导曲线公式但至少要知道三个事实私钥是随机生成的256位整数取值范围接近 1 到 2^256公钥是椭圆曲线上的一个点通过私钥乘以基点 G 得到写作 K kG从公钥可以推算出地址但是从地址或公钥无法反推私钥因为椭圆曲线离散对数问题目前没有高效解法。以太坊地址的生成流程是一条标准流水线私钥 → 椭圆曲线乘法得到公钥 → 对公钥做 Keccak-256 哈希 → 取结果最后20字节 → 转成 0x 开头的40位十六进制字符串。整个链路不依赖任何第三方完全由私钥决定。所以你可以这样理解地址本质上是“你私钥对应公钥哈希的后20字节”丢了前面12字节的精度但也正因如此地址本身不存在“泄露即被盗”的问题——只有私钥才致命。那数字签名到底在做什么一句话版签名是用你的私钥对一条消息的哈希做一次特定计算得到一对大整数r, s。任何人都可以拿着你的公钥、消息原文和签名验证“这个签名是否由对应私钥产生”但别人无法通过签名反推出你的私钥。在以太坊的 ECDSA 签名里还会额外带上一个 v 值让验证者能够直接恢复出签名者地址——这就是为什么验签时可以做到“既验真又不用单独传地址”。为了让这套流程看得见摸得着我强烈建议用代码跑一遍。下面是一个 Python 示例使用 eth_account 库from eth_account import Account # 从已有私钥创建账户 acct Account.from_key(0x你想拿来测试的私钥) print(地址:, acct.address) # 对文本消息签名 message Learn Cryptology for Web3 signed acct.sign_text(message) print(消息哈希:, signed.message_hash.hex()) print(签名:, signed.signature.hex()) # 从签名恢复签名者 recovered Account.recover_message(signed.payload, signaturesigned.signature) print(恢复结果:, recovered) print(是否一致:, recovered.lower() acct.address.lower())跑完之后你对“签名说了算不算数”会有非常直观的感受用不同私钥签名恢复出的地址完全不同改掉消息里的任何一个字节签名立刻对不上。把私钥、公钥、地址、签名串起来实际验证一遍比读十遍理论都更能建立直觉。这类签名在实际链上使用时有一个发生率极高的坑重放攻击。假设你在以太坊主网用某私钥签了一笔交易这个签名本身没有绑定“哪条链”。如果攻击者拿到这笔已广播的交易把它原封不动地转发到另一条同样支持该签名的链上对方节点有可能照单全收。所以以太坊提出了EIP-155在待签名的数据里加入 chainId主网为1让同一笔交易只能在特定链上有效。凡是要做跨链、多链钱包的同学第一件事就是确认对方实现是否遵守了 EIP-155否则迟早要出事。这里还想多说一句传统系统里的签名目的大多是“防抵赖”比如银行回执、纸质合同。区块链上的签名则直接等于“授权”每一次私钥使用都可能导致资产转移。两者的风险等级完全不同密钥保管的严肃性自然也不可同日而语。4. 默克尔树一个区块里上千笔交易怎么实现“秒验证”前两章都在讲单个数据怎么防篡改、怎么认证身份。但区块链面对的真实数据量远不止于此一个比特币区块通常打包几千笔交易以太坊区块里也是几百到上千笔。如果为了验证某笔交易是否在区块中必须下载整个区块并重新计算所有交易哈希手机钱包和轻节点根本没法落地。默克尔树Merkle Tree就是为了解决这个效率问题而生的。构造方式并不复杂。假设一个区块里有8笔交易先把每笔交易分别哈希得到8个叶节点然后把相邻两个叶节点的哈希拼起来再做一次哈希得到4个父节点再往上两两合并得到2个爷节点最后合并成1个根就是默克尔根Merkle Root。如果某一层的节点数是奇数就把最后一个节点自己复制一份再配对这是常见的奇数叶子处理规则。默克尔根会被写进区块头相当于把整块交易压缩成了一个32字节的总指纹。那么问题来了如何证明某笔交易确实存在于这个区块里答案是不需要把所有交易都给你看。你只需要一条“默克尔路径”从该交易所在的叶子节点开始每一层都提供一个兄弟节点的哈希。验证方拿到这些哈希后从下往上逐级拼合、逐级哈希最终算出一个根与区块头里的默克尔根比对。一致就说明这笔交易确实被打包了。整条路径长度等于树高也就是 log₂(N) 个节点。1000笔交易树高才10层10000笔交易也只需要14个哈希。这种压缩能力就是默克尔树被区块链选中成为“标配”的直接原因。用生活打比方学校要证明“张三今天确实来上课了”最笨的办法是搬出全班花名册逐一核对。默克尔树的思路则是把全班按树形分组老师只给出一串“同组同学的哈希凭证”你沿着树上行汇总出根和手里的总哈希一比对就行。你不用看全班每一个人却能得到“看过全班”等价的验证效果。这个比喻很多初学者听完都会恍然大悟。比特币的SPV 轻钱包Simplified Payment Verification正是建立在这个机制上。轻钱包不需要同步全量区块链数据只保存每个区块头大约80字节。当收到一笔交易推送时节点会附带一条默克尔路径轻钱包自行算出根并与区块头里的默克尔根比对。确认无误就认为这笔交易确实入块了。今天手机钱包能轻量化运行靠的就是这套设计。以太坊在默克尔树上又往前走了一步实现了默克尔帕特里夏树Merkle Patricia TrieMPT。普通默克尔树适合“静态数据的存在性证明”但以太坊管理的是账户状态、合约存储这样的可增删改键值数据库。MPT 结合了前缀树与默克尔哈希能对“读、写、改、删”后的状态给出新根。以太坊客户端里至少维护着四条这样的树交易树、收据树、状态树、存储树各自拥有独立的默克尔根而这一切的底子仍然是哈希。顺带一提默克尔树还能天然防止“交易被悄悄调换位置”。某笔交易一旦被篡改哪怕只是改了一个字节对应叶子哈希就会变一路向上所有父节点哈希全部连锁变化最终默克尔根对不上区块头里的值立刻暴露。这就是哈希的“雪崩效应”在树形结构上的放大版本。5. 走通闭环从Web3靶场、CTF密码学题到经典教材的落地路线最后一章聊点实操层面的路径规划。很多刚接触 Web3 的人会在“怎么练”这个问题上卡壳。光看概念记不住真上手又怕浪费手续费。我的建议是三条线同时推进靶场实操、CTF 题目、经典教材。靶场方面现在生态里既有专门的 Web3 靶场也有大量通用CTF平台长期提供密码学专题。Web3 领域比较知名的有 OpenZeppelin 的 Ethernaut、Damn Vulnerable DeFi 这类开源项目都是可以在本地或测试网上反复练习的。通用CTF平台里的密码学题目几乎覆盖了现代密码学的核心攻击面古典密码、RSA、分组密码、哈希攻击、签名伪造等。这些题目表面看起来和区块链关系不大但底层数学工具与链上密码学完全一致。举个例子CTF里高频出现的ECDSA nonce 复用攻击直接就能迁移到链上漏洞分析如果某个钱包或合约在处理签名时固定了随机数 k攻击者拿到两条不同消息的签名后就能通过简单的代数运算恢复出私钥。这几年不少真实发生的链上私钥泄露事件究其根源都是随机数生成出了问题。CTF 的模拟题和现实攻防之间的距离往往只隔着一个“工程实现细节”。教材方面国内学习者常看的杨波《现代密码学》第五版是一本很规整的骨架书把对称密码、公钥密码、哈希函数、数字签名、安全协议讲得很系统适合用来搭知识框架。如果想看更有工程味、更多历史逸闻和实战细节的内容**Bruce Schneier 的《应用密码学》**是绕不开的经典。虽然出版年代早很多算法已经被淘汰但书中那种“从现实需求反推密码设计”的思路至今仍在影响着一代代密码工程师。我的建议是先看应用再用骨架书梳理最后回到题目里验证。不要一上来就啃椭圆曲线群论、有限域扩展这类纯数学内容。那是研究者的路不是应用者的路。我见过太多人卡在数学推导上学了两个月椭圆曲线连地址怎么从私钥生成都还没跑通过这就本末倒置了。实操路径可以按这个顺序来用 Python 或 ethers.js 跑通“私钥→公钥→地址→签名→验签”全流程。这一步解决“看得见”。找公开区块链浏览器选一个真实区块下载区块头手动核对前后区块哈希的链接关系验证默克尔根与交易数量是否对得上。这一步解决“算得动”。进 Web3 靶场把 ERC20、多签钱包、代理合约这些经典漏洞样例各打一遍重点关注需要密码学知识支撑的场景比如链下签名授权、重放攻击、签名校验绕过。这一步解决“用得上”。做一批 CTF 密码学题至少覆盖 RSA 低指数/共模、哈希长度扩展、ECDSA nonce 复用三类经典考点。做完你会发现链上安全报告里的很多攻击描述你在题目里早见过了。最后把我踩过的几个认知偏差放在这里大家对照自查常见误区真实情况区块链上的数据是加密存储的链上大部分数据公开透明密码学负责完整性、认证与授权而不是提供保密地址就是公钥地址是公钥哈希的后20字节不是公钥本身更不是私钥签名是加密的逆过程签名用私钥对摘要做变换验证用公钥没有人能“解密”签名助记词可以像密码一样找回助记词是私钥的另一种编码一旦丢失毫无找回机制只能靠备份私钥离线保存就绝对安全离线要防丢、防盗、防损坏还要防被恶意软件截获冷存储是流程体系而非单一操作整个密码学在 Web3 里的地位我的体会是它不是可选的进阶分支而是所有信任机制的底座。哈希让你相信数据没被改签名让你证明你确实做过某件事默克尔树让你在庞大账本里也能飞速验证。这三件事环环相扣构成了“去中心化信任”的最小闭环。后续无论你想深入共识算法、智能合约安全还是做链上数据分析都建议先把这一篇涉及的代码和练习亲自跑一遍。我自己的学习习惯是每学一个密码学知识点就强制写一个小脚本去调用它、看输出、故意改错再观察异常。这种方式虽然慢但理论才不会只停留在“眼睛会了”的层面。
返回列表