这并不是关于以太坊使用非标准sha3的问题。 我找到了正确的JS哈希库,并且能够将JS中的哈希值与Solidity字节字符串匹配起来。 我想知道的是:当我把单元uint传递给JS哈希库时,如何表示这个单元,使得它产生的结果与Solidity sha3生成的哈希值一样。

JS
'0x' + keccak(
  1
)
// 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

Solidity
sha3(
  1
);
// 0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2

原文地址

3 人回答 0

3 个回答
投票数
最旧发布
最近发布

回答发布于 2018-09-07 16:18:47

Jehan的回复很棒,但我需要进一步解释一下:为什么在solidity中sha3(1)的结果是b10e2d...fa0cf6?

这是因为solidity的sha3函数是根据参数类型对其输入进行哈希运算的。 因此,如果将数值1存储为bytes8bytes16bytes32等不同类型,那么数值1将生成不同的哈希值。由于sha3(1)1作为数字文本传递,因此将其转换为最小的类型uint8

8位适合2个十六进制字符,因此如果你将输入填充为2个字符,那么你将在web3中获得同样的结果:

Javascript

web3.sha3(leftPad((1).toString(16), 2, 0), { encoding: 'hex' })
// 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2

同样的,你可以把这个数字放在Solidity的一边:

Solidity

// uint is equivalent to uint256
sha3(uint(1))
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6

Javascript

// note that the value is padded by 64 characters to fit 256 bits
web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6

关于BigNumber类型的注释

它们不会自动与web3.sha3一起执行。你必须先把它们转换成十六进制。

Solidity

sha3(uint(100 ether))
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273

Javascript

// the .slice is to remove the leading '0x'
web3.sha3(leftPad(web3.toHex(web3.toWei(100)).slice(2).toString(16), 64, 0), { encoding: 'hex' })
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273

编注

我写了一个能够提供了web3.sha3版本的简单lib——能够与Solidity中sha3操作完全匹配。希望这能解决你所有有关哈希计算的问题:)。https://github.com/raineorshine/solidity-sha3

||
||

回答发布于 2018-09-07 16:18:46

Solidity内部使用十六进制的值

> web3.sha3(web3.toHex(1))
"5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2"
||
||

回答发布于 2018-09-07 16:18:45

Solidity的sha3函数对uint的字节表示进行哈希运算。 也就是说,十六进制数(基数为16),填充为32个字节。十六进制表示中的32个空字节是64个零。

要在JS中执行此操作,我们可以使用左填充包(left-pad package):

const jsHashWeb3 = web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
||
||

回答发布于 2018-09-07 16:18:45

Solidity的sha3函数对uint的字节表示进行哈希运算。 也就是说,十六进制数(基数为16),填充为32个字节。十六进制表示中的32个空字节是64个零。

要在JS中执行此操作,我们可以使用左填充包(left-pad package):

const jsHashWeb3 = web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
||
||

回答发布于 2018-09-07 16:18:46

Solidity内部使用十六进制的值

> web3.sha3(web3.toHex(1))
"5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2"
||
||

回答发布于 2018-09-07 16:18:47

Jehan的回复很棒,但我需要进一步解释一下:为什么在solidity中sha3(1)的结果是b10e2d...fa0cf6?

这是因为solidity的sha3函数是根据参数类型对其输入进行哈希运算的。 因此,如果将数值1存储为bytes8bytes16bytes32等不同类型,那么数值1将生成不同的哈希值。由于sha3(1)1作为数字文本传递,因此将其转换为最小的类型uint8

8位适合2个十六进制字符,因此如果你将输入填充为2个字符,那么你将在web3中获得同样的结果:

Javascript

web3.sha3(leftPad((1).toString(16), 2, 0), { encoding: 'hex' })
// 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2

同样的,你可以把这个数字放在Solidity的一边:

Solidity

// uint is equivalent to uint256
sha3(uint(1))
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6

Javascript

// note that the value is padded by 64 characters to fit 256 bits
web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6

关于BigNumber类型的注释

它们不会自动与web3.sha3一起执行。你必须先把它们转换成十六进制。

Solidity

sha3(uint(100 ether))
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273

Javascript

// the .slice is to remove the leading '0x'
web3.sha3(leftPad(web3.toHex(web3.toWei(100)).slice(2).toString(16), 64, 0), { encoding: 'hex' })
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273

编注

我写了一个能够提供了web3.sha3版本的简单lib——能够与Solidity中sha3操作完全匹配。希望这能解决你所有有关哈希计算的问题:)。https://github.com/raineorshine/solidity-sha3

||
||

回答发布于 2018-09-07 16:18:47

Jehan的回复很棒,但我需要进一步解释一下:为什么在solidity中sha3(1)的结果是b10e2d...fa0cf6?

这是因为solidity的sha3函数是根据参数类型对其输入进行哈希运算的。 因此,如果将数值1存储为bytes8bytes16bytes32等不同类型,那么数值1将生成不同的哈希值。由于sha3(1)1作为数字文本传递,因此将其转换为最小的类型uint8

8位适合2个十六进制字符,因此如果你将输入填充为2个字符,那么你将在web3中获得同样的结果:

Javascript

web3.sha3(leftPad((1).toString(16), 2, 0), { encoding: 'hex' })
// 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2

同样的,你可以把这个数字放在Solidity的一边:

Solidity

// uint is equivalent to uint256
sha3(uint(1))
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6

Javascript

// note that the value is padded by 64 characters to fit 256 bits
web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6

关于BigNumber类型的注释

它们不会自动与web3.sha3一起执行。你必须先把它们转换成十六进制。

Solidity

sha3(uint(100 ether))
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273

Javascript

// the .slice is to remove the leading '0x'
web3.sha3(leftPad(web3.toHex(web3.toWei(100)).slice(2).toString(16), 64, 0), { encoding: 'hex' })
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273

编注

我写了一个能够提供了web3.sha3版本的简单lib——能够与Solidity中sha3操作完全匹配。希望这能解决你所有有关哈希计算的问题:)。https://github.com/raineorshine/solidity-sha3

||
||

回答发布于 2018-09-07 16:18:46

Solidity内部使用十六进制的值

> web3.sha3(web3.toHex(1))
"5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2"
||
||

回答发布于 2018-09-07 16:18:45

Solidity的sha3函数对uint的字节表示进行哈希运算。 也就是说,十六进制数(基数为16),填充为32个字节。十六进制表示中的32个空字节是64个零。

要在JS中执行此操作,我们可以使用左填充包(left-pad package):

const jsHashWeb3 = web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
||
||