hashlib模块
Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。
什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
举个例子,你写了一篇文章,内容是一个字符串‘how to use python hashlib - by Michael‘,并附上这篇文章的摘要是‘2d73d4f15c0db7f5ecb321b6a65e5d6d‘。如果有人篡改了你的文章,并发表为‘how to use python hashlib - by Bob‘,你可以一下子指出Bob篡改了你的文章,因为根据‘how to use python hashlib - by Bob‘计算出的摘要不同于原始文章的摘要。
可见,摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。
摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。
下面就是一个加密算法的形式:
import hashlib m = hashlib.md5() m.update(b"Hello") m.update(b"It‘s me") print(m.digest()) m.update(b"It‘s been a long time since last time we ...") print(m.digest()) #2进制格式hash print(len(m.hexdigest())) #16进制格式hash
运行结果如下:
5ddeb47b2f925ad0bf249c52e342728a
fef3d1cb846deb62c96ab4a65a80bc6d
5ddeb47b2f925ad0bf249c52e342728a
b‘[\xa1C\x11\xa1\xb24\x03M\xa0\xe0P=\xdf\x94\xb9‘
32
m.update(b"Hello")和m.update(b"It‘s me")是把两个字符串拼接之后进行加密,等价于对m.update(b"HelloIt‘s me"),就是对内容进行加密的情况,是不能反解。
1. md5加密
import hashlib hash = hashlib.md5() hash.update("admin".encode("utf-8")) print(hash.hexdigest())运行结果如下:21232f297a57a5a743894a0e4a801fc3
2.sha1加密
import hashlib hash = hashlib.sha1() hash.update("admin".encode("utf-8")) print(hash.hexdigest())运行结果如下:d033e22ae348aeb5660fc2140aec35850c4da997
3.sha256加密
import hashlib hash = hashlib.sha256() hash.update("admin".encode("utf-8")) print(hash.hexdigest())运行如下:8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
4.sha384加密
import hashlib hash = hashlib.sha384() hash.update("admin".encode("utf-8")) print(hash.hexdigest())运行结果如下:9ca694a90285c034432c9550421b7b9dbd5c0f4b6673f05f6dbce58052ba20e4248041956ee8c9a2ec9f10290cdc0782
5.sha512加密
import hashlib hash = hashlib.sha512() hash.update("admin".encode("utf-8")) print(hash.hexdigest())运行结果如下:9ca694a90285c034432c9550421b7b9dbd5c0f4b6673f05f6dbce58052ba20e4248041956ee8c9a2ec9f10290cdc0782
6. ‘加盐’加密
以上加密算法虽然很厉害,但仍然存在缺陷,通过撞库可以反解。所以必要对加密算法中添加自定义key再来做加密。
import hashlib
m = hashlib.md5()
m.update("admin".encode("utf-8"))
print(m.hexdigest())
hash = hashlib.md5("python".encode("utf-8"))
hash.update("admin".encode("utf-8"))
print(hash.hexdigest())
运行结果如下:
21232f297a57a5a743894a0e4a801fc3
75b431c498b55557591f834af7856b9f
从上面可以看出,要想增加撞库的难度,可以增加密码的难度。
7. hmac加密
import hmac
m = hmac.new("python".encode(‘utf-8‘))
m.update("admin".encode(‘utf-8‘))
print(m.hexdigest())
运行结果如下:
540f0bf357bfda39ceee96c8e97b2e9e
比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度更长。
有没有可能两个不同的数据通过某个摘要算法得到了相同的摘要?完全有可能,因为任何摘要算法都是把无限多的数据集合映射到一个有限的集合中。这种情况称为碰撞,比如Bob试图根据你的摘要反推出一篇文章‘how to learn hashlib in python - by Bob‘,并且这篇文章的摘要恰好和你的文章完全一致,这种情况也并非不可能出现,但是非常非常困难。
摘要算法应用
摘要算法能应用到什么地方?举个常用例子:
任何允许用户登录的网站都会存储用户登录的用户名和口令。如何存储用户名和口令呢?方法是存到数据库表中:
name | password
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
michael |
123456
bob | abc999
alice | alice2008
如果以明文保存用户口令,如果数据库泄露,所有用户的口令就落入黑客的手里。此外,网站运维人员是可以访问数据库的,也就是能获取到所有用户的口令。
正确的保存口令的方式是不存储用户的明文口令,而是存储用户口令的摘要,比如MD5:
username | password
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
michael | e10adc3949ba59abbe56e057f20f883e
bob |
878ef96e86145580c38c87f0410ad153
alice |
99b1c2188db85afee403b1536010c2c9
当用户登录时,首先计算用户输入的明文口令的MD5,然后和数据库存储的MD5对比,如果一致,说明口令输入正确,如果不一致,口令肯定错误。
小结:
摘要算法在很多地方都有广泛的应用。要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令。
下面下了一个简单的加密登录程序:
import json,hashlib def register(): ‘‘‘用户注册模块,注册之后存储到文件数据库中‘‘‘ name = input("Please input you register‘s name: ") pwd = input("Please input you password:") hash = hashlib.md5() hash.update(pwd.encode("utf-8")) pwd = hash.hexdigest() sex = input("Please input your sex:") age = input("Please input your age:") mail = input("Please input your mail:") address = input("请输入你的地址:") message = {"name":name,"sex":sex,"age":age,"mail":mail,"address":address,"pwd":pwd} with open("user_db.json",‘w‘) as f: json.dump(message,f) def login(): ‘‘‘用户登录验证模块,从上面存储的用户数据库中找数据,也使用加密验证是否正确‘‘‘ while True: m = hashlib.md5() name = input("请输入你的用户名:") m.update(input("请输入你的密码:").encode(‘utf-8‘)) password = m.hexdigest() with open("user_db.json",‘r‘) as f1: user_dic = json.load(f1) if name == user_dic["name"] and password == user_dic["pwd"]: print("欢迎光临,登录成功!") return else: print("您输入的用户名或密码不对,请核对后输入!") login()
运行结果如下:
请输入你的用户名:geng
请输入你的密码:admin
您输入的用户名或密码不对,请核对后输入!
请输入你的用户名:耿长学
请输入你的密码:admin
欢迎光临,登录成功!
其实hashlib存在的意义就是加密,加密是为了防止以明文的方式让别人获取用户信息,所以要通过加密进行保证,即便黑客获取了用户信息,但是由于密码或者关键部分使用加密算法,黑客看到的只是加密之后的信息。由于Md5是不能反解的,只能通过撞库碰运气,因此密码要相对负责一些。