保护密码的最好方法是使用加盐哈希;
哈希算法
哈希算法是一种单向函数,把任意数量的数据转换成固定长度的“指纹”,这个过程无法逆转。如果输入发生一点改变,由此产生的哈希值完全不同。
基于哈希加密账号系统中,用户注册和认证的大致流程如下:
-
用户创建自己的账号;
-
密码经过哈希加密后存储在数据库中。密码一旦写入磁盘,任何时候都不允许明文形式;
-
用户试图登录时,系统从数据库取出已经加密的密码,和经过哈希加密的用户输入的密码进行对比;
-
如果哈希值相同,用户将被授权访问。否则,告知输入登录信息无效;
只有加密哈希函数才可以用来进行密码哈希加密,像:sha256,sha512,ripemd和whirlpool都是加密哈希函数;
如何破解哈希
字典法:
破解哈希加密的最简单方法是尝试猜测密码,哈希每个猜测的密码,并对比猜测密码的哈希值是否等于被破解的哈希值。如果相等则猜中。猜测密码攻击的两种常见的方法是字典攻击和暴力攻击。
查表法:
破解相同类型的哈希值,查表法是一种非常高效的方式,主要理念是预先计算出密码字典中的每个密码的哈希值,然后存储相应的密码到一个表里。
反向查表法:
攻击者从被黑的用户账号数据库创建一个用户名和对应的哈希表,然后攻击者猜车一系列哈希值并使用该查询表来查找使用此密码的用户。通常许多用户都是用相同的密码,这种方式非常有效。
彩虹表:
彩虹表是一种以空间换时间的技术。与查表法相似,只是使查询表更小,牺牲了破解速度。因为彩虹表更小,所以单位空间可以存储更多的哈希值,从而使攻击更有效。能够破解任何最多8位长度的MD5值擦彩虹表已经出现。
加盐:
查表和彩虹表只有在所有密码都以完全相同的方式进行哈希加密才有效,如果两个用户有相同的密码,他们将有相同的密码哈希值。可以通过随机化哈希,当同一个密码哈希两次后,得到的哈希值是不一样的,从而避免了这种攻击。
可以通过再密码中加入一段随机字符串进行哈希加密,这个被加的字符串称为盐值。这使得相同密码每次都被加密为完全不同的字符串,需要盐值来校验密码是否正确。通常和密码哈希值一同存储在账号数据库中。
盐值无需加密,由于随机化了哈希值,查表法,反向查表法,彩虹表都会失效。因为攻击者无法事先知道盐值,所以他们没有办法预先计算。
盐值使用误区
盐值复用:
错误就是每次都是用相同的盐值进行哈希加密,这个盐值要么被硬编码到程序中,要么只在第一次使用时随机获得。这样做法是无效的,因为如果两个用户有相同的密码,他们会有相同的哈希值。
短盐值:
如果盐值太短,攻击者可以预先制作针对于所有可能的盐值的查询表。不应该将用户名作为盐值,对每个服务而言 ,用户名是唯一的,他们是不可预测的。为使攻击者无法构造包含所有可能盐值的查询表,盐值必须足够大,一个好的经验使用和哈希函数输出的字符串相等长的盐值。
双重哈希和古怪的哈希函数:
哈希碰撞:
由于哈希函数将任意大小的数据转换成定长的字符串,因此,必定一些不同的输入经过哈希计算之后得到相同的字符串的情况。可通过加盐的方式解决。
如何正确进行哈希加密
基础知识:加盐哈希
盐值应该使用加密的安全伪随机数生成器产生。必须使用 CSPRNG;
存储密码步骤:
-
使用 CSPRNG生成足够长的随机盐值;
-
将盐值混入密码,并使用标准的密码哈希函数进行加密 ,如Argon2、 bcrypt 、 scrypt 或 PBKDF2 ;
-
将盐值和对应的哈希值一起存入数据库;
校验密码步骤:
-
从数据库检索用户的盐值和响应的哈希值;
-
将盐值混入用户输入的密码,并且使用通用的哈希函数进行加密;
-
比较上一步的结果,是否和数据库存储的哈希值相同。相同则密码正确,否则错误;