为什么大多数散列函数产生的散列包含 0-9 之间的字符?

信息安全 哈希 md5 河豚
2021-08-25 00:53:44

这是我从不了解散列函数的事情。我知道像漩涡和河豚这样的算法都会产生不遵循这种模式的输出,但为什么大多数人都会这样做呢?它是某种硬件/软件的东西吗?如果他们确实产生了 a-z0-9 而不是 a-f0-9 的输出,那不会增加他们的复杂性吗?

3个回答

它只是十六进制编码。一个 16 字节的 md5 散列可以包含不可打印的字符,因此它被编码为一个 32 字符的十六进制字符串。

正如其他人所回应的那样,散列函数(所有这些函数,包括 MD5、SHA-256、Whirlpool 和其他几十个函数)输出MD5 的输出为 128 位。但是,人类不擅长读取位。人类善于阅读文字因此,当哈希函数输出用于人类消费时,它会被转换为具有某种编码的字符。

十六进制是将位编码为字符的最简单的编码之一。它将一个四位块转换为“a”到“f”范围内的数字或字符。存在其他编码,例如Base64,它使用更大的字母表(64 个符号而不是 16 个)并且更紧凑(MD5 的 128 位输出在 Base64 中编码为 24 个字符,而在十六进制中编码为 32 个字符),但更多实现起来很复杂。

十六进制有许多可能的变体;例如,我们可以每隔几个字符添加一些空格(以方便阅读),或其他标点符号,例如冒号(':');我们可以使用大写或小写字母。散列函数输出的传统是使用没有空格或标点符号的小写字母。这一传统在 MD5 的初期就已经生效:MD5 于 1991 年设计,于 1992 年 4 月作为RFC 1321发布;正如您在该文档中看到的(接近结尾,A.5 节),哈希输出已经使用小写十六进制。

Thomas Pornin 的回答很好,但还有一点。哈希输出不仅是传统和人类可读性,还有一些地方适用于输入RFC2069 中在摘要访问身份验证中,当与更多数据连接时,散列输出会重新散列。但与直觉相反(对我来说)重新散列时使用的散列表示是小写的人类可读的十六进制字符版本,而不仅仅是作为比特流的散列输出,即输入的长度是它需要的两倍。第 3.1.3 节中的 RFC 指定此表示“出于本文档的目的”,这并不像“出于本算法的目的”那样明确,但我的测试表明 Firefox 的实现就是这种情况MD5 显然所有的实现都必须匹配。相反,比特币的双 SHA-256 哈希使用二进制表示你如何执行双 SHA-256 编码?