hash函数与密码的暴力破解

0x00 背景

在某乎上看到了一个关于密码如何保存的问题,整理一下自己的理解。

0x01 理解

首先使用盐的话明显彩虹表就派不上用场了,除非你所有用户都用同一个盐(怎么可能,那没意义……)。

其次,破解sha256的方法并不是用彩虹表,而是直接用GPU在线暴力破解。这种情况下即使你加了盐,攻击者仍然可以枚举八位字符concat上盐(明文,且很大可能是跟hash后的密码存在同一个地方,很难想象攻击者获得了hash后的密码而没获得盐的情况)后hash,由于sha256本身计算很快,GPU上暴力破解一个8位密码+盐只需要3.4天(Rain Table is Dead),所以如果你被攻击者盯上了(APT?),光使用一个8位密码+盐还是很不安全的。但是如果攻击者想要一次性破解大量用户密码(比如脱了某网站的裤,想获得所有人明文密码)就比较困难了,加了盐后并没有现成的彩虹表可查,而在线暴力破解一个就得数天,2亿人得破解到哪天。

0x02 关于盐(salt)

可以总结出一些关于盐的用法与特性(某乎用户的回答):

  1. 盐必须是随机串
    有的公司为了方便,把时间、用户名、ip地址什么的作盐,其实比较作死。因为不随机的字串具有规律性,有人尝试过直接构造非随机盐的彩虹表,好像效果也不错。
  2. 盐不能太短
    和密钥不能太短是一个道理,假设是8位盐,也就256种可能。为每个盐造个彩虹表也OK,反正现在存储不值钱。
  3. 盐不能复用
    每个用户都需要一个随机盐,理由很简单,如果是统一盐,那和直接hash其实是一样的
  4. 盐存在用户表里面
    基本盐都和用户表一起存,因为本身就是明文保存的,所以对盐也不需要有安全保存的考虑,方便业务实现就行。
  5. 加盐不是为了密码不被破解,而是为了密码不被批量破解!

0x03 结论

可以看出,加盐可以防止彩虹表批量破解,但是并不能防止定向暴力破解。那么如何防止被定向破解呢?可以使用一些计算速度较慢的hash函数,比如PBKDF2(Speed HashingSalted Password Hashing,其实就是把基础那些hash算法反复迭代数千次,以达到增加计算量的目的),这样即使用GPU暴力破解,破解时间也很漫长。

所以防定向破解(APT?)要用PBKDF2这种慢的,防止被在线破解;当然从对所有用户负责的角度来说,即使是B2C的web application能用PBKDF2是最好的了。