nodejs-keccak256
affaan-m/ecc
Use Ethereum's Keccak-256, not Node's NIST SHA3, to prevent silent hashing bugs in selectors, signatures, and addresses.
What is nodejs-keccak256?
This skill prevents a critical bug where Node.js's built-in sha3-256 (NIST SHA3) silently produces wrong hashes for Ethereum data. Use it when computing function selectors, signatures, storage slots, or address derivation in JavaScript/TypeScript.
- Explains why Node's crypto.createHash('sha3-256') breaks Ethereum hashing
- Provides correct Keccak-256 patterns using ethers, viem, or web3.js
- Shows how to compute function selectors, event topics, and storage slots
- Demonstrates address derivation from public keys
- Includes audit commands to find unsafe hashing in your codebase
How to install nodejs-keccak256
npx skills add null --skill nodejs-keccak256How to use nodejs-keccak256
- 1.Import Keccak-256 from ethers, viem, or web3.js instead of Node's crypto module
- 2.Replace any crypto.createHash('sha3-256') calls with the appropriate library function
- 3.For ethers v6: use keccak256(toUtf8Bytes(data)) or solidityPackedKeccak256() for packed types
- 4.For viem: use keccak256(toBytes(data))
- 5.For web3.js: use web3.utils.keccak256(data) or web3.utils.soliditySha3()
- 6.Run the provided grep commands to audit your codebase for unsafe patterns
Use cases
- Computing EIP-712 signatures or function selectors in a dApp
- Building Merkle tree or storage-slot helpers for smart contract interaction
- Reviewing Ethereum-related JavaScript code for silent hashing bugs
- Deriving Ethereum addresses from public keys in Node.js
- Packing and hashing Solidity types in off-chain code
- Smart contract developers writing JavaScript/TypeScript tooling
- Full-stack Web3 engineers building dApps or indexers
- Security auditors reviewing Ethereum client code
- Anyone using Node.js crypto with Ethereum data
nodejs-keccak256 FAQ
Node exposes NIST SHA3-256, the standardized variant. Ethereum uses Keccak-256, an earlier algorithm that produces different hashes. Node will not warn you of the difference.
ethers, viem, and web3.js all provide correct Keccak-256 functions. Choose whichever you already depend on; all are equally safe.
Use id('functionName(type1,type2)').slice(0, 10) in ethers, or the equivalent in viem/web3.js.
Yes. Node's sha3-256 is correct for NIST SHA3 use cases. Only avoid it for Ethereum data.
Run grep -rn "createHash.*sha3" to find sha3-256 calls, then verify they are not used with Ethereum data.
Full instructions (SKILL.md)
Source of truth, from affaan-m/ecc.
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. metadata: 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.
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
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' },
);
Common patterns
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
import { keccak256 } from 'ethers';
function pubkeyToAddress(pubkeyBytes: Uint8Array): string {
const hash = keccak256(pubkeyBytes.slice(1));
return '0x' + hash.slice(-40);
}
Audit your codebase
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.
Related skills
More from affaan-m/ecc and the wider catalog.
nutrient-document-processing
Convert, extract, OCR, redact, sign, and fill documents via Nutrient DWS API.
nuxt4-patterns
Nuxt 4 patterns for SSR hydration, route rules, lazy loading, and safe data fetching.
openclaw-persona-forge
Forge complete OpenClaw lobster personas with guided design or gacha randomization, generating SOUL.md, identity rules, names, and avatar prompts.
opensource-pipeline
Fork, sanitize, and package private projects for safe public release through a 3-stage pipeline.
orch-add-feature
Agent skill from affaan-m/ecc.
orch-build-mvp
Agent skill from affaan-m/ecc.