nodejs-keccak256

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Node.js Keccak-256

Node.js Keccak-256

Ethereum uses Keccak-256, not the NIST-standardized SHA3 variant exposed by Node's
crypto.createHash('sha3-256')
.
以太坊使用的是Keccak-256,而非Node的
crypto.createHash('sha3-256')
提供的NIST标准化SHA3变体。

When to Use

适用场景

  • Computing Ethereum function selectors or event topics
  • Building EIP-712, signature, Merkle, or storage-slot helpers in JS/TS
  • Reviewing any code that hashes Ethereum data with Node crypto directly
  • 计算以太坊函数选择器或事件主题
  • 使用JS/TS构建EIP-712、签名、默克尔树或存储槽相关工具
  • 审查所有直接使用Node crypto模块对以太坊数据进行哈希计算的代码

How It Works

实现原理

The two algorithms produce different outputs for the same input, and Node will not warn you.
javascript
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
两种算法对相同的输入会产生不同的输出,且Node不会给出任何警告。
javascript
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

Examples

示例

ethers v6

ethers v6

typescript
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],
);
typescript
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

viem

typescript
import { keccak256, toBytes } from 'viem';

const hash = keccak256(toBytes('hello'));
typescript
import { keccak256, toBytes } from 'viem';

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

web3.js

web3.js

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

Common patterns

常用模式

typescript
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]),
  );
}
typescript
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]),
  );
}

Address from public key

从公钥生成地址

typescript
import { keccak256 } from 'ethers';

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

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

Audit your codebase

审计你的代码库

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

Rule

规则

For Ethereum contexts, never use
crypto.createHash('sha3-256')
. Use Keccak-aware helpers from
ethers
,
viem
,
web3
, or another explicit Keccak implementation.
在以太坊相关开发场景下,切勿使用
crypto.createHash('sha3-256')
。请使用
ethers
viem
web3
或其他明确实现了Keccak算法的库提供的Keccak相关工具方法。