hash算法是非常基础,也是非常重要的计算机算法,它能够将任意长度的二进制明文串映射为较短的二进制串,映射的结果通常是固定长度的,这个结果就叫hash值。
一个优秀的hash算法,有如下特点:
1.正向快速:给定明文和Hash算法,在有限时间和有限资源内能计算得到Hash值;
2.逆向困难:给定Hash值,在有限时间内很难(基本不可能)逆推出明文;
3.输入敏感:原始输入信息发生任何改变,新产生的Hash值都应该出现很大不同;
4.冲突避免:很难找到两段内容不同的明文,使得它们的Hash值一致(发生碰撞)。
冲突避免有时候又称为“抗碰撞性”,分为“弱抗碰撞性”和“强抗碰撞性”。如果给定明文前提下,无法找到与之碰撞的其他明文,则算法具有“弱抗碰撞性”;如果无法找到任意两个发生Hash碰撞的明文,则称算法具有“强抗碰撞性”。很多场景下,也往往要求算法对于任意长的输入内容,可以输出定长的Hash值结果。
常见hash算法
首先要明白,hash算法并不是一个具体的算法而是一类算法的统称,目前常见的Hash算法包括MD5和SHA系列算法。
MD4(RFC 1320)是MIT的Ronald L.Rivest在1990年设计的,MD是MessageDigest的缩写。其输出为128位。MD4已被证明不够安全。MD5(RFC 1321)是Rivest于1991年对MD4的改进版本。它对输入仍以512位进行分组,其输出是128位。MD5比MD4更加安全,但过程更加复杂,计算速度要慢一点。MD5已被证明不具备“强抗碰撞性”。
SHA(Secure Hash Algorithm)并非一个算法,而是一个Hash函数族。NIST(National Institute of Standards and Technology)于1993年发布其首个实现。目前知名的SHA-1算法在1995年面世,它的输出为长度160位的Hash值,抗穷举性更好。SHA-1设计时模仿了MD4算法,采用了类似原理。SHA-1已被证明不具备“强抗碰撞性”。
为了提高安全性,NIST还设计出了SHA-224、SHA-256、SHA-384和SHA-512算法(统称为SHA-2),跟SHA-1算法原理类似。SHA-3相关算法也已被提出。目前,MD5和SHA1已经被破解,一般推荐至少使用SHA2-256或更安全的算法。
提示:MD5是一个经典的Hash算法,和SHA-1算法一起都被认为安全性已不足应用于商业场景。
性能:
Hash算法一般都是计算敏感型的。意味着计算资源是瓶颈,主频越高的CPU运行Hash算法的速度也越快。因此可以通过硬件加速来提升Hash计算的吞吐量。例如采用FPGA来计算MD5值,可以轻易达到数十Gbps的吞吐量。
也有一些Hash算法不是计算敏感型的。例如scrypt算法,计算过程需要大量的内存资源,节点不能通过简单地增加更多CPU来获得Hash性能的提升。这样的Hash算法经常用在避免算力攻击的场景。
hash攻击与防护:
Hash算法并不是一种加密算法,不能用于对信息的保护。但Hash算法常用于对口令的保存上。例如用户登录网站需要通过用户名和密码来进行验证。如果网站后台直接保存用户的口令明文,一旦数据库发生泄露后果不堪设想。大量用户倾向于在多个网站选用相同或关联的口令。
利用Hash的特性,后台可以仅保存口令的Hash值,这样每次比对Hash值一致,则说明输入的口令正确。即便数据库泄露了,也无法从Hash值还原回口令,只有进行穷举测试。
然而,由于有时用户设置口令的强度不够,只是一些常见的简单字符串,如password、123456等。有人专门搜集了这些常见口令,计算对应的Hash值,制作成字典。这样通过Hash值可以快速反查到原始口令。这一类型以空间换时间的攻击方法包括字典攻击和彩虹表攻击(只保存一条Hash链的首尾值,相对字典攻击可以节省存储空间)等。
为了防范这一类攻击,一般采用加盐(salt)的方法。保存的不是口令明文的Hash值,而是口令明文再加上一段随机字符串(即“盐”)之后的Hash值。Hash结果和“盐”分别存放在不同的地方,这样只要不是两者同时泄露,攻击者就很难破解了。