SHA哈希详解:SHA-1、256、384、512到底有什么区别

哈希函数会把任意输入转换成固定长度的字符串,理解这个过程到底保证了什么、又没有保证什么,基本就能明白哈希值都用在哪些地方。

哈希是单向计算的

从输入计算出哈希值很快很容易,但反过来从哈希值推算出原始输入在计算上被设计成基本不可行——这正是哈希和加密的根本区别,加密在有正确密钥的情况下是可以还原的。

输出长度始终固定

无论输入是一个字符还是一整本书的内容,SHA-256的输出始终是256位(16进制64个字符)。正是这种固定长度,让哈希值可以当作任意大小数据的一个紧凑"指纹"来使用。

相同的输入永远得到相同的哈希值

在任何设备上,对同一个输入计算哈希,结果永远一致,这个特性正是哈希被用来验证文件是否被篡改或损坏的原因。

输入哪怕只变化一点点,输出也会完全不同(雪崩效应)

改动输入中的一个字符,就会让输出哈希值整体变得面目全非,而不是只改变其中一部分,所以哈希值没法用来判断两份内容"有多相似",只能判断是否完全一致。

SHA-1在安全场景下已经被攻破

研究者已经实际演示过针对SHA-1的碰撞攻击(找到两个不同输入产生相同哈希值),因此它已不再被认为适合用在证书等对安全性要求高的场景,不过在Git内部对象ID这类非安全用途或一些历史遗留系统中仍然能见到它。

SHA-256、SHA-384、SHA-512的主要区别在输出长度

三者都属于同一个SHA-2家族,目前都被认为是安全的。数字代表输出的位数,位数越长理论上的安全余量越大,但计算量也会略有增加。

哈希不是加密

一个常见的误解是把哈希当成"打乱了但还能还原"的数据形式,实际上并不存在任何密钥或流程能把哈希值还原成原始输入。这正是为什么哈希被用来验证数据(证明两份内容是否一致),而不是用来保护那些以后还需要取回原文的数据。

为什么密码不能只靠普通哈希来保护

直接存储密码的SHA-256哈希值仍然容易受到预先计算好的彩虹表和暴力破解攻击,因为同一个密码永远会得到同一个哈希值。真正的密码存储系统会为每个用户加上随机的"盐值",并使用专门设计得很慢的算法(比如bcrypt或Argon2),而SHA-256这类通用的快速哈希算法并不适合这个用途。

常见问题

两个文件的哈希值一样,就一定说明这两个文件完全相同吗?

对SHA-256、SHA-384、SHA-512来说,在实际使用中可以这么认为,偶然发生碰撞的概率低到几乎不可能。但SHA-1已经被证实可以人为制造出碰撞,所以不应该再用它来做安全性要求高的完整性校验。

可以用哈希生成器来检查下载的文件是否损坏吗?

可以,这正是哈希最常见也最正当的用途之一。把发布方提供的哈希值,和你用下载下来的文件重新生成的哈希值进行比较,如果一致,就说明文件在传输过程中没有被篡改或损坏。