Ethereum uses Keccak-256, instead of the SHA-3 FIPS 202 standard. In the sha3 libraries you are using, try looking for the option to specify using Keccak-256.
For Python see Getting Method ID "Keccak hash" in Python
For Javascript, this library js-sha3 would involve using the keccak_256
function instead of sha3_256
.
keccak_256('');
// c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
sha3_256('');
// a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
Others:
keccak_256('The quick brown fox jumps over the lazy dog');
// 4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15
keccak_256('The quick brown fox jumps over the lazy dog.');
// 578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d
sha3_256('The quick brown fox jumps over the lazy dog');
// 69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04
sha3_256('The quick brown fox jumps over the lazy dog.');
// a80f839cd4f83f6c3dafc87feae470045e4eb0d366397d5c6ce34ba1739f734d
Jehan's answer is great, but we need to explain one more thing: Why does sha3(1)
in solidity produce b10e2d...fa0cf6
?
This is because solidity's sha3 function hashes its inputs based on the argument types. Thus the value 1
will generate a different hash if it is stored as bytes8
, bytes16
, bytes32
, etc. Since sha3(1)
is being passed 1
as a number literal, it is converted into the smallest necessary type, uint8
1.
8 bits fit into 2 hex characters, so if you pad your input to 2 characters you will get the same result in web3:
Javascript:
web3.sha3(leftPad((1).toString(16), 2, 0), { encoding: 'hex' })
// 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2
Likewise, you can cast the number on the solidity side:
Solidity:
// uint is equivalent to uint256
sha3(uint(1))
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
Javascript:
// note that the value is padded by 64 characters to fit 256 bits
web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
A note about BigNumber
types:
They don't work automatically with web3.sha3
. You have to convert them to hex first.
Solidity:
sha3(uint(100 ether))
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273
Javascript:
// the .slice is to remove the leading '0x'
web3.sha3(leftPad(web3.toHex(web3.toWei(100)).slice(2).toString(16), 64, 0), { encoding: 'hex' })
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273
EDIT:
I wrote a small lib that provides a version of web3.sha3
that exactly matches the behavior of sha3
in Solidity. Hopefully this clears up all your hashing woes :).
https://github.com/raineorshine/solidity-sha3
Best Answer
Here's a full working example on generating solidity sha3 hashes from
uint256
:Solidity:
I've made the library go-solidity-sha3 to be able to easily convert solidity types into solidity sha3 hashes in Go. Here's an example:
A more complex example: