hashlib提供了常用的摘要算法如MD5,SHA1等
通俗的理解MD5算法,输入任意长度的数据,输出为固定长度的数据串(数字通常是16进制)
很重要的一点
:哈希算法是一个单向函数,无法反推
常见应用
- 可以判断一段数据是否被篡改
- 用于网站登陆用户口令的存储
判断数据是否被篡改
比如有这样一句话:中国是一个伟大的国家,中华民族是一个伟大的民族
通过计算哈希值判断文章是否被改变:
注:
1.调用update
函数的时候传入的值必须是编码过的,不能传Unicode字符
2.字符可以拆分多次update
,结果是一样的
import hashlib
str1 = "中国是一个伟大的国家,中华民族是一个伟大的民族"
md5 = hashlib.md5()
md5.update(str1.encode("utf-8")) # 注意这里必须要编码,否则报错
print(md5.hexdigest())
>>a08a193575c827d17da02bacd4bb3279
验证update分开调用
md5 = hashlib.md5()
md5.update(str1.encode("utf-8")[0:10])
md5.update(str1.encode("utf-8")[10:])
print(md5.hexdigest())
>>a08a193575c827d17da02bacd4bb3279
下面将字符串改变一个字符,看哈希值是否还相等,这里加一个小数点
import hashlib
str1 = "中国是一个伟大的国家,中华民族是一个伟大的民族."
md5 = hashlib.md5()
md5.update(str1.encode("utf-8"))
print(md5.hexdigest())
>>08a26a6692382b2dc581dfc294ee4054
可以看到上面的哈希值已经变化.所以我们可以通过计算哈希值来判断我们的数据是否发生了改变
用于用户登陆口令存储
对于用户来说一般登陆网站或者应用都是有登陆账号和密码的.我们一般的做法都是会将这些口令数据映射起来存储到数据库中,比如mysql:
+------+--------+
|user |password|
+------+--------+
|z3 | 1234 |
|l4 | 5678 |
|w5 | 2345 |
+------+--------+
这样做有一个问题,那就是运维人员以及数据库管理人员或者数据库遭到泄露,那么其他人就可以知道所有用户的账号密码,这是非常不安全的.那么我们可以怎么做呢,那就是用户名不变,给密码使用hash
算法加密,用户登陆依然使用正常的密码,我们的程序拿到密码后进行哈希运算比较哈希值来判断用户是否输入密码正确.又因为md5
算法是单向的,不能反推,所以就算数据泄露别人知道了哈希值也是反推不出来用户的输入密码的,这样就保证了安全性的前提,又不影响用户登陆.
+------+--------+
|user |password|
+------+--------+
|z3 | 81dc9bdb52d04dc20036dbd8313ed055|
|l4 | 674f3c2c1a8a6f90461e8a66fb5550ba|
|w5 | 81b073de9370ea873f548e31b8adc081|
+------+--------+
上面这样做看似没问题,其实还有一个问题:
有些用户太懒了,使用手机号或123456或生肖作为密码
这样出现什么问题呢,一些人闲着没事干,想出来了很多的常见密码进行哈希运算,这样就得到了一大批的哈希值,然后将数据库的哈希值进行匹配(暴力破解),这样也是能推出一部分用户的账号密码的,那这样怎么解决呢?
加盐(很多框架也是这么干的)
在程序中设置一个盐值(一般是base64随机生成的字符,连开发者自己都记不住的字符串)
,程序拿到用户输入密码之后拼接上这个盐值再进行哈希运算,用户的密码就会很复杂,那些闲着没事干的人只要拿不到盐值
基本就很难推演数据库里面存储的哈希结果.实现用户登陆口令存储
代码:
import hashlib
import os
password = "123456".encode("utf-8")
salt = os.urandom(32)
print(salt)
>>b'h\x02b$\xff\xea\xe7\xed\x88\xe4\xff\x8a\x11 \xf4US\xec\xb1\xc3S\xb5H[\x94\x0f\x85\x0b\xc5\x91\xd7 '
md5 = hashlib.md5()
md5.update(password+salt)
print(md5.hexdigest())
>>e118ac543e51c96e96dd9ce5202bcab1
如果想要存储唯一的哈希值(不同用户相同的密码会生成相同的哈希值),可以再哈希运算的时候将用户名也作为条件放进去哈希运算.只是要注意哈希运算输入的bytes类型
网友评论