solidity – How Is the keccak256(a, b) Function Implemented – Technical Overview

hashhash-algorithmkeccakSecuritysolidity

I need to understand how keccak256(a, b) is implemented and how it differs from keccak256(a || b).

Is the content padded?

I need this because I do not want to allow for vulnerabilities where a user could fake a hash, for example by doing:
H(0xabc, 0xdef) = H(0xa, 0xbcdef) which would be a major security vulnerability.

Thank you

Best Answer

Solidity uses a non-standard packed mode where arguments are packed tightly. You can check out the algorithm in the docs: Solidity: non-standard-packed-mode

In summary, keccak256(a,b) = keccak(a || b) is given. You might wonder why your example keccak256(0xa, 0xa) ≠ keccak256(0xaa) seems to prove my thesis wrong. This is simply because you tried to use a datatype that is unknown in Solidity. In Solidity numbers are stored in a multiple of 8 bits. You tried to use a number containing only 4 bits, leading to a situation where the Solidity compiler is being forced to pad your number to fit into 8 bits. 0xa became 0x0a for example. So you tried to compare keccak256(0xa, 0xa) = keccak256(0x0a, 0x0a) = keccak256(0x0a0a) with keccak256(0xaa)