SHA-1(Secure Hash Algorithm 1,安全散列算法1)是一种密码散列函数,SHA-1可以生成一个被称为消息摘要的160比特(20字节)散列值,散列值通常的呈现形式为40个十六进制数。
SHA-1和MD5都是
hash function
,两者实现不同,但现阶段都已经不安全,建议SHA-2系列的算法,包括比
SHA256
、
SHA512
等,不过越安全的算法越慢,而且摘要长度更长,需要根据不同使用场景进行取舍。
python中的实现
由Python内置模块
hashlib
提供,使用
hashlib.sha1()
获得,用法参考之前的
摘要算法的python实现和使用场景
。
安全性更高的加盐处理
尽管
MD5
以及
SHA-1
都是不可逆的算法,但是可能发生碰撞,且
SHA-1
已经不再视为可抵御有充足资金、充足计算资源的攻击者。2005年,密码分析人员发现了对
SHA-1
的有效攻击方法,这表明该算法可能不够安全,不能继续使用。
且在使用的过程中(如密码密文形式存储),也会由于设置的
key
值过于简单,很容易得到对应的md5值(这不是算法的问题,是用户设置的密码数据过于简单的问题,如设置密码为123),此时为了尽可能保证md5值(用户密码)不会轻易破解(黑客使用简单密码对应的md5值去进行匹配),可以通过对key添加一个复杂的字符串来实现,这就是俗称的
“加盐”
:
1 2
|
def calc_md5(password): return get_md5(password + 'the-salt')
|
再假设,如果用户使用了相同的密码,此时MD5的值是一样的,为了保证md5的破解难度,此时还可以使用用户名(假设用户名不能相同)的一部分来作为加盐的值,以此来尽可能保证存储的密文密码破解的可能性。
此外,为了防止黑客通过彩虹表根据哈希值反推原始口令,并增加破解的难度,在计算哈希的时候设置可以设置不同的盐值(如使用用户的用户名),由于每个用户的盐值都不一样,即使破解了一个用户,剩余的用户也需要重新生成彩虹表。
Flask中提供的默认的用户密码密文生成函数
from werkzeug.security import generate_password_hash
使用的就是加盐哈希算法:加密时混入一段“随机”字符串(盐值)再进行哈希(可以对使用的哈希算法通过
method
参数进行指定,默认使用的是
SHA-256
(通常为64个十六进制数表示))。即使密码相同,如果盐值不同,那么哈希值也是不一样的。现在网站开发中主要是运用这种算法。
generate_password_hash
生成的密文:组成部分为:使用哈希算法名(15000表示的是迭代的次数),盐值,SHA-256值,通过$分隔:
1
|
pbkdf2:sha256:150000$2b8nQyP1$d6eb56ab9813aa4300809bea2e6b7a22143969fdae6818ce14cbdd158bd8436e
|
都是不可逆的算法,如果需要进行验证,必须知晓传递的key值,使用key值利用相同的算法重新获得数据去进行比较,此时才能知晓数据是否一致。
Flask和Django中的密文生成方式参考
Flask和Django的密文生成分析
。
摘要算法在很多地方都有广泛的应用,但要注意摘要算法(摘要算法无法保存完整的数据)不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改验证。它的单向计算特性决定了可以在不存储明文密码的情况下验证用户密码。
为什么选用摘要算法作为密文的生成方式
1.单向性,即使看到了存储的密文密码,也无法获取原始密码(单向性不可逆),虽然MD、SHA256都已经不再安全,但是在进行摘要算法之前,对原始数据进行加盐操作,此时就可以获取安全性较高的密码系统。
2.不使用安全性更高的对称加密或者非对称加密算法的原因是,还需要额外保存密钥,一旦密钥泄露,信息将会暴露。
3.信息摘要算法存储的是密码的信息摘要,无法获取用户完成的密码信息。Flask以及Django都是使用的加盐哈希算法来完成密码密文的保存(哈希算法使用的是SHA-256),即使Flask以及Django都无法知道用户原始密码。验证过程,也是重新执行了一遍加盐哈希算法,将得到的定长字符和保存的密文进行比较,从而判断密码是否相同。