mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-07 01:33:31 +08:00
103 lines
2.8 KiB
Markdown
103 lines
2.8 KiB
Markdown
---
|
|
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.
|
|
origin: ECC direct-port adaptation
|
|
version: "1.0.0"
|
|
---
|
|
|
|
# Node.js Keccak-256
|
|
|
|
Ethereum uses Keccak-256, not the NIST-standardized SHA3 variant exposed by Node's `crypto.createHash('sha3-256')`.
|
|
|
|
## 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
|
|
|
|
## 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
|
|
```
|
|
|
|
## Examples
|
|
|
|
### 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],
|
|
);
|
|
```
|
|
|
|
### viem
|
|
|
|
```typescript
|
|
import { keccak256, toBytes } from 'viem';
|
|
|
|
const hash = keccak256(toBytes('hello'));
|
|
```
|
|
|
|
### web3.js
|
|
|
|
```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]),
|
|
);
|
|
}
|
|
```
|
|
|
|
### 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);
|
|
}
|
|
```
|
|
|
|
### 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
|
|
```
|
|
|
|
## Rule
|
|
|
|
For Ethereum contexts, never use `crypto.createHash('sha3-256')`. Use Keccak-aware helpers from `ethers`, `viem`, `web3`, or another explicit Keccak implementation.
|