Python中HMAC加密算法的应用
作者:Python知识大全 发布时间:2021-07-29 15:55:18
HMAC 算法可用于验证在应用程序之间传递或存储在潜在易受攻击位置的信息的完整性。基本思想是生成与共享密钥组合的实际数据的加密散列。然后,可以使用所得到的散列来检查所发送或存储的消息以确定信任级别,而不发送秘密密钥。
签名消息
new() 函数创建一个用于计算消息签名的新对象。此示例使用默认的 MD5 散列算法。
```python
hmac_simple.py
import hmac
digest_maker = hmac.new(b'secret-shared-key-goes-here')with open('lorem.txt', 'rb') as f:
while True:
block = f.read(1024)
if not block:
break
digest_maker.update(block)digest = digest_maker.hexdigest()print(digest)
运行时,代码读取数据文件并为其计算 HMAC 签名。
$ python3 hmac_simple.py
4bcb287e284f8c21e87e14ba2dc40b16
可选的摘要类型
尽管默认的 hmac 算法是 MD5,但那不是最安全的方法。MD5 摘要算法有一些缺点,例如碰撞?(两个不同的消息产生了不同的哈希值)。SHA-1 被公认为是比较健壮的,应该使用它。
hmac_sha.py
import hmac
import hashlib
digest_maker = hmac.new(
b'secret-shared-key-goes-here',
b'',
hashlib.sha1,)with open('hmac_sha.py', 'rb') as f:
while True:
block = f.read(1024)
if not block:
break
digest_maker.update(block)digest = digest_maker.hexdigest()print(digest)
new() 函数接受三个参数值,第一个是密钥,共享于两个通信的端点之间,所以两个端点都使用相同的值。第二个参数是初始化消息值。如果需要认证的消息内容非常小,例如时间戳或者 HTTP POST,那么整个消息体可以传入 new() 而不用 update() 方法。最后一个参数是要使用的摘要算法。默认的是 hashlib.md5,例子中使用的是 hashlib.sha1。
$ python3 hmac_sha.py
dcee20eeee9ef8a453453f510d9b6765921cf099
二进制摘要
前一个例子使用了 hexdigest() 方法生成可打印的摘要字符串。这个摘要字符串是由 digest() 方法生成的值的不同表现形式而已,这
hmac_base64.py
import base64
import hmac
import hashlib
with open('lorem.txt', 'rb') as f:
body = f.read()hash = hmac.new(
b'secret-shared-key-goes-here',
body,
hashlib.sha1,)digest = hash.digest()print(base64.encodestring(digest))
base64 编码的字符串以换行符结尾,当将字符串嵌入到 HTTP 头或者其他敏感的上下文中时,经常需要将这个换行符删除。
$ python3 hmac_base64.py
b'olW2DoXHGJEKGU0aE9fOwSVE/o4=\n'
消息签名的应用
HMAC 算法应该用于任何公共网络服务,并且任何数据都应该存储在安全性很重要的地方。例如,当数据被通过管道或者 socket 发送的时候,数据应该被签名,然后在使用之前验签。此处给出的扩展示例位于文件 hmac_pickle.py。
第一步是创建一个函数计算一个字符串的摘要,以及一个简单的类,用于实例化并通过通信通道传递。
hmac_pickle.py
import hashlib
import hmac
import io
import pickle
import pprint
def make_digest(message):
"Return a digest for the message."
hash = hmac.new(
b'secret-shared-key-goes-here',
message,
hashlib.sha1,
)
return hash.hexdigest().encode('utf-8')class SimpleObject:
"""Demonstrate checking digests before unpickling.
"""
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
接下来,创建一个 BytesIO 缓冲池代表一个 socket 或者管道。例子中使用了一个原生的,但是很容易解析的,格式化的数据流。首先数据的摘要和长度被写入,后面紧跟了一个换行符。对象的序列化形式由 pickle 生成。真实的系统可能不希望依赖于长度值,因为如果摘要错误,则长度也是错误的。某些不太可能出现在实际数据中的终结符序列可能更加合适。
然后示例程序中往数据流中写入了两个对象。第一个是使用正确的摘要值写入的。
使用缓冲区模拟可写套接字或者管道
out_s = io.BytesIO()
往流中写入一个有效的对象
digest\nlength\npickle
o = SimpleObject('digest matches')
pickled_data = pickle.dumps(o)
digest = make_digest(pickled_data)
header = b'%s %d\n' % (digest, len(pickled_data))
print('WRITING: {}'.format(header))
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('\nWRITING: {}'.format(header))
out_s.write(header)
out_s.write(pickled_data)
out_s.flush()
记住数据是在 BytesIO 缓冲池中的,它可以再次被读出。首先读取带有摘要和数据长度的行。然后使用长度值读取剩下的数据。pickle.load() 可以直接从流中读取数据,但是它假设一个可信任的数据流,而且这个数据还不足够可信能够反序列化它。从流中读取序列化值为字符串,而不实际反序列化更安全。
使用 BytesIO 模拟可读的 socket 或者管道
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)
一旦序列化数据被读取到内存,摘要值可以被重新计算,并且使用 compare_digest() 同传递过来的数据比较。如果摘要匹配,证明它是安全的去信任数据并且反序列化它。
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('WARNING: Data corruption')
输出表示第一个对象被验证通过,第二个被视为「损坏」。
$ python3 hmac_pickle.py
WRITING: b'f49cd2bf7922911129e8df37f76f95485a0b52ca 69\n'
WRITING: b'b01b209e28d7e053408ebe23b90fe5c33bc6a0ec 76\n'
READ: b'f49cd2bf7922911129e8df37f76f95485a0b52ca' 69
ACTUAL: b'f49cd2bf7922911129e8df37f76f95485a0b52ca'
OK: digest matches
READ: b'b01b209e28d7e053408ebe23b90fe5c33bc6a0ec' 76
ACTUAL: b'2ab061f9a9f749b8dd6f175bf57292e02e95c119'
WARNING: Data corruption
可以在定时攻击中使用简单的字符串或字节比较来比较两个摘要,以通过传递不同长度的摘要来暴露部分或全部秘密密钥。compare_digest() 实现了一个快速但是常量时间的比较函数去防止定时攻击。
来源:https://blog.csdn.net/Baihu292/article/details/130674271


猜你喜欢
- 0.配置依赖环境,如果不进行这步可能会出现一些问题中间可能有多余空格,去除下再运行,一般都能安装成功,如果不能可以先更新下sudo apt-
- Software as a service 软件即服务,21世纪开始兴起的一种完全创新的软件应用模式。客户通过互联网向厂商定购所需的应用软件
- 把下面SQL里的SELECT单独执行,没有问题,但是用来CREATE VIEW 就报错了.CREATE OR REPLA
- 自动求导机制从后向中排除子图每个变量都有两个标志:requires_grad和volatile。它们都允许从梯度计算中精细地排除子图,并可以
- 这样处理的弊端是:如果数据量大,子分类很多,达到4级以上,这方法处理极端占用数据库连接池 对性能影响很大。 如果用SQL下面的CTE递归处理
- 当我们修改一份代码的时候,也许会碰到修改后的代码还不如修改之前的代码能够满足自己的需求,那么这个时候我们就需要对代码进行回滚,下面我们来看一
- 由于我已经安装了anaconda,所以不在赘述,下载可以上清华镜像版下载 https://mirrors.tuna.tsinghua.edu
- 带有yield的函数在Python中被称之为generator(生成器),也就是说,当你调用这个函数的时候,函数内部的代码并不立即执行 ,这
- 1.对于一维数组,可以有:2. 对于二维数组:考虑可将其看作为矩阵,故可以如下书写二重遍历 这里外层循环的是二维数组A的行,内层则
- 简单的说,组织体系指的就是组织信息的方式。看了一堆拗口的定义后,我根据自己的理解画了下面这个图:从上图看出,同样的图形元素由于采用了不同的组
- 1. 谈谈Javascript的对象Javascript作为一种弱语言类型的语言,同时也是一种动态类型的语言。在使用Javascript的过
- 问:如何自己制作验证码的head.fix和body.fix文件答:1 图象绘制完成后,将文件存为24位位图格式的BMP图象文件。 2 去除前
- 大家好,我是了不起!在某些难以抉择得时候,我们经常要用外力来帮助我们做出选择比如,梁山出征方腊前沙场点兵,挑选先锋的场景这个时候
- 如何利用Image Data Type从数据库中读取图片,并在主页中显示图形?然后,写如下代码:< % @&nbs
- 因为最近在做文本检测相关,想试着用用百度的paddle框架。1、安装Anaconda3官网下载安装包直接运行安装,然后新建python3.7
- 目录用Python实现定时任务用Python实现定时任务的四种方法利用while True: + sleep()实现定时任务利用thread
- 计时器setTimeout()和setInterval()两个都是js的计时功能的函数两个有些区别。 setTimeout(): 在js手册
- CSS制作滑动折叠的文字效果,可以用于二级导航菜单的制作,不错的下拉菜单。<!DOCTYPE html PUBLIC "-/
- 一、Jupyter Notebook是什么?1.notebook jupyter简介Jupyter Notebook是一个开源Web应用程序
- 1 sample(序列a,n)sample(序列a,n)功能:从序列a中随机抽取n个元素,并将n个元素生以list形式返回。例:from r