跳转至

使用哈希算法以及加盐来增强服务端密码存储安全

T20:57:20+08:00

一、明文

用户名和密码以明文方式存储在数据库中,若数据库被拿下,那么攻击者就可以直接拿到所有人的密码。

Text Only
1
2
3
4
|User|Password|
|  1 |  P(1)  |
|  2 |  P(2)  |
|  3 |  P(3)  |

二、使用哈希算法

哈希算法的本质是对数据进行一个不重复的单射。

Text Only
1
2
3
4
P(1) -> P'(1)
P(2) -> P'(2)
P(3) -> P'(3)
...

服务端只存储经过哈希后的密码。客户端在登陆时发送原本的密码,并在服务端使用同样的哈希算法计算,与哈希后的密码进行比对。

Text Only
1
2
3
4
|User|HashedPassword|
|  1 |     P'(1)    |
|  2 |     P'(2)    |
|  3 |     P'(3)    |

这样,若数据库被拿下,攻击者拿到的是 P',而 P' 不能被直接拿来登录(因为 P' 经过一次哈希 不能依然等于 P'),同时也不能反向求得 P。 如此,攻击者必须枚举 P,直至找到一个使用相同哈希算法正向计算后结果与 P' 相同的 P,才是真正的密码。

但是众所周知,万物皆可打表。 作为人类,大多数人设置的密码都缺乏随机性,比如姓名缩写+生日、更有甚者就是一个 123456。攻击者可以使用一个庞大的常见密码库并使用相同的哈希算法预先计算出一大张表,直接与 P' 进行匹配。

三、加盐

将不同用户的密码附加上不同的随机串来形成新的密码,保存对这个密码进行哈希的结果作为存储的密码。(不同的盐值也保存在服务端中)

Text Only
1
2
3
4
S(1) + P(1) -> SP(1) -> SP'(1)
S(2) + P(2) -> SP(2) -> SP'(2)
S(3) + P(3) -> SP(3) -> SP'(3)
...

这样,一来增强了用户密码的随机性,提高了打表难度, 另一方面攻击者计算出的一张表只能针对一个盐值,将对群体的攻击转化为了对一个个体的攻击,大大增加了攻击代价。

Text Only
1
2
3
4
|User| Salt |HashedPasswordWithSalt|
|  1 | S(1) |        SP'(1)        |
|  2 | S(2) |        SP'(2)        |
|  3 | S(3) |        SP'(3)        |

参考

谈谈密码安全:服务端密码保存 - 知乎 (zhihu.com)

评论