28 hashlib模块 -----摘要算法的模块
- 能够把 一个 字符串 数据类型的变量
- 转换成一个 定长的 密文的 字符串,字符串里的每一个字符都是一个十六进制数字对于同一个字符串,不管这个字符串有多长,只要是相同的,无论在任何环境下,
- 多少次执行,在任何语言中使用相同的算法\相同的手段得到的结果永远是相同的只要不是相同的字符串,得到的结果一定不同
有啥用?
可以把账号密码转换城密文 存储到数据库里,就很安全了
例如:
'zhuangdd3714' -> '127649364964908724afd'
字符串 --> 密文
密文还能转化成字符串吗? 不行啊! 不可逆的
1234567 - > '127649364964908724afd'
算法 : 对于同一个字符串,用相同的算法,相同的手段去进行摘要,获得的值总是相同的!
1234567 摘要- > '127649364964908724afd' 用后面这个密文与数据库存储的密文作比较,相同即可
2、可以校验下载的文件是否完整,可用?
下载前的MD5 = 下载后的MD5 即达成一致性
一、md5
md5是一个算法,32位的字符串,每个字符都是一个十六进制
md5算法 效率快 算法相对简单
update
hexdigest
s1 = 'zhuangdd3714' # aee949757a2e698417463d47acac93df md5_obj = hashlib.md5() md5_obj.update(s1.encode('utf-8')) # 必须传入Bytes 作为参数 b'参数' res = md5_obj.hexdigest() # 获得摘要结果 print(res, len(res), type(res)) # aee949757a2e698417463d47acac93df 32 <class 'str'>
二、sha1
sha1也是一个算法,转换为40位的字符串,每个字符都是一个十六进制
算法相对复杂 计算速度也慢(用的人少,相对安全?)
把上面的md5 换成sha1就行
s1 = 'zhuangdd3714' md5_obj = hashlib.sha1() md5_obj.update(s1.encode('utf-8')) res = md5_obj.hexdigest() print(res,len(res),type(res)) __________________ a8eabf4a67b6c37941186b8fd1000eb6b92d3147 40 <class 'str'>
三、安全性
撞库
大白话讲就是创建一个海量数据库,创建一些常用的密码,用同样的算法,例如用的比较多的md5摘要这些密码,然后把生成的密文与要破解的账号密码数据库
做比较分析,从而达到破解密码的奇效。
所以仅仅用密文模块来加密远远不够呀,那怎么办呢?
加盐!
也就是在实例化对象的时候,我们传入盐这个参数
加盐!
s1 = 'zhuangdd3714' md5_obj1 = hashlib.md5('任意的字符串作为盐'.encode('utf-8')) md5_obj1.update(s1.encode('utf-8')) res = md5_obj1.hexdigest() print(res,len(res),type(res)) #结果是437c55d3563c457dcb0215b348561cd2 32 <class 'str'>
不加盐
md5_obj = hashlib.md5() md5_obj.update(s1.encode('utf-8')) res = md5_obj.hexdigest() print(res,len(res),type(res)) # 33b2ce1064ab66aa329715a825dd0b7f 32 <class 'str'>
两者结果是不同的!这样安全性提高 了~ 但是还是不够的呀
固定的盐,还是会被破解的,只要数量达到一定规模,还是会被分析出来
那怎么办?
动态加盐!
username = input('username : ') passwd = input('password : ') md5obj = hashlib.md5(username.encode('utf-8')) md5obj.update(passwd.encode('utf-8')) print(md5obj.hexdigest()) # ee838c58e5bb3c9e687065edd0ec454f
是的,这里用了用户账号名来当作盐,由于每个用户的账号名都是不同的! 所以这里安全性大大提高了!
四、文件的一致性校验
md5_obj = hashlib.md5() with open('5.序列化模块_shelve.py','rb') as f: md5_obj.update(f.read()) ret1 = md5_obj.hexdigest() md5_obj = hashlib.md5() # 这里注意要再实例化一次 with open('5.序列化模块_shelve.py.bak','rb') as f: md5_obj.update(f.read()) ret2 = md5_obj.hexdigest() print(ret1,ret2) =================== 最后ret1 ==ret2 证明两个文件内同一致
大文件的校验
假如文件10G 你的内存只有4G 所以无法一次性update 摘要
所以考虑拆开摘要
例如:
md5_obj = hashlib.md5() md5_obj.update('hello,world'.encode('utf-8')) print(md5_obj.hexdigest()) md5_obj = hashlib.md5() md5_obj.update('hello,'.encode('utf-8')) md5_obj.update('world'.encode('utf-8')) print(md5_obj.hexdigest()) ================ 结果一致
所以大文件的已执行校验:
md5_obj = hashlib.md5() with open('5.序列化模块_shelve.py.bak','rb') as f: md5_obj.update(f.read()) # 循环 循环的读取文件内容 # 循环的来update print(md5_obj.hexdigest())
小试牛刀?
写成一个函数 参数 : 文件1的路径,文件2的路径,默认参数 = 1024000 计算这两个文件的md5值 返回它们的一致性结果 T/F