- To calculate the SHA-3 (keccak-256) hash of something, use the keccak256/sha3 function:
keccak256(...)
// OR
sha3(...) // alias to keccak256
- The function returns the hash in bytes32 format:
keccak256(...) returns (bytes32);
- Since the arguments to this functions are concatenated without padding, use any of the following input formats to yield the same value:
keccak256("hello", "world")
keccak256("helloworld")
keccak256(0x68656c6c6f776f726c64)
keccak256(68656c6c6f776f726c64)
- Use solidity's sha3 function to calculate the SHA-256 hash of the input. It works just like the keccak256 function:
sha256(...) returns (bytes32);
- Use the ecrecover function to verify the address associated with a public key. The function accepts a signed hash message along with v, r, and s values to calculate the address. For invalid inputs, it returns a 0:
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address);
- Try running it in real time using a contract. Consider the following contract, which returns the address from the signed message:
pragma solidity ^0.4.23;
contract VerificationContract {
function verifyAddress(
bytes32 h,
uint8 v,
bytes32 r,
bytes32 s) public pure returns (address) {
return ecrecover(h, v, r, s);
}
}
- Let's test this function with an input message and address. First, create a hash from the input message using web3JS:
var message = "Hello World!";
var prefix = "x19Ethereum Signed Message: ";
var hash = web3.utils.sha3(prefix + message.length + message);
- Sign the message using the address:
var address = "0x...";
var signature = await web3.eth.sign(message, address);
- Calculate the v, r, and s values from the signed signature:
var r = signature.slice(0, 66);
var s = '0x' + signature.slice(66, 130);
var v = '0x' + web3.toDecimal(signature.slice(130, 132));
- Pass the generated values to verify the address:
var result =
await VerificationContract.verifyAddress
.call(hash, v, r, s);
- The returned result should be equal to the address used in step 8.
- Apart from keccak and SHA, solidity can calculate ripemod-160 hashes as well:
ripemd160(...) returns (bytes20);
-
Solidity provides functions to calculate modulo operations on values that do not wrap around the uint256 data type. This works for calculating modulus operations after addition or multiplication.
- To compute (a + b) % x; where x != 0, use the solidity function called addmod:
addmod(uint x, uint y, uint k) returns (uint);
- To compute (a * b) % x; where x != 0, use the solidity function called mulmod:
mulmod(uint x, uint y, uint k) returns (uint);
Cryptographic functions such as sha256, ecrecover, and ripemd160 are a type of precompiled contract and they exist only after the first transaction to it. If you are using a private network, calling these nonexistent contracts can result in an out-of-gas error. Making some kind of transaction (such as sending some wei) can solve this issue in a private network. The main or test network already has these contracts in a working state and it doesn't require such a transaction.