密文存储

数据库中用户的密码一般是密文存储的,作用 ?

  • 防止被脱裤后账号泄露
  • 防止内部DBA或者有权限人员直接可以看到用户账号密码

加密hash算法

传统的md5加密,在彩虹表的攻势下已经不再安全,新的加密方法呢?

可以使用

  • OpenWall的Portable PHP password hashing framework
  • 经过充分测试的加密hash函数,比如SHA256, SHA512, RipeMD, WHIRLPOOL, SHA3等
  • 设计良好的key扩展hash算法,比如PBKDF2,bcrypt,scrypt
  • crypt的安全版本。($2y$, $5$, $6$)

不要使用

  • 过时的hash函数,比如MD5,SHA1
  • crypt的不安全版本。($1$, $2$, $2x$, $3$)
  • 任何自己设计的算法。

只依靠hash隐患

优秀的hash算法加密可以保障密文的安全,但如果多个企业只用一套”安全的加密算法”会有什么隐患?

  1. 网站A被脱裤,密文保障了密码的安全,但脱裤者自己注册一个号,得到了密文, 就可以得到一个明文->密文的映射,相当于破解了一个密文, 然后在数据中进行 select pwd="xxx" 操作,就可以得到相同密码的用户。
  2. 在密码爆炸的时代,用户在多个网站下的密码很可能是一样的,参考扎克伯克fb twitter linkedin 密码设置一样,被黑客破解的事件。
    这样的话, 一个网站被脱裤,所以网站都有了危机。

显然,除了优秀的hash算法加密外,可以对它进行一点改进或者说增强, 一种方法就是 加盐

盐(salt) 是开发设计者设计的一种随机字符串,在密文中加上盐的干扰,可以加大破解难度,变相提高安全性。

md5(md5(pwd) + salt) , 但md5已经不再安全。

改良下, SHA512( SHA512(pwd) + salt )

但暴力破解也是一个问题,利用一种慢哈希算法,设置一次加密的时间,执行一次hash加密会很慢,提高暴力破解的时间,变相提高安全性。
bcrypt(SHA512(pwd), salt, cost)

存储与验证过程

存储一个密码:

  1. 使用CSPRNG生成一个长的随机盐。
  2. 将密码和盐拼接在一起,使用标准的加密hash函数比如SHA256进行hash
  3. 将盐和hash记录在用户数据库中

验证一个密码:

  1. 从数据库中取出用户的盐和hash
  2. 将用户输入的密码和盐按相同方式拼接在一起,使用相同的hash函数进行hash
  3. 比较计算出的hash跟存储的hash是否相同。如果相同则密码正确。反之则密码错误。

资料: (http://drops.wooyun.org/papers/1066) (http://blog.coderzh.com/2016/01/10/a-password-security-design-example/)