Keccak-256 和 SHA3-256 结果不同,原因只有一个:填充字节不一样。Keccak 用的是 0x01,NIST 标准化后的 SHA3 改成了 0x06。同样的输入,因为末尾补的字节不同,整个哈希值就完全变了。以太坊用的是原始 Keccak-256,不是 SHA3-256。如果你在代码里调了 sha3-256 去算以太坊的函数选择器或地址,结果会对不上,而且大多数库不会给你任何警告。
为什么会有两个版本
Keccak 是 2012 年 NIST SHA-3 竞赛的获胜算法。但 NIST 在 2015 年正式发布 FIPS 202 标准时,对填充方案做了修改,把 Keccak 提交时的 0x01 改成了 0x06。这个改动本身很小,但输出完全不同。以太坊在 NIST 标准化之前就已经采用了 Keccak-256,所以一直沿用原始版本。Monero 也是同样的情况,它在 2014 年上线,早于 NIST 标准发布。
有一种常见的混淆说法是"Keccak-256 被标准化为 SHA-3",ETHGlossary 的中文条目就写了类似的话。严格来说,被标准化的是 Keccak 算法家族,但标准版改了填充,所以叫 SHA3-256 的那个东西和以太坊用的 Keccak-256 不是一回事。写代码时不要被这种简化的表述带偏。
核验方法:用已知向量对一下
最直接的核验方式是拿一个已知的输入输出对来比对。以太坊的函数选择器是一个很好的测试点:transfer(address,uint256) 的 Keccak-256 哈希取前 4 字节应该是 0xa9059cbb。如果你用某个库算出来不是这个值,说明你用的不是 Keccak-256。
另一个可用的核验点是空字符串的哈希。Keccak-256 对空输入的输出是 c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470。SHA3-256 对空输入的输出是 a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a。两者不一样,用这个可以快速判断一个工具或库返回的到底是哪个算法。
如果你在浏览器里需要一个快速的核验工具,有些在线工具明确标注了支持 Keccak-256 变体,并且说明输出与 Solidity 的 keccak256() 一致。用的时候注意看它有没有把 Keccak-256 和 SHA3-256 分开列,如果只写了"SHA3"而没有"Keccak",大概率算不出你要的结果。
编码环节:哈希之前的坑
标题里的"编码"指向一个和哈希本身无关、但同样会导致结果对不上的问题。哈希函数处理的是字节序列,不是字符串。你在代码里传给哈希函数的东西,必须先确定编码方式。
最常见的错误是十六进制字符串和原始字节的混淆。假设你要哈希一个地址 0xAbC...。如果你直接把字符串 "0xAbC..." 的 UTF-8 字节喂给 Keccak,和先把 0xAbC... 解析成 20 字节的地址再哈希,结果是完全不同的。Solidity 的 keccak256(address) 做的是后者。在 JavaScript 里用 ethers.keccak256 或 viem 的 keccak256 时,传给它们的是 BytesLike,可以是 hex 字符串,但库会先做 hex 解码再哈希。如果你手动把字符串转成字节数组再传给一个底层的 Keccak 实现,很容易漏掉解码这一步。
文本编码同理。哈希一个 UTF-8 字符串和哈希一个 UTF-16 字符串,字节序列不同,哈希值自然不同。在跨语言、跨平台核验时,先确认双方用的是同一种字节表示。十六进制输出也要统一大小写和是否有 0x 前缀,否则比对时会因为格式差异误判。
给你的判断
如果你在以太坊生态里写代码,永远不要用语言标准库自带的 sha3-256 去替代 Keccak-256。Node.js 的 crypto.createHash('sha3-256') 是 NIST 版本,用在这里会静默产生错误的函数选择器、事件主题和地址。用 ethers、viem、web3.js 或明确标注 Keccak 的实现。
如果你在核验一个哈希值是否正确,先确认算法名,再确认编码。两者有一个不对,结果就对不上。用 transfer(address,uint256) 的选择器或空字符串的哈希做一次快速对照,能排除大部分问题。
如果你只是好奇两者的区别,记住一点就够了:同一个输入,Keccak-256 和 SHA3-256 给出不同的 32 字节结果,因为末尾补的字节不同。以太坊选的是前者,原因只是历史时机,没有额外的技术优劣。
参考资料
- Dart packages·dvKeccak256 function,页面未标明更新日期;核查日期:2026-10-21。
- Dart packages·Keccak256 class,页面未标明更新日期;核查日期:2026-10-21。
- GitHub·Keccak-256 Hash Function (Monero docs),页面未标明更新日期;核查日期:2026-10-21。
- Zerethon·Keccak-256 哈希生成器,页面发布或更新日期:2026-05-14;核查日期:2026-10-21。
- ETHGlossary·keccak-256 中文条目,页面未标明更新日期;核查日期:2026-10-21。
- Zerethon Tools·哈希生成器 — 全算法支持,页面发布或更新日期:2026-05-16;核查日期:2026-10-21。
- GitHub·nodejs-keccak256 SKILL.md,页面发布或更新日期:2026-06-20;核查日期:2026-10-21。



