Python为加密任务提供了各种内置算法。这篇文章将演示hmac。加密任务的内置算法之一**,用于使用Python的加密消息签名和验证**,并通过Python4Delphi在Python GUI中运行以获得结果。
hmac模块实现了用于消息验证的键合,如RFC 2104中所述。HMAC算法可以用来验证应用程序之间传递的信息的完整性,或者存储在一个有潜在风险的位置。
其基本思想是生成实际数据的加密散列,并结合共享的秘密密钥。然后,产生的哈希值可以用来检查传输或存储的信息,以确定信任程度,而不需要传输秘密密钥。
这篇文章将指导你
如何在Windows GUI应用程序中使用内置的hmac库实现Python加密服务?
先决条件 在我们开始工作之前,请下载并安装你所在平台的最新 Python。按照 这里提到的 Python4Delphi安装说明。或者,你也可以查看这个视频中的简单说明 开始使用Python4Delphi。
首先,使用Python4Delphi与RAD Studio的项目Demo1打开并运行我们的Python GUI。然后将脚本插入下层备忘录中,点击执行按钮,在上层备忘录中得到结果。你可以在 GitHub上找到Demo1的源代码。关于Delphi如何在这个神奇的Python GUI中运行你的Python代码的幕后细节可以在这个 链接中找到。
打开Demo01.dproj
我们如何使用二进制摘要来产生可打印的摘要?
让我们尝试一个二进制摘要的例子,以产生可打印的摘要。一些网络服务(Google checkout, Amazon S3)使用base64编码的二进制摘要而不是hexdigest。在Python4Delphi GUI中运行以下代码。
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.encodebytes(digest))
base64编码的字符串在新的一行中结束,当把字符串嵌入http头或其他对格式敏感的环境中时,经常需要把它剥离出来。让我们看看Python GUI中的输出。
如何用Python实现消息签名的应用?
接下来,让我们尝试一个更高级的例子消息签名的应用。HMAC认证应该被用于任何公共网络服务,以及任何存储数据的时间,而这些时间的安全性是很重要的。例如,当通过管道或套接字发送数据时,该数据应该被签名,然后在使用该数据之前对签名进行测试。
以下是实现消息签名应用的步骤:
- 建立一个函数来计算一个字符串的摘要,并建立一个简单的类来实例化并通过通信通道传递。
- 创建一个BytesIO缓冲区来表示套接字或管道。这个例子对数据流使用了一种天真的、但容易解析的格式。数据的摘要和长度被写入,后面是一个新行。接下来是由pickle生成的对象的序列化表示。
- 对于这个例子的程序,写两个对象到流中。第一个对象是用正确的摘要值写的。第二个对象用一个无效的摘要写到流中,这个摘要是通过对其他一些数据而不是pickle的数据计算出的。
- 现在数据在BytesIO缓冲区中,它可以被再次读出来。首先读取带有摘要和数据长度的那行数据。然后读取剩余的数据,使用长度值。pickle.load()可以直接从数据流中读取,但是这假设了一个可信的数据流,而这个数据还没有被信任到足以解开它。从流中以字符串的形式读取pickle,而不实际解开对象,是比较安全的。
- 一旦提取的数据在内存中,可以重新计算摘要值,并使用compare_digest()与读取的数据进行比较。如果摘要匹配,就可以安全地相信数据并解开它。
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
# Simulate a writable socket or pipe with a buffer
out_s = io.BytesIO()
# Write a valid object to the stream:
# digestnlengthnpickle
o = SimpleObject('digest matches')
pickled_data = pickle.dumps(o)
digest = make_digest(pickled_data)
header = b'%s %dn' % (digest, len(pickled_data))
print('WRITING: {}'.format(header))
out_s.write(header)
out_s.write(pickled_data)
# Write an invalid object to the stream
o = SimpleObject('digest does not match')
pickled_data = pickle.dumps(o)
digest = make_digest(b'not the pickled data at all')
header = b'%s %dn' % (digest, len(pickled_data))
print('nWRITING: {}'.format(header))
out_s.write(header)
out_s.write(pickled_data)
out_s.flush()
# Simulate a readable socket or pipe with a buffer
in_s = io.BytesIO(out_s.getvalue())
# Read the data
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('WARNING: Data corruption')
- 输出显示,第一个对象被验证,第二个对象被认为是 "损坏的",正如预期。
用简单的字符串或字节比较两个摘要可以在定时攻击中使用,通过传递不同长度的摘要暴露部分或全部密匙。 compare_digest()实现了一个快速但恒定时间的比较函数,以防止定时攻击。
恭喜你!你已经学会了如何实现Python密码。你已经学会了如何使用Python GUI for Delphi Windows App中内置的hmac 库来实现Python加密服务。