密码学俱乐部的第一条规则是:永远不要 *自行发明* 密码系统。密码学俱乐部的第二条规则是:永远不要 *自行实现* 密码系统:许多现实世界中的漏洞是在密码系统的 *实现* 阶段以及设计阶段被发现的。
Python 中用于密码学原语的一个有用的库简称为 cryptography。它既有“安全”原语,也有“hazmat”层。“hazmat”层需要谨慎和密码学知识,并且很容易使用它来实现安全漏洞。在这篇介绍性文章中,我们不会介绍“hazmat”层中的任何内容!
cryptography 中最有用的高级安全原语是 Fernet 实现。Fernet 是一种以遵循最佳实践密码学的方式加密缓冲区的标准。它不适用于非常大的文件——任何千兆字节范围及以上的文件——因为它要求您一次性将要加密或解密的整个缓冲区加载到内存中。
Fernet 支持对称或密钥密码学:相同的密钥用于加密和解密,因此必须妥善保管。
生成密钥很容易
>>> k = fernet.Fernet.generate_key()
>>> type(k)
<class 'bytes'>
这些字节可以写入具有适当权限的文件中,最好是在安全的机器上。
一旦您有了密钥材料,加密也很容易
>>> frn = fernet.Fernet(k)
>>> encrypted = frn.encrypt(b"x marks the spot")
>>> encrypted[:10]
b'gAAAAABb1'
如果您在您的机器上加密,您会得到略微不同的值。不仅因为(我希望)您生成了与我不同的密钥,而且因为 Fernet 将要加密的值与一些随机生成的缓冲区连接在一起。这是我之前提到的“最佳实践”之一:它将防止攻击者能够分辨哪些加密值是相同的,这有时是攻击的重要组成部分。
解密同样简单
>>> frn = fernet.Fernet(k)
>>> frn.decrypt(encrypted)
b'x marks the spot'
请注意,这仅加密和解密字节字符串。为了加密和解密文本字符串,它们需要被编码和解码,通常使用 UTF-8。
20 世纪中期密码学中最有趣的进展之一是公钥密码学。它允许发布加密密钥,同时解密密钥保持秘密。例如,它可以用于存储服务器要使用的 API 密钥:服务器是唯一有权访问解密密钥的东西,但任何人都可以通过使用公共加密密钥添加到存储中。
虽然 cryptography 没有任何公钥密码学安全原语,但 PyNaCl 库有。PyNaCl 包装并提供了一些使用 Daniel J. Bernstein 发明的 NaCl 加密系统的好方法。
NaCl 始终同时加密和签名或解密和验证签名。这是一种防止基于可延展性的攻击的方法,在这种攻击中,攻击者会修改加密值。
加密使用公钥完成,而签名使用密钥完成
>>> from nacl.public import PrivateKey, PublicKey, Box
>>> source = PrivateKey.generate()
>>> with open("target.pubkey", "rb") as fpin:
... target_public_key = PublicKey(fpin.read())
>>> enc_box = Box(source, target_public_key)
>>> result = enc_box.encrypt(b"x marks the spot")
>>> result[:4]
b'\xe2\x1c0\xa4'
解密反转角色:它需要私钥进行解密,公钥用于验证签名
>>> from nacl.public import PrivateKey, PublicKey, Box
>>> with open("source.pubkey", "rb") as fpin:
... source_public_key = PublicKey(fpin.read())
>>> with open("target.private_key", "rb") as fpin:
... target = PrivateKey(fpin.read())
>>> dec_box = Box(target, source_public_key)
>>> dec_box.decrypt(result)
b'x marks the spot'
PocketProtector 库构建于 PyNaCl 之上,包含完整的密钥管理解决方案。
评论已关闭。