比特币地址包含校验和。Base58Check 算法在应用Base58 编码之前,使用哈希函数的前四个字节作为校验和。
以太坊地址最初不包含校验和,但后来发现需要校验和。如何在不破坏向后兼容性的情况下,将校验和追溯到地址中?以下是以太坊在采用EIP-55提案时的做法。
以太坊地址是公钥 Keccak-256 哈希值的最后 20 个字节(40 个十六进制字符)。协议允许十六进制地址中的字母使用大写或小写。此选项为改进校验和提供了灵活性。您可以故意混合使用大小写字母,在密钥之上编码一条额外的消息(即校验和)。这有点像隐写术,只不过它是公开的,而不是隐藏的。
十六进制表示法使用 10 位数字和 6 个字母,因此一个十六进制字符是字母的概率为 6/16。平均而言,一个包含 40 个十六进制字符的字符串包含 15 个字母。这意味着,通过交替字母的大小写,平均可以向以太坊地址添加 15 位信息。
可以想象,一个地址可能不包含任何字母,或者完全由字母组成。一个由 40 个十六进制字符组成的随机字符串的字母数量是一个二项式随机变量,其参数为n = 40 和p = 3/8,这近似于一个均值为 15、标准差为 3 的正态随机变量。这意味着以太坊地址中的字母数量将相当紧密地聚集在 15 个左右,很少超过 21 个或少于 9 个。
好的,但是如何利用平均15 位的自由呢?你无法对 15 位的数字进行编码,因为你可能没有 15 位可用。
EIP-55 的做法如下:将地址及其 Keccek-256 哈希值(本身就是一个哈希值:实际上包含两个哈希值)左对齐,并将地址中所有字母大写,并与大于或等于 0x8 的地址字符对齐。
举个例子,假设我们的地址是
7341e5e972fc677286384f802f8ef42a5ec5f03b
这个地址包含 13 个字母,这并不罕见。现在我们来计算它的哈希值。
>>> 从 Crypto.Hash 导入 keccak >>> kh = keccak.new(digest_bits=256) >>> kh.update(b"7341e5e972fc677286384f802f8ef42a5ec5f03b").hexdigest() 'd8e8fcb225fb835fdb89a5918e736820ec75b3efaf3cbb229f03cdc41bf9f254'
现在我们将地址和它的哈希值排列起来。
341e5e9 72f c67 72 86384f 8 0 2 f8 ef4 2 a5 ec 5f 0 3 b d8e8fcb225fb835fdb89a5918e736820ec75b3e...
地址中与 0x8 到 0xf 哈希字符对齐的字符将以红色突出显示。数字将保持不变,但红色字母将变为大写。
341E5E972fc677286384F802F8ef42a5EC5f03B
相关文章
文章“改造错误检测”最先出现在John D. Cook上。
原文: https://www.johndcook.com/blog/2025/07/27/retrofitting-error-detection/