4、Python密码学库概览:hashlib、cryptography、pycryptodome的安装与基本使用
做签名验签工具,说白了就是跟密码学算法打交道。Python 生态里这块的库不少,但真正靠谱、用得多的,其实就三个:hashlib、cryptography、pycryptodome。我刚开始做安全开发时也踩过不少坑,今天就把这三个库的安装和基本用法给你捋清楚。
核心观点:hashlib 做哈希,cryptography 做通用密码操作,pycryptodome 做底层算法。签名验签工具里,三个库都会用到。
4.1 三个库的定位与区别
先搞清楚它们各自是干嘛的,不然容易选错。
| 库名 | 定位 | 典型用途 | 我个人的选择建议 |
|---|---|---|---|
| hashlib | Python 标准库,纯哈希 | MD5、SHA1、SHA256 等摘要计算 | 做哈希时首选,零依赖 |
| cryptography | 现代密码学高层封装 | 签名、加密、证书、密钥管理 | 签名验签工具的主力库 |
| pycryptodome | 底层密码算法集合 | RSA、ECC、AES 等原始算法 | 需要精细控制算法参数时用 |
你想想看,hashlib 是 Python 自带的,装完 Python 就能用。cryptography 和 pycryptodome 需要 pip 安装。我一般这么搭配:哈希用 hashlib,签名验签主体用 cryptography,遇到特殊算法需求再上 pycryptodome。
4.2 安装方法
安装其实很简单,但版本问题容易翻车。我曾经在生产环境遇到过 cryptography 版本不兼容导致签名失败的情况,折腾了一下午。
4.2.1 hashlib
这个不用装,直接 import 就行。
import hashlib
print(hashlib.algorithms_guaranteed) # 查看所有支持的算法
4.2.2 cryptography
推荐用 pip 安装,注意 Python 版本要 3.7+。
pip install cryptography
小提示:我建议用虚拟环境安装,避免跟系统级 Python 包冲突。我习惯用 python -m venv venv 创建隔离环境。
4.2.3 pycryptodome
这个库安装时有个坑——它跟 pycrypto 包名容易混淆。记住是 pycryptodome,不是 pycrypto。
pip install pycryptodome
注意:pycryptodome 在 Windows 上可能需要安装 Visual C++ 构建工具。如果安装失败,去微软官网下载 "Microsoft C++ Build Tools" 装上就行。
4.3 基本使用:hashlib
hashlib 的使用模式非常固定,说白了就是三步:创建对象、喂数据、取摘要。
import hashlib
# 计算字符串的 SHA256 哈希
data = b"hello, world"
sha256 = hashlib.sha256()
sha256.update(data)
digest = sha256.hexdigest()
print(digest) # 输出 64 位十六进制字符串
# 一行搞定
digest = hashlib.sha256(data).hexdigest()
我在项目中经常用它来校验文件完整性。比如下载了一个签名工具包,先算 SHA256,再跟官方公布的比对,一致才用。
def file_sha256(filepath):
sha256 = hashlib.sha256()
with open(filepath, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
sha256.update(chunk)
return sha256.hexdigest()
4.4 基本使用:cryptography
cryptography 的 API 设计得比较现代,我个人很喜欢。它把底层细节封装得很好,你不需要关心算法实现细节。
4.4.1 生成 RSA 密钥对
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
# 生成私钥
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
# 提取公钥
public_key = private_key.public_key()
# 序列化私钥(PEM 格式)
private_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
# 序列化公钥
public_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
关键点:公钥指数固定用 65537,这是业界标准。密钥长度至少 2048 位,1024 位已经不安全了。
4.4.2 签名与验签
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
message = b"这是一条待签名的消息"
# 签名
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
# 验签
try:
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("验签成功")
except:
print("验签失败")
嗯,这里要注意:签名用的是私钥,验签用的是公钥。我见过不少新手搞反了,结果验签永远失败。
4.5 基本使用:pycryptodome
pycryptodome 的 API 更底层一些,适合需要精细控制算法参数的场景。比如你想用 RSA-OAEP 加密,或者自定义哈希算法。
4.5.1 生成 RSA 密钥对
from Crypto.PublicKey import RSA
# 生成 2048 位密钥对
key = RSA.generate(2048)
# 导出私钥(PEM 格式)
private_key = key.export_key()
print(private_key.decode())
# 导出公钥
public_key = key.publickey().export_key()
print(public_key.decode())
4.5.2 签名与验签
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
message = b"这是一条待签名的消息"
# 计算哈希
h = SHA256.new(message)
# 签名
signature = pkcs1_15.new(key).sign(h)
# 验签
try:
pkcs1_15.new(key.publickey()).verify(h, signature)
print("验签成功")
except (ValueError, TypeError):
print("验签失败")
小技巧:pycryptodome 的签名流程是"先哈希,再签名",而 cryptography 是"自动哈希"。如果你需要控制哈希算法,pycryptodome 更灵活。
4.6 三个库的对比总结
为了让你看得更清楚,我画了一张图来展示这三个库在签名验签流程中的位置。
从这张图可以看出来:hashlib 负责哈希计算,cryptography 和 pycryptodome 负责签名/验签。实际开发中,我通常用 cryptography 做主力,遇到特殊需求才用 pycryptodome。
4.7 避坑指南
最后分享几个我踩过的坑,你遇到了能少走弯路。
- 密钥格式不匹配:cryptography 生成的 PEM 密钥,pycryptodome 不一定能直接读。我建议统一用 cryptography 做密钥管理。
- 哈希算法不一致:签名时用的哈希算法,验签时必须用同一个。我曾经在签名时用 SHA256,验签时忘了指定,结果一直失败。
- 填充模式搞错:RSA 签名有 PSS 和 PKCS1v15 两种填充模式。PSS 更安全,但兼容性差一些。我一般用 PSS,除非对方要求 PKCS1v15。
- 字节串 vs 字符串:密码学操作全是字节串(bytes),不是字符串(str)。
b"hello"和"hello"不一样,别搞混了。
重要提醒:千万不要在生产环境使用自己实现的密码学算法。就用这些经过安全审计的库,别想着自己造轮子。我曾经见过有人自己实现 RSA,结果密钥生成有漏洞,被攻击者轻松破解。