为什么SHA-1哈希只有160位,但却有40个字符长?

46

这个问题的标题已经说得很清楚了。我一直在研究SHA-1,大多数地方看到的都是由40个十六进制字符组成,对我来说这是640位。它不能只用10个十六进制字符表示吗?160位=20字节。而一个十六进制字符可以表示2个字节,对吧?为什么长度是需要的两倍呢?我的理解哪里错了吗?

如果使用Base32或Base36,SHA-1是否可以甚至只有5个或更少的字符?

6个回答

101

一个十六进制字符只能表示16个不同的值,即4位二进制数。(16 = 24

40 * 4 = 160。


不,你需要比36进制更多的5个字符。

共有2160种不同的SHA-1哈希值。

2160 = 1640,这就是为什么我们需要40个十六进制数字的另一个原因。

但2160 = 36160 log362 = 3630.9482...,因此仍需要使用36进制中的31个字符。


20
如果你使用基数为“4.3e9”,那么你可以拥有5个字符。 - NullUserException
1
@NullUserException:不幸的是,在约基数2.09e6后,我用完了所有数字。 - Ben Hocking
非常感谢您的解释,我知道我的数学肯定出了问题。已经有几年没有做过这么复杂的数学了。 - AGrunewald
1
有趣的是,如果您将字符集增加一倍以上(从16到36),您会期望生成的字符串大小会减少一半以上,但实际上并没有发生这种情况(仅从40减少到31)... - Jeyekomon

16

我认为OP的困惑来自于表示SHA1哈希的字符串占用40个字节(至少在使用ASCII时),相当于320位(而不是640位)。

原因在于哈希值是以二进制方式存储的,而十六进制字符串只是对其进行编码。因此,如果您使用更高效的编码(或根本不使用编码),则可以仅使用160位空间(20个字节),但这样做的问题是它不是二进制安全的。

您可以使用base64,这样您只需大约27-28个字节(或字符),而不是40个字节(请参见此页面)。


9

每8位字节有两个十六进制字符,而不是每个十六进制字符有两个字节。

如果您正在处理8位字节(如SHA-1定义中),那么一个十六进制字符编码一个字节内的单个高位或低位4位二进制数。因此,一个完整的字节需要两个这样的字符。


7

我的回答与之前的回答不同之处在于我对问题产生困惑的确切原因的理论解释,以及我提供的逐步解释方法。

一个字符所占用的字节数取决于所使用的编码方式(请参见此处)。现在有一些情况下我们使用2个字节来表示一个字符,例如在Java编程时(这里是原因)。因此,40个Java字符将等于80字节= 640位,正是OP的计算结果。而10个Java字符确实可以包含SHA-1哈希所需的正确信息量。

然而,与成千上万种可能的Java字符不同,只有16个不同的十六进制字符,即0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E和F。但是这些字符并不相同于Java字符,并且比编码Java字符0到9和A到F所占用的空间更少。它们是表示仅由4位表示的所有可能值的符号:

0  0000    4  0100    8  1000    C  1100
1  0001    5  0101    9  1001    D  1101
2  0010    6  0110    A  1010    E  1110
3  0011    7  0111    B  1011    F  1111

因此,每个十六进制字符只有半个字节,40个十六进制字符给我们20个字节=160位 - 这是SHA-1哈希的长度。

6

两个十六进制字符组成了0-255的范围,即0x00 == 0,0xFF == 255。因此,2个十六进制字符为8位,这使得您的SHA摘要为160位。


4

SHA-1是160位。

这相当于20个字节=40个十六进制字符(每个字节2个十六进制字符)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接