为什么像sha1这样的哈希函数最多只使用16个不同的字符(十六进制)


Why hashing functions like sha1 use only up to 16 different char (hexadecimal)?

很抱歉我这么好奇。

sha1使用[a-f0-9]字符作为其哈希函数。我可以知道为什么它不使用所有可能的字符[a-z0-9]吗?通过使用所有可用的字符,它可以大大增加可能的不同哈希的数量,从而降低可能的碰撞的可能性。

如果你不认为这是一个真正的问题,只需留言,我会立即删除这个问题。

===

如答案中所述,sha1执行NOT仅使用16 chars。正确的事实是:sha1是160位二进制数据(引用)。我添加这个是为了防止混淆。

您混淆了表示内容

sha1160位二进制数据。你可以很容易地用来表示它

hex: 0xf1d2d2f924e986ac86fdf7b36c94bcdf32beec15
decimal: 1380568310619656533693587816107765069100751973397
binary: 1111000111010010110100101111100100100100111010011000011010101100100001101111110111110111101100110110110010010100101111001101111100110010101111101110110000010101
base 62: xufK3qj2bZgDrLA0XN0cLv1jZXc

十六进制并没有什么神奇之处。这只是一种非常常见的机制,用于显示沿4位边界轻松突破的内容。

base 62输出是用这个小ruby生成的:

#!/usr/bin/ruby
def chars_from_hex(s)
  c = s % 62
  s = s / 62
  if ( s > 0 )
    chars_from_hex(s)
  end
  if (c < 10)
      print c
  elsif (c < 36)
      print "abcdefghijklmnopqrstuvwxyz"[c-11].chr()
  elsif (c < 62)
      print "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[c-37].chr()
  else
      puts "error c", c
  end
end
chars_from_hex(0xf1d2d2f924e986ac86fdf7b36c94bcdf32beec15)

它使用了从一个碱基转换为另一个碱基的标准习语,并将0-9视为0-9,a-z视为10-35,A-Z视为36-61。如果需要的话,它可以通过包括例如!@#$%^&*()-_=+'|[]{},.<>/?;:'"~`来简单地扩展以支持更多的数字。(或者任何一个庞大的Unicode代码点。)

@yes123特别询问了散列的ascii表示,因此以下是将160位散列直接解释为ascii的结果:

ñÒÒù$é¬ý÷³l¼ß2¾ì

它看起来不太像,因为:

  • 对于小于32的字节值,ascii没有很好的可打印表示
  • ascii本身不能表示大于127的字节值,127和255之间的值将根据iso-8859-01或其他字符编码方案进行解释

这种基础转换在实践中也很有用;Base64编码方法使用64个(而不是我的62个)字符来一次表示6个比特;它还需要两个字符来表示"数字"和一个字符来填充。UUEncoding选择了一组不同的"数字"。一位同事遇到了一个问题,通过将输入数字的基数改为输出数字,这个问题很容易解决。

这是错误的推理。sha1使用40*4=160比特。

恰好将其格式化为40个十六进制数字是很方便的(因此也是惯例)。

如果你觉得自己处于160位中可能开始发生冲突的问题域,你可以使用哈希大小更大的不同加密哈希

 sha224: 224 bits
 sha256: 256 bits
 md5: 128 bits

使用十六进制只允许更容易地显示。SHA1使用160位。通过对其进行十六进制编码,它允许摘要以字符串的形式轻松显示和传输。仅此而已。

哈希算法的输出是位。用十六进制表示它们只是一种表示。它确实受益于长度为0 mod 16的结果,因此在基17中的表示将是不方便的。

sha-1生成一个160位的散列,即20个字节,其中有1461501637330902918203684832716283019655932542976个可能的值。因为散列算法就是这样定义的。

然而,将散列编码为可读文本通常是有用的,一种方便的方法是将这20个字节简单地编码为十六进制(将占用40个字节)。十六进制字符是[a-f0-9。