如何为 Solidity 生成的整数值生成 sh3_keccak256?
How to generate sh3_keccak256 for integer values as generated by Solidity?
我正在尝试在 Python 中生成由 Solidity 生成的相同 sha3.keccak_256 整数值。
这是 Solidity 的作用:
pragma solidity ^0.4.18;
contract GenerateHash{
function generateHashVal(int id, int date) pure public returns (bytes32){
//Using values - (123,1522228250);
return keccak256(id,date);
}
}
由此生成的哈希为0xdf4ccab87521641ffc0a552aea55be3a0c583544dc761541784ec656668f4c5a
虽然在 Python3 中,我无法为整数值生成相同的值。如果我将其类型转换为字符串,那么我可以获得一些值,但这与 Solidity 的值不匹配:
>>> s=sha3.keccak_256(repr(data).encode('utf-8')).hexdigest()
>>> print(s)
37aafdecdf8b7e9da212361dfbb20d96826ae5cc912ac972f315228c0cdc51c5
>>> print(data)
1231522228250
感谢任何帮助。
您需要构建正确的二进制表示形式,它应该是两个 32 字节的整数连接在一起。可能还有其他方法可以做到这一点,但这里有一种方法可以使用正确的填充将所有内容转换为十六进制,然后使用 binascii.unhexlify
转换为字节序列:
sha3.keccak_256(binascii.unhexlify('{:064x}{:064x}'.format(123, 1522228250))).hexdigest()
# output: 'df4ccab87521641ffc0a552aea55be3a0c583544dc761541784ec656668f4c5a'
解决方案
查看 web3
python 库,它有许多有用的功能*。在这种情况下,我们可以使用 Web3.soliditySha3()
。您传入类型和数据,它会为您生成哈希,如下所示:
from web3 import Web3
result = Web3.soliditySha3(['uint256', 'uint256'], [123, 1522228250])
assert result == "0xdf4ccab87521641ffc0a552aea55be3a0c583544dc761541784ec656668f4c5a"
Web3 v4 注意事项
v4 即将推出。它在很多地方已经从十六进制字符串切换到 bytes
,包括这个函数。因此,如果您使用 pip install --pre web3
安装(我建议您这样做,直到 v4 稳定下来),以上内容略有修改:
assert Web3.toHex(result) == "0xdf4ccab87521641ffc0a552aea55be3a0c583544dc761541784ec656668f4c5a"
其他资源
Ethereum StackExchange 是一个非常活跃的 Ethereum-specific 问题站点。您可能会得到更快的回复,并找到更多 already-asked 问题。例如,这里提出了类似的问题:Python and Solidity keccak256 function gives different results.
* 免责声明:我是 web3.py repo.
的贡献者
我正在尝试在 Python 中生成由 Solidity 生成的相同 sha3.keccak_256 整数值。
这是 Solidity 的作用:
pragma solidity ^0.4.18;
contract GenerateHash{
function generateHashVal(int id, int date) pure public returns (bytes32){
//Using values - (123,1522228250);
return keccak256(id,date);
}
}
由此生成的哈希为0xdf4ccab87521641ffc0a552aea55be3a0c583544dc761541784ec656668f4c5a
虽然在 Python3 中,我无法为整数值生成相同的值。如果我将其类型转换为字符串,那么我可以获得一些值,但这与 Solidity 的值不匹配:
>>> s=sha3.keccak_256(repr(data).encode('utf-8')).hexdigest()
>>> print(s)
37aafdecdf8b7e9da212361dfbb20d96826ae5cc912ac972f315228c0cdc51c5
>>> print(data)
1231522228250
感谢任何帮助。
您需要构建正确的二进制表示形式,它应该是两个 32 字节的整数连接在一起。可能还有其他方法可以做到这一点,但这里有一种方法可以使用正确的填充将所有内容转换为十六进制,然后使用 binascii.unhexlify
转换为字节序列:
sha3.keccak_256(binascii.unhexlify('{:064x}{:064x}'.format(123, 1522228250))).hexdigest()
# output: 'df4ccab87521641ffc0a552aea55be3a0c583544dc761541784ec656668f4c5a'
解决方案
查看 web3
python 库,它有许多有用的功能*。在这种情况下,我们可以使用 Web3.soliditySha3()
。您传入类型和数据,它会为您生成哈希,如下所示:
from web3 import Web3
result = Web3.soliditySha3(['uint256', 'uint256'], [123, 1522228250])
assert result == "0xdf4ccab87521641ffc0a552aea55be3a0c583544dc761541784ec656668f4c5a"
Web3 v4 注意事项
v4 即将推出。它在很多地方已经从十六进制字符串切换到 bytes
,包括这个函数。因此,如果您使用 pip install --pre web3
安装(我建议您这样做,直到 v4 稳定下来),以上内容略有修改:
assert Web3.toHex(result) == "0xdf4ccab87521641ffc0a552aea55be3a0c583544dc761541784ec656668f4c5a"
其他资源
Ethereum StackExchange 是一个非常活跃的 Ethereum-specific 问题站点。您可能会得到更快的回复,并找到更多 already-asked 问题。例如,这里提出了类似的问题:Python and Solidity keccak256 function gives different results.
* 免责声明:我是 web3.py repo.
的贡献者