- python的hashlib提供了常见的摘要算法如MD5,SHA1等。
- 摘要算法又称哈希算法、散列算法。 它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)
- 摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest。目的是为了发现原始数据是否被篡改过。
- 摘要算法之所以能指出数据是否被篡改过,是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。 而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。
- 例1. 以常用的摘要算法MD5为例,计算一个字符串的MD5
-
import hashlib md5 = hashlib.md5() md5.update('hewuxin is a very good student'.encode('utf-8')) print(md2.hexdigest()) #如果数据量很大,可以分开来写 md5 = hashlib.md5() md5.update('hewuxin is a very'.encode('utf-8')) md5.update('good student'.encode('utf-8')) print(md2.hexdigest()) #输出结果为 7888d1fd0f3a4d6f929431076606139b
- 如果改动一个字符,计算结果就会完全不同。
- MD5是最常见的摘要算法,速度很快,生成结果为固定的128bit字节 ,通常用一个32为的16进制字符串表示。
- 另外一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似:
-
import hashlib sha1 = hashlib.sha1() sha1.update('hewuxin is a good student'.encode('utf-8')) print(sha1.hexdigest()) #输出结果为 4be67298fdde24e05c325bf2f99fe68f630ab656
同样如果数据量很大,可以分开来写
- SHA1的结果是160bit字节,通常用一个40为的16进制字符串表示
- 比SHA1更安全的算法是SHA256和SHA512,但是越安全的算法越慢,而且摘要长度更长。由于
- 因为任何摘要算法都是把无限多的数据集合映射到一个有限的集合中,所以完全有可能出现两个不同的数据通过某个摘要算法得到相同的摘要结果 ,这种情况成为碰撞。 出现碰撞的几率非常非常小。
- 摘要算法应用 有 允许用户登录的网站中用户密码的加密
- 当用户登录时,首先计算用户输入的明文口令的MD5,然后和存储在数据库中的MD5对比,如果一致,则登录成功。
- 设计一个验证用户登录的函数,根据用户输入的口令是否正确,返回True或False
-
import hashlib UserDict = { 'hewuxin': '319622121d9ae418930f9f581b886ac5', 'wuxin':'d0518e9c0c8c8cbae2b1220df62c8674' } def login(username,password): pw = hashlib.md5() pw.update(password.encode('utf-8')) return pw.hexdigest() == UserDict[username] login('hewuxin,'123618') #输出结果为: True
- 其实采用MD5存储口令也不安全 ,因为可以使用存储MD5口令的数据库反推出明文口令。
- 要确保存储的口令不被反推出来可以使用对原始口令追加一个复杂字符串来实现,俗称”加盐“
-
import hashlib,random ud = {} def get_md5(s): # return s的md5编码 return hashlib.md5(s.encode("utf-8")).hexdigest() class User(object): #定义User类 def __init__(self, username, password): #初始化 self.username = username self.salt = ''.join([chr(random.randint(48,122)) for i in range(10)]) #随机生成salt:循环20次每次在(48,122)之间取随机数转换为字符 self.password = get_md5(password + self.salt) #生成加盐后的md5 password ud = { 'bob': User('bob', 'abc999'), 'alice': User('wuxin', 'alice2008'), 'heyuyang': User('hewuxin', '123618') } def login(username,password): user = ud[username] return user.password == get_md5(password + user.salt) print(login('hewuxin','123618')) #返回结果 True
摘要算法在很多地方都有广泛的应用。要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令.