标准库笔记 - 加密:hmac
hmac 密码消息签名与验证
消息签名(默认是md5)
import hmac
h = hmac.new(b'a-key')
with open('test.txt', 'rb') as fr:
while True:
block = fr.read(1024)
if not block:
break
h.update(block)
digest = h.hexdigest()
print(digest)
输出: 00541c98e881f71cf431c304bb19719d
text.txt的内容只有一行: hello world.
。实际上,如果内容短小,可以这样:
h2 = hmac.new(b'a-key', b'hello world.\n')
print(h2.hexdigest())
输出是一样的: 00541c98e881f71cf431c304bb19719d
SHA1
人们说,SHA1算法更健壮,比MD5好。我不知道,总之用SHA1就是。
h3 = hmac.new(b'a-key', b'hello world.\n', 'sha1')
print(h3.hexdigest())
输出是长一些: 85207b857b8a731d9640b8b3fbc2725277d09dea
base64编码
import base64
import hmac
import hashlib
with open('test.txt', 'rb') as fr:
body = fr.read()
hash1 = hmac.new(b'a-key', body, hashlib.sha1)
digest = hash1.digest()
print(base64.encodebytes(digest))
print(base64.b64encode(digest)) # 比上面少了个换行符 '\n'`
输出:
b'hSB7hXuKcx2WQLiz+8JyUnfQneo=\n'
b'hSB7hXuKcx2WQLiz+8JyUnfQneo='
书中一个复杂的例子(可略过)
这个例子提到io缓冲、腌制什么的,感觉很难,实际看一遍,也还看得懂。
import hashlib
import hmac
import io
import pickle
def make_digest(message):
h = hmac.new(
b'secret-shared-key-goes-here',
message,
hashlib.sha1,
)
return h.hexdigest().encode('utf-8')
# 一个简单的类
class SimpleObject:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
# 创建一个BytesIO缓冲区
out_s = io.BytesIO()
# 正确例子:
o = SimpleObject('digest matches')
# 将一个对象串行化
pickled_data = pickle.dumps(o)
# print(pickled_data)
# b'\x80\x04\x95<\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\x0cSimpleObject\x94\x93\x94)\x81\x94}\x94\x8c\x04name\x94\x8c\x0edigest matches\x94sb.'
digest = make_digest(pickled_data)
header = b'%s %d\n' % (digest, len(pickled_data))
print('WRITING: {}'.format(header))
# WRITING: b'2574f41071ee032fa55b17eac7c8be8e5ea36c59 71\n'
out_s.write(header)
out_s.write(pickled_data)
# 错误例子:
o = SimpleObject('digest does not match.')
pickled_data = pickle.dumps(o)
digest = make_digest(b'not the pickled data at all')
header = b'%s %d\n' % (digest, len(pickled_data))
print('WRITING: {}'.format(header))
out_s.write(header)
out_s.write(pickled_data)
out_s.flush()
in_s = io.BytesIO(out_s.getvalue())
while True:
first_line = in_s.readline()
if not first_line:
break
incoming_digest, incoming_length = first_line.split(b' ')
incoming_length = int(incoming_length.decode('utf-8'))
print('\nREAD:', incoming_digest, incoming_length)
incoming_pickled_data = in_s.read(incoming_length)
actual_digest = make_digest(incoming_pickled_data)
print('ACTUAL:', actual_digest)
if hmac.compare_digest(actual_digest, incoming_digest):
obj = pickle.loads(incoming_pickled_data)
print('OK:', obj)
else:
print('WARING: Data corruption')
# 输出:
# WRITING: b'2574f41071ee032fa55b17eac7c8be8e5ea36c59 71\n'
# WRITING: b'b01b209e28d7e053408ebe23b90fe5c33bc6a0ec 79\n'
#
# READ: b'2574f41071ee032fa55b17eac7c8be8e5ea36c59' 71
# ACTUAL: b'2574f41071ee032fa55b17eac7c8be8e5ea36c59'
# OK: digest matches
#
# READ: b'b01b209e28d7e053408ebe23b90fe5c33bc6a0ec' 79
# ACTUAL: b'd64506a3bf18b459748c0ccfd4d675c6bed412ae'
# WARING: Data corruption