密码加盐哈希

Salted Password Hashing - Doing it Right 收获很大,之前有很多理解都是错误的。安全问题很难被测试出来,遵循安全规范是最佳策略。

本文主要讨论密码的安全,但有一些方法和原则是通用的。

1 不用自作聪明

柯克霍夫原则(Kerckhoffs' principle):安全不依赖于算法,只依赖于秘钥。所以不要试图实现自己的加密(哈希)算法,或者组合已有算法,试图通过算法的“私有”来抵御攻击。

2 密码哈希

哈希是一种单向函数, H(p) = q ,没有办法根据q计算出p,并且不同的p计算出的q不同。我们通过存储密码的哈希值,就算密码库泄露了,根据哈希值也无法获取密码,达到安全的目的。然而,并非如此。(主要还是密码太短了,且不够随机。如果密码长度都是1K以上的随机字符串,也很安全。)

3 哈希的破解

3.1 字典或暴力破解

通过算出常用密码表或者字符排列的哈希,对比密码库的哈希,如果命中,密码破解。这种方式效率太低,尤其是暴力破解。(借助GPU,短密码的破译问题不大)

3.2 查找表

预先计算出密码和哈希的对应表,对比哈希,找到密码。效率很高。大家在密码上的想象力太小了,整个密码空间并不大。

3.3 反向查找表

没看懂

3.4 彩虹表

一种优化的查表法,隐含存储的表更大,但实际用的空间缺不大,查找时耗费更多CPU。

4 加盐

查表法和彩虹表能工作是因为密码和密码的哈希是一一对应的。例如:sha256("iop3er") 的结果是 3fd23da8467ae302aec51d7d73e14924cfb9c5e6fbc0b6cd6764ea681d292aa0 ,这种对应让哈希值和密码等价了。 加盐 就是打破这种一一对应。例如:sha256("iop3er" + "Abt3dE") 的结果是 c668ba513909925384d766f6b8fd488055614fab6e34fa873ce29c12390ef389,sha256("iop3er" + "Px2I9g") 的结果是 7a14a66eaad6fa1d66ba540a82bfb808bf3dd216bc8c79ae3bffba2a144f0c5b。就算知道了 和哈希值,因为密码和哈希值不再一一对应,破解难度大大增加。

4.1 加盐的误区

4.1.1 重复使用相同的盐

的目的是增加不确定性,应该每个密码使用不同的盐,盐和密码哈希存放在一起。

4.1.2 盐的长度(空间)太短

盐的长度至少和哈希值一样长,例如用sha256哈希,盐至少32个字节,并且从所有可见ascii码中选取

5 慢哈希

加盐 也无法抵御暴力破解,借助先进的GPU和专门硬件,1秒可以计算数10亿哈希。为了降低破解的效率,可以使用 秘钥延伸 (key stretching)。 秘钥延伸 的核心是让哈希变慢,这样即使使用GPU或专门硬件破解也变的非常耗时(但不影响正常用户登陆体验)。常见的慢哈希算法有 PBKDF2 bcrypt

6 使用哈希key或者加密哈希

可以(DES)加密哈希或者使用Hmac(基于哈希的消息认证码)。不要把key和密码拼一起,然后做hash,要使用hmac。(我见过很多认证系统是将key和请求的其它信息拼一起做哈希,作为签名的),要注意哈希key或秘钥的保密。

Author: root

Created: 2017-07-25 二 12:30

Validate