交易参数:RLP(nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0)。 使用 Keccak256 算法来计算经过 RLP 编码的未签署交易的哈希值。 按照上文讲述的步骤,通过 ECDSA 算法,使用私钥签署哈希值。 对已签名的交易进行编码:RLP(nonce, gasPrice, gasLimit, to, value, data, v, r, s)。 将经过 RLP 编码的交易数据解码后,我们又可以得到原始交易参数和签名。 请注意,链 ID 是被编码到签名的 v 参数中的,因此我们不会将链 ID 本身包含在最终的签名交易数据中。我们也不会提供任何发送方地址,因为地址可以通过签名恢复。这就是以太坊网络内部用来验证交易的方式。 签名消息的标准化 关于如何为签名消息定义标准结构,人们提出了很多种提议。目前为止,还没有一个提议最终确定下来。最初由 Geth 实现的 personal_sign 格式依然是最常见的。尽管如此,有一些提议非常有趣。 我先来简单介绍下目前创建签名所采用的方式: "\x19Ethereum Signed Message:\n" + length(message) + message 消息通常会预先进行哈希计算,因此长度会固定在 32 个字节: "\x19Ethereum Signed Message:\n32" + Keccak256(message) 完整的消息(包括前缀)会再经历一次哈希计算,然后用私钥对哈希值签名。这种方式适用于所有权证明,但是在其它情况下可能会出现问题。例如,如果用户 A 签署了一个消息并将其发送给合约 x,用户 B 可以复制这个已签署消息并发送给合约 Y。这就叫重放攻击。有一些提案旨在解决这一问题,如 EIP 191 和 EIP 721。 EIP 191:签名数据标准 EIP 191 是一个很简单的提案:它定义了版本号和版本专有数据。格式如下所示: 0x19 <1 byte version> <version specific data> <data to sign> 顾名思义,版本专有数据(version specific data)取决于我们所使用的版本。目前,EIP 191 有三个版本:
如果我们指定目标验证者(如,合约地址),该合约可以使用自己的地址来重新计算哈希值。将已签署消息提交到不同的合约实例是行不通的,因为后者无法验证签名。 由于 0x19 已经被选为固定的字节前缀,签名消息无法成为经过 RLP 编码的签名交易,因为后者永远不会以 0x19 开头。 (责任编辑:admin) |