哈希算法
基本概念:哈希算法是把一个无限的输入集合映射到一个有限的输出集合(散列值)
哈希算法最重要的特点就是:
相同的输入一定得到相同的输出;
不同的输入大概率得到不同的输出。
哈希算法的目的:
就是为了验证原始数据是否被篡改。(哈希碰撞)
哈希碰撞
哈希碰撞是指,两个不同的输入得到了相同的输出:
哈希算法是把一个无限的输入集合映射到一个有限的输出集合,必然会产生碰撞。哈希碰撞肯定是概率发生的,所以衡量一个哈希算法是否优秀与安全,就是这个碰撞概率,所以这个碰撞概率越低越优秀。
你可以定义自己的哈希算法:
coding:utf-8
自定义哈希函数
def my_hash(x):
return (x % 7) ^ 9
print(my_hash(1))
print(my_hash(2))
print(my_hash(3))
print(my_hash(4))
但是你会发现你定义的这个简单哈希规律性很强,如果我很容易碰撞且很容易猜测属出,所以衡量一个哈希算法是否优秀与安全要满足:
1、发生碰撞概率底
2、不容易推断输出结果
常用的哈希算法:
算法 输出长度(位) 输出长度(字节)
MD5 128 bits 16 bytes
SHA-1 160 bits 20 bytes
RipeMD-160 160 bits 20 bytes
SHA-256 256 bits 32 bytes
SHA-512 512 bits 64 bytes
Python 3内置hash()函数
在运行hash()函数时你会发现了一个现象:相同字符串在同一次运行时的哈希值是相同的,但是不同次运行的哈希值不同。这是由于Python的字符串hash算法有一个启动时随机生成secret prefix/suffix的机制,存在随机化现象:对同一个字符串输入,不同解释器进程得到的hash结果可能不同。因此当需要做可重现可跨进程保持一致性的hash,需要用到hashlib模块
hashlib提供了常见的摘要算法,如MD5,SHA1
哈希算法的用途
因为相同的输入永远会得到相同的输出的性质,一般有如下用途
1、验证输入是否被篡改。
2、存储用户口令(注意防止彩虹表攻击。)
比如你在下载一个软件:
你会看到显示的哈希,这个就可以用做比对你下载的软件是否被串改,你可以用官网提示的算法,在本地计算下然后与之比对。
哈希算法的另一个重要用途是存储用户口令。如果直接将用户的原始口令存放到数据库中,会产生极大的安全风险:
数据库管理员能够看到用户明文口令;
数据库数据一旦泄漏,黑客即可获取用户明文口令。
比如Django的session表内容。
彩虹表攻击
彩虹表,什么是彩虹表?
因为相同的输入永远会得到相同的输出的性质,所以在我们猜到hash算法后我可以提前计算常用口令的hash,然后建立一一对应的表,然后用hash值反推常用的口令。
常用口令 MD5
hello123 f30aa7a662c728b7407c54ae6bfd27d1
12345678 25d55ad283aa400af464c76d713c07ad
passw0rd bed128365216c019988915ed3add75fb
19700101 570da6d5277a646f6552b8832012f5dc
… …
20201231 6879c0ae9117b50074ce0a0d4c843060
这个表就是彩虹表,所以不要用生日作为密码。
如何防止呢?就是加盐,比如你设置coke和session值时额外添加一个随机数,这样就能达到无法反推的目的。