Solidity Keccak256与SHA3-256

1. 引言

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