Python hashlib and hmac
hashlib
hashlib提供了常用的摘要算法:MD5, SHA1等等
摘要算法:也成哈希算法,散列算法。通过一个函数把任意长度的数据转换成一个长度固定的数据串。主要用在存储一些不能被修改和查看的数据。
如用户名和密码存储在数据库中,但是不能明文存储,通过摘要算法转换成一串数据,安全性比明文存储要好。
算法MD5:hashlib.md5(Bytes)
常用的摘要算法MD5, 输入的参数是Bytes类型,生成结果是固定的128bit, 通常用一个32位的16进制字符串表示
计算一个字符串的MD5值,传入string类型的参数
import hashlib
和直接传入Bytes参数效果一样
如果数据量很大,可以多次调用md5.update(), 效果一样
但是一定要注意,多次调用的时候,字符串分隔后中间的符号一定要保留,否则结果将会不一样,
如下面的例子中, ‘a’后面少了一个空格,结果相当于‘this is apassword’ 而不是‘this is a password’:
算法SHA1:hashlib.sha1(bytes),用法和MD5相同,生成160bit字节,通常用40位的16进制字符串表示
Hmac
Hmac算法:Keyed-Hashing for Message Authentication。通过一个标准算法,在计算哈希的过程中,把key混入计算过程中
hmac.new(key, message, digestmod='MD5')
key 和message都必须是Bytes类型
下面是分别用hashlib 和 hmac实现的密码验证:
用hashlib实现:
# _*_ coding:utf-8_*_
import hashlib, random
def get_md5(s):
return hashlib.md5(s.encode('utf-8')).hexdigest()
class User(object):
def __init__(self, username, password):
self.username = username
self.salt = ''.join([chr(random.randint(48, 122)) for i in range(20)])
self.password = get_md5(password + self.salt)
db = {
'michael': User('michael', '123456'),
'bob': User('bob', 'abc999'),
'alice': User('alice', 'alice2008')
}
def login(username, password):
user = db[username]
return user.password == get_md5(password + user.salt)
# user.password 里传入的参数是db里的password
# ==后面的get_md5里的password是用的login这里传入的password
# 测试:
assert login('michael', '123456')
assert login('bob', 'abc999')
assert login('alice', 'alice2008')
assert not login('michael', '1234567')
assert not login('bob', '123456')
assert not login('alice', 'Alice2008')
print('ok')
用hmac实现
# _*_ coding:utf-8 _*_
import hmac, random
def get_md5(key, s):
return hmac.new(key.encode('utf-8'), s.encode('utf-8'), 'MD5').hexdigest()
class User(object):
def __init__(self, username, password):
self.username = username
self.key = ''.join([chr(random.randint(48, 122)) for i in range(20)])
self.password = get_md5(self.key, password)
db = {
'michael': User('michael', '123456'),
'bob': User('bob', 'abc999'),
'alice': User('alice', 'alice2008')
}
def login(username, password):
user = db[username]
return user.password == get_md5(user.key, password)
# 测试:
assert login('michael', '123456')
assert login('bob', 'abc999')
assert login('alice', 'alice2008')
assert not login('michael', '1234567')
assert not login('bob', '123456')
assert not login('alice', 'Alice2008')
print('ok')