Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。
什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。
摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。
我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:
能够把 一个 字符串 数据类型的变量转换成一个 定长的 密文的 字符串,
字符串里的每一个字符都是一个十六进制数字
对于同一个字符串,不管这个字符串有多长,只要是相同的,无论在任何环境下,多少次执行,在任何语言中
使用相同的算法相同的手段得到的结果永远是相同的只要不是相同的字符串,得到的结果一定不同
字符串 --> 密文
密文 不可逆的 字符串
md5是一个算法,32位的字符串,每个字符都是一个十六进制
md5算法 效率快 算法相对简单
s="asdf1234" import hashlib md5_obj = hashlib.md5() md5_obj.update(s.encode('utf-8')) res = md5_obj.hexdigest() print(res,len(res),type(res)) 结果:1adbb3178591fd5bb0c248518f39bf6d 32 <class 'str'>
sha1也是一个算法,40位的字符串,每个字符都是一个十六进制
算法相对复杂 计算速度也慢
s="asdf1234" import hashlib sha1_obj = hashlib.sha1() sha1_obj.update(s.encode('utf-8')) res = sha1_obj.hexdigest() print(res,len(res),type(res)) 结果:f58cf5e7e10f195e21b553096d092c763ed18b0e 40 <class 'str'>
# 数据库 - 撞库 # 考虑这么个情况,很多用户喜欢用123456,888888,password这些简单的口令, # 于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表: # 'e10adc3949ba59abbe56e057f20f883e': '123456' # '21218cca77804d2ba1922c33e0151105': '888888' # '5f4dcc3b5aa765d61d8327deb882cf99': 'password'
这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。
对于用户来讲,当然不要使用过于简单的口令。但是,我们能否在程序设计上对简单口令加强保护呢?
由于常用口令的MD5值很容易被计算出来,所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:
hashlib.md5("salt".encode("utf8"))
s="asdf1234" import hashlib md5_obj = hashlib.md5('任意的字符串作为盐'.encode('utf-8')) md5_obj.update(s.encode('utf-8')) res = md5_obj.hexdigest() print(res,len(res),type(res))
动态加盐
import hashlib username = input('username : ') passwd = input('password : ') md5obj = hashlib.md5(username.encode('utf-8')) md5obj.update(passwd.encode('utf-8')) print(md5obj.hexdigest())
文件的一致性校验
import hashlib md5_obj = hashlib.md5() with open('wenjian.py','rb') as f: md5_obj.update(f.read()) ret1 = md5_obj.hexdigest() import hashlib md5_obj = hashlib.md5() with open('wenjian.py.bak','rb') as f: md5_obj.update(f.read()) ret2 = md5_obj.hexdigest() print(ret1,ret2)
如果这个文件特别大,内存装不下
import hashlib md5_obj = hashlib.md5() md5_obj.update('hello,world,hello'.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')) md5_obj.update('hello'.encode('utf-8')) print(md5_obj.hexdigest()) 结果: 4f7e626316260c1c72f310509bf7cdae 4f7e626316260c1c72f310509bf7cdae