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 三个库的对比总结

为了让你看得更清楚,我画了一张图来展示这三个库在签名验签流程中的位置。

Python 密码学库在签名验签中的角色 原始数据 hashlib SHA256 哈希计算 cryptography 高层签名/验签 API pycryptodome 底层算法精细控制 签名/验签结果 说明 三个库可独立使用,也可组合

从这张图可以看出来: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,结果密钥生成有漏洞,被攻击者轻松破解。