1. 引言

SHA3由Keccak标准化而来,在很多场合下Keccak和SHA3是同义词,但在2015年8月SHA3最终完成标准化时,NIST调整了填充算法:SHA3-256(M) = KECCAK [512] (M || 01, 256)。所以标准的NIST-SHA3就和Keccak计算的结果不一样。
如对空字符串进行Keccak256 和 SHA3-256结果各不相同:

//Keccak256()结果:c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470//SHA3-256()结果:a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a

以太坊在开发的时候SHA3还在标准化中,所以采用了Keccak,所以Ethereum和Solidity智能合约代码中的SHA3是指Keccak256,而不是标准的NIST-SHA3,为了避免混淆,直接在合约代码中写成Keccak256是最清晰的。

2. Solidity中Keccak256与abi.encode和abi.encodePacked联合使用

// 使用encodePacked存在哈希碰撞的问题// (AAA, BBB) -> AAABBB // (AA, ABBB) -> AAABBB// 以上2种输入,哈希结果相同。function collisionExample(string memory _string1, string memory _string2)public pure returns (bytes32) {return keccak256(abi.encodePacked(_string1, _string2));}// 使用encode可避免哈希碰撞的问题// (AAA, BBB) -> AAABBB // (AA, ABBB) -> AAABBB// 以上2种输入,哈希结果不同。function collisionExample2(string memory _string1, string memory _string2)public pure returns (bytes32) {return keccak256(abi.encode(_string1, _string2));}

参考资料

[1] keccak和sha3的区别
[2] Which cryptographic hash function does Ethereum use?
[3] Difference between keccak256 and sha3
[4] does keccak256 and sha3 reproduce the same hash ?
[5] Hashing Functions In Solidity Using Keccak256