盐(Salt)

在密码学中,是指通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这种过程称之为“加盐”。(看不懂没关系,接着往下看)

第一代密码

早期的软件系统或者互联网应用,数据库中设计用户表的时候,大致是这样的结构:

mysql> desc User;

+----------+--------------+------+-----+---------+-------+

| Field | Type | Null | Key | Default | Extra |

+----------+--------------+------+-----+---------+-------+

| UserName | varchar(50) | NO | | | |

| PassWord | varchar(150) | NO | | | |

+----------+--------------+------+-----+---------+-------+

数据存储形式如下:

mysql> select * from User;

+----------+----------+

| UserName | PassWord |

+----------+----------+

| lichao | 123 |

| akasuna | 456 |

+----------+----------+

主要的关键字段就是这么两个,一个是登陆时的用户名,对应的一个密码,而且那个时候的用户名是明文存储的,如果你登陆时用户名是 123,那么数据库里存的就是 123。这种设计思路非常简单,但是缺陷也非常明显,数据库一旦泄露,那么所有用户名和密码都会泄露,后果非常严重。参见《CSDN 详解 600 万用户密码泄露始末》。 

第二代密码

为了规避第一代密码设计的缺陷,聪明的人在数据库中不在存储明文密码,转而存储加密后的密码,典型的加密算法是 MD5 和 SHA1,其数据表大致是这样设计的:

mysql> desc User;

+----------+--------------+------+-----+---------+-------+

| Field | Type | Null | Key | Default | Extra |

+----------+--------------+------+-----+---------+-------+

| UserName | varchar(50) | NO | | | |

| PwdHash | char(32) | NO | | | |

+----------+--------------+------+-----+---------+-------+

数据存储形式如下:

mysql> select * from User;

+----------+----------------------------------+

| UserName | PwdHash |

+----------+----------------------------------+

| lichao | 202cb962ac59075b964b07152d234b70 |

| akasuna | 250cf8b51c773f3f8dc8b4be867a9a02 |

+----------+----------------------------------+

假如你设置的密码是 123,那么数据库中存储的就是 202cb962ac59075b964b07152d234b70 或 40bd001563085fc35165329ea1ff5c5ecbdbbeef。当用户登陆的时候,会把用户输入的密码执行 MD5(或者 SHA1)后再和数据库就行对比,判断用户身份是否合法,这种加密算法称为散列。

严格地说,这种算法不能算是加密,因为理论上来说,它不能被解密。所以即使数据库丢失了,但是由于数据库里的密码都是密文,根本无法判断用户的原始密码,所以后果也不算太严重。

第三代密码

本来第二代密码设计方法已经很不错了,只要你密码设置得稍微复杂一点,就几乎没有被破解的可能性。但是如果你的密码设置得不够复杂,被破解出来的可能性还是比较大的。

好事者收集常用的密码,然后对他们执行 MD5 或者 SHA1,然后做成一个数据量非常庞大的数据字典,然后对泄露的数据库中的密码就行对比,如果你的原始密码很不幸的被包含在这个数据字典中,那么花不了多长时间就能把你的原始密码匹配出来。这个数据字典很容易收集,CSDN 泄露的那 600w 个密码,就是很好的原始素材。

于是,第三代密码设计方法诞生,用户表中多了一个字段:

mysql> desc User;

+----------+-------------+------+-----+---------+-------+

| Field | Type | Null | Key | Default | Extra |

+----------+-------------+------+-----+---------+-------+

| UserName | varchar(50) | NO | | | |

| Salt | char(50) | NO | | | |

| PwdHash | char(32) | NO | | | |

+----------+-------------+------+-----+---------+-------+

数据存储形式如下:

mysql> select * from User;

+----------+----------------------------+----------------------------------+

| UserName | Salt | PwdHash |

+----------+----------------------------+----------------------------------+

| lichao | 1ck12b13k1jmjxrg1h0129h2lj | 6c22ef52be70e11b6f3bcf0f672c96ce |

| akasuna | 1h029kh2lj11jmjxrg13k1c12b | 7128f587d88d6686974d6ef57c193628 |

+----------+----------------------------+----------------------------------+

Salt 可以是任意字母、数字、或是字母或数字的组合,但必须是随机产生的,每个用户的 Salt 都不一样,用户注册的时候,数据库中存入的不是明文密码,也不是简单的对明文密码进行散列,而是 MD5( 明文密码 + Salt),也就是说:

MD5('123' + '1ck12b13k1jmjxrg1h0129h2lj') = '6c22ef52be70e11b6f3bcf0f672c96ce'

MD5('456' + '1h029kh2lj11jmjxrg13k1c12b') = '7128f587d88d6686974d6ef57c193628'

 

“盐值”是一组随机的字符串,被称为Salt,由系统随机生成。Salt可以插在最前面、最后面,也可以插在中间,可分开插入也可倒序。

 

用户注册时:

用户在网站注册时提供ID与密码;系统为用户分配盐值;盐值插入密码后进行HASH;将ID,HASH值与盐值一起存入数据库。

身份验证时:

用户提供ID与密码;系统在数据库中通过用户提供的ID查找HASH值与盐值;将盐值插入用户提供的密码后进行HASH;将HASH值与数据库中的HASH值比较,相等则验证成功,反之则验证失败。

 

推荐链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: