1、概述
从关于hash(一):基本概念一文可知,hash过程虽然不可逆,但却可以使用查表法、暴力破解等方式从hash值中恢复出原始数据,所以如果仅仅是使用hash算法对明文进行处理得到hash值,并将hash值作为密码的行为是及其不安全的,为了从一定程度上降低受到攻击的风险,安全专家们发明了一种“加盐(salting)”的技术。
在密码学中,盐(salt)是在散列之前往待散列内容中加入的随机字符串,往待散列前的内容中加入字符串的过程称为“加盐”。
注意:
还需要注意的是用来保护密码的hash函数跟数据结构课上见过的hash函数不完全一样。比如实现hash表的hash函数设计的目的是快速,但是不够安全。只有加密hash函数(cryptographic hash functions)可以用来进行密码的hash。这样的函数有SHA256, SHA512, RipeMD, WHIRLPOOL等。
2、为什么加盐会降级密码被破解的风险
看下表中的例子,在第一行中,字符串yschlj在不加盐时通过MD5散列后的hash值为9ef955becb90f111522b599b91393118,通过查表、暴力破解等方式是可以找到该hash值对应的原始内容的,在第二行中,字符串yschlj与盐wka拼接后的再通过MD5散列后的hash值为53dc0f081b142eec156aa32ff568c2ba,此时如果此hash值泄露的话,我们假设依然可以从该hash值中恢复出原始字符串,但是由于此时salt也参杂在原始字符串中,在不知道salt的情况下,也不容易猜出哪些字符是原文密码哪些是salt,从这个角度来看加盐会降低密码被破解的风险。
原始数值 | salt | 32位的MD5值 |
yschlj | 不加盐 | 9ef955becb90f111522b599b91393118 |
yschlj | wka | 53dc0f081b142eec156aa32ff568c2ba |
3、加盐时常犯的错误
盐值重复、盐值过短、用户名作为盐值、组合使用哈希函数或两次使用哈希。
盐值重复
切忌不可为所有账号使用同一个盐值,正确做法是用户创建账号或每次修改密码时,都应该重新生成新的盐值进行加密。
盐值过短
如果盐值过短,攻击者们依然可以构造出一个包含所有可能的盐值的表,推荐盐值的长度应与哈希函数输出的值长度相等,比如SHA256算法的输出是32个字节,那么盐值长度至少也应该是32个随机字节。
用户名作为盐值
不推荐把盐值作为盐值使用。
组合使用哈希函数或两次使用哈希
组合使用哈希函数也是不推荐的做法,不要发明自己的加密方法,使用已经设计好的标准算法是可取的。常用的一些组合哈希函数有(都不推荐使用):
sha1(str_rot13(password + salt))
md5(sha1(password))
sha1(sha1(password))
md5(sha1(md5(md5(password) + sha1(password)) + md5(password)))
md5(md5(salt) + md5(password))