一、模块简介
Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。
什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。
摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。
我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:
1 import hashlib #导入模块 2 3 md5 = hashlib.md5() #拿到一个操作句柄 4 md5.update(b'fuyong') #获取一个二进制格式的字符串 5 ret = md5.hexdigest() #对字符串进行摘要(加密) 6 print(ret)
如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的:
1 import hashlib 2 3 md5 = hashlib.md5() 4 md5.update(b'fu') 5 md5.update(b'yong') 6 ret = md5.hexdigest() 7 print(ret)
二、摘要算法应用
1、密码加密
1 import hashlib 2 3 #注册 4 username = input('请输入您的账号:') 5 password = input('请输入您的密码:') 6 7 md5 = hashlib.md5() 8 md5.update(bytes(password,encoding='utf-8')) 9 password_md5 = md5.hexdigest() 10 with open('db.txt','w') as f: 11 f.write('%s|%s'%(username,password_md5)) 12 13 #登录 14 username = input('请输入您的账号:') 15 password = input('请输入您的密码:') 16 17 with open('db.txt') as f2: 18 for line in f2: 19 usr,pwd = line.split('|') 20 21 md5 = hashlib.md5() 22 md5.update(bytes(password,encoding='utf-8')) 23 pwd_md5 = md5.hexdigest() 24 25 print(usr,pwd_md5) 26 print(username,pwd) 27 if username == usr and pwd == pwd_md5: 28 print('登录成功!') 29 else:print('用户名或密码错误')
2、读取一个文件内容,并且摘要
db文件内容
加密后的内容如下:
摘要后的文件
三、为算法加盐
考虑这么个情况,很多用户喜欢用123456,888888,password这些简单的口令,于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表:
'e10adc3949ba59abbe56e057f20f883e': '123456' '21218cca77804d2ba1922c33e0151105': '888888' '5f4dcc3b5aa765d61d8327deb882cf99': 'password'
这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。
对于用户来讲,当然不要使用过于简单的口令。但是,我们能否在程序设计上对简单口令加强保护呢?
由于常用口令的MD5值很容易被计算出来,所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:
hashlib.md5("salt".encode("utf8"))
经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。
1 import hashlib 2 3 md5 = hashlib.md5('加盐的字符串写在这里,要进行编码'.encode('utf-8')) 4 md5.update(b'fuyong'+bytes('可以在这里再次进行加密,加的字不一样,结果就不一样',encoding='utf-8')) 5 ret = md5.hexdigest() 6 print(ret)