专栏首页用户2442861的专栏为什么要在MD5加密的密码中加“盐”

为什么要在MD5加密的密码中加“盐”

原文地址:http://www.xttblog.com/?p=986

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

以上这句话是维基百科上对于 Salt 的定义,但是仅凭这句话还是很难理解什么叫 Salt,以及它究竟起到什么作用。

第一代密码

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

1 2 3 4 5 6 7

mysql> desc User; +----------+--------------+------+-----+---------+-------+ | Field    | Type         | Null | Key | Default | Extra | +----------+--------------+------+-----+---------+-------+ | UserName | varchar(50)  | NO   |     |         |       | | PassWord | varchar(150) | NO   |     |         |       | +----------+--------------+------+-----+---------+-------+

数据存储形式如下:

1 2 3 4 5 6 7

mysql> select * from User; +----------+----------+ | UserName | PassWord | +----------+----------+ | lichao   | 123      | | akasuna  | 456      | +----------+----------+

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

第二代密码

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

1 2 3 4 5 6 7

mysql> desc User; +----------+--------------+------+-----+---------+-------+ | Field    | Type         | Null | Key | Default | Extra | +----------+--------------+------+-----+---------+-------+ | UserName | varchar(50)  | NO   |     |         |       | | PwdHash  | char(32)     | NO   |     |         |       | +----------+--------------+------+-----+---------+-------+

数据存储形式如下:

1 2 3 4 5 6 7

mysql> select * from User; +----------+----------------------------------+ | UserName | PwdHash                          | +----------+----------------------------------+ | lichao   | 202cb962ac59075b964b07152d234b70 | | akasuna  | 250cf8b51c773f3f8dc8b4be867a9a02 | +----------+----------------------------------+

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

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

第三代密码

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

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

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

1 2 3 4 5 6 7 8

mysql> desc User; +----------+-------------+------+-----+---------+-------+ | Field    | Type        | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+-------+ | UserName | varchar(50) | NO   |     |         |       | | Salt     | char(50)    | NO   |     |         |       | | PwdHash  | char(32)    | NO   |     |         |       | +----------+-------------+------+-----+---------+-------+

数据存储形式如下:

1 2 3 4 5 6 7

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 之后的散列,坏人们的数据字典已经无法直接匹配,明文密码被破解出来的概率也大大降低。

是不是加了 Salt 之后就绝对安全了呢?淡然没有!坏人们还是可以他们数据字典中的密码,加上我们泄露数据库中的 Salt,然后散列,然后再匹配。但是由于我们的 Salt 是随机产生的,假如我们的用户数据表中有 30w 条数据,数据字典中有 600w 条数据,坏人们如果想要完全覆盖的坏,他们加上 Salt 后再散列的数据字典数据量就应该是 300000* 6000000 = 1800000000000,一万八千亿啊,干坏事的成本太高了吧。但是如果只是想破解某个用户的密码的话,只需为这 600w 条数据加上 Salt,然后散列匹配。可见 Salt 虽然大大提高了安全系数,但也并非绝对安全。

实际项目中,Salt 不一定要加在最前面或最后面,也可以插在中间嘛,也可以分开插入,也可以倒序,程序设计时可以灵活调整,都可以使破解的难度指数级增长。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 系统的环境变量path的作用是什么

     http://blog.csdn.net/libo2006/article/details/1531545

    bear_fish
  • java数据库操作 (附带数据库连接池的代码)

    本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188

    bear_fish
  • caffe源码分析-DataReader

    DataReader作为DataLayer的数据成员变量,以多线程的方式从数据库(如lmdb, hdf5)读取数据:

    bear_fish
  • XLNet训练成本6万美元,顶5个BERT,大模型「身价」惊人

    数据、算法和计算力是推动人工智能发展的三大要素。随着高性能 GPU、TPU 的出现,人们似乎正在将算力的利用推向极致。

    机器之心
  • Java学习笔记第一篇:坦克大战游戏

    一、Java学习笔记系列 笔者大学时候学的编程语言是C和汇编,毕业以后并未从事过开发工作,也没有接触过Java。但近两年的PaaS、CI/CD主要是以Java应...

    魏新宇
  • Kaggle竞赛硬件如何选择?不差钱、追求速度,那就上TPU吧

    图 1:在 Kaggle Notebook 中可以免费使用 CPU、GPU 和 TPU。

    机器之心
  • 如何薅羊毛 | PyTorch终于能用上谷歌云TPU,推理性能提升4倍

    现在PyTorch官方已经在Github上给出示例代码,教你如何免费使用谷歌云TPU训练模型,然后在Colab中进行推理。

    昱良
  • 【深度】基于论文,对谷歌 TPU 的最全分析和专业评价

    【新智元导读】本文以 Google 最新公开的 TPU 论文《在数据中心中对张量处理器进行性能分析》的译本为基础,对该论文及 TPU 进行了评价。 源起 2...

    新智元
  • TPU中的指令并行和数据并行

    TPU V1定义了一套自己的指令集,虽然在介绍处理器时,往往会先谈指令集架构,但此处却把它放到了最后,这主要基于两个原因;其一在于个人的对处理器不太了...

    sea-wind
  • 谷歌云TPU服务正式全面开放:「AlphaGo背后的芯片」进入商用化

    机器之心

扫码关注云+社区

领取腾讯云代金券