nodejs-keccak256

nodejs-keccak256

熱門

在 JavaScript 和 TypeScript 中預防以太坊雜湊錯誤。Node 的 sha3-256 是 NIST SHA3,而非以太坊的 Keccak-256,會默默破壞選擇器、簽名、儲存槽和地址推導。

23萬星標
3.5萬分支
更新於 2026/7/21
SKILL.md
readonlyread-only
name
nodejs-keccak256
description

Prevent Ethereum hashing bugs in JavaScript and TypeScript. Node's sha3-256 is NIST SHA3, not Ethereum Keccak-256, and silently breaks selectors, signatures, storage slots, and address derivation.

version
1.0.0

Node.js Keccak-256

以太坊使用的是 Keccak-256,而非 Node 的 crypto.createHash('sha3-256') 所暴露的 NIST 標準化 SHA3 變體。

使用時機

  • 計算以太坊函式選擇器或事件主題
  • 在 JS/TS 中建構 EIP-712、簽名、Merkle 或儲存槽輔助工具
  • 審查任何直接使用 Node crypto 對以太坊資料進行雜湊的程式碼

運作原理

兩種演算法對相同輸入會產生不同輸出,且 Node 不會發出警告。

import crypto from 'crypto';
import { keccak256, toUtf8Bytes } from 'ethers';

const data = 'hello';
const nistSha3 = crypto.createHash('sha3-256').update(data).digest('hex');
const keccak = keccak256(toUtf8Bytes(data)).slice(2);

console.log(nistSha3 === keccak); // false

範例

ethers v6

import { keccak256, toUtf8Bytes, solidityPackedKeccak256, id } from 'ethers';

const hash = keccak256(new Uint8Array([0x01, 0x02]));
const hash2 = keccak256(toUtf8Bytes('hello'));
const topic = id('Transfer(address,address,uint256)');
const packed = solidityPackedKeccak256(
  ['address', 'uint256'],
  ['0x742d35Cc6634C0532925a3b8D4C9B569890FaC1c', 100n],
);

viem

import { keccak256, toBytes } from 'viem';

const hash = keccak256(toBytes('hello'));

web3.js

const hash = web3.utils.keccak256('hello');
const packed = web3.utils.soliditySha3(
  { type: 'address', value: '0x742d35Cc6634C0532925a3b8D4C9B569890FaC1c' },
  { type: 'uint256', value: '100' },
);

常見模式

import { id, keccak256, AbiCoder } from 'ethers';

const selector = id('transfer(address,uint256)').slice(0, 10);
const typeHash = keccak256(toUtf8Bytes('Transfer(address from,address to,uint256 value)'));

function getMappingSlot(key: string, mappingSlot: number): string {
  return keccak256(
    AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [key, mappingSlot]),
  );
}

從公鑰推導地址

import { keccak256 } from 'ethers';

function pubkeyToAddress(pubkeyBytes: Uint8Array): string {
  const hash = keccak256(pubkeyBytes.slice(1));
  return '0x' + hash.slice(-40);
}

審查你的程式碼庫

grep -rn "createHash.*sha3" --include="*.ts" --include="*.js" --exclude-dir=node_modules .
grep -rn "keccak256" --include="*.ts" --include="*.js" . | grep -v node_modules

規則

在以太坊相關情境中,絕對不要使用 crypto.createHash('sha3-256')。請使用來自 ethersviemweb3 或其他明確的 Keccak 實作的 Keccak 感知輔助工具。