9.6 KiB
9.6 KiB
RSA 密钥管理与签名验证工具技术文档
本项目提供一个基于 cryptography 库的轻量级 RSA 加密、解密、签名与验证功能封装,支持多种密钥格式(PEM、PKCS#1、PKCS#8、OpenSSH)的加载与写入。适用于需要安全地处理 RSA 公私钥及数字签名的应用场景。
📦 依赖库
pip install cryptography
注意:
cryptography是一个使用 CFFI 绑定 OpenSSL 的密码学库,需确保系统中已安装必要的编译工具或预编译包。
🧩 模块功能概览
| 功能 | 描述 |
|---|---|
_load_private_key |
从文件加载私钥(支持 PEM 和 OpenSSH 格式) |
_load_public_key |
从文件加载公钥(支持 PEM 和 OpenSSH 格式) |
_write_private_key |
将私钥写入文件(支持 PKCS#1, PKCS#8, OpenSSH 格式) |
_write_public_key |
将公钥写入文件(支持 PEM, OpenSSH 格式) |
_sign / _verify |
使用私钥签名和公钥验证数据(SHA256 + PKCS1v15) |
RSAer 类 |
面向对象接口,集成密钥生成、读写、签名/验证等功能 |
🔐 私钥操作
_load_private_key(filepath: str, password: bytes = None) → RSAPrivateKey
从指定路径加载私钥文件,自动识别格式并返回对应的 RSAPrivateKey 对象。
参数:
filepath(str): 私钥文件路径。password(bytes, optional): 解密加密私钥所需的口令(字节类型),若未加密可省略。
支持格式:
| 开头标识 | 格式说明 |
|---|---|
-----BEGIN OPENSSH PRIVATE KEY----- |
OpenSSH 私钥格式 |
-----BEGIN RSA PRIVATE KEY----- 或 -----BEGIN PRIVATE KEY----- |
PEM 编码的私钥(PKCS#1 或 PKCS#8) |
返回值:
RSAPrivateKey: 成功时返回私钥对象。
异常:
ValueError: 不支持的私钥格式。TypeError: 密码错误或格式损坏。
示例:
private_key = _load_private_key("id_rsa", password=b"mypass")
_write_private_key(key, filepath, fmt="pkcs8", password: bytes = None)
将私钥对象写入文件,支持加密保存。
参数:
key(RSAPrivateKey): 要写入的私钥对象。filepath(str): 输出文件路径。fmt(str): 输出格式,可选"pkcs8"(默认)、"pkcs1"、"openssh"。password(bytes, optional): 若提供,则使用最佳可用算法加密私钥。
支持格式:
fmt 值 |
格式描述 |
|---|---|
pkcs8 |
PEM 编码的 PKCS#8 格式(推荐) |
pkcs1 |
PEM 编码的传统 RSA 私钥(仅限 RSA) |
openssh |
OpenSSH 原生私钥格式(兼容 OpenSSH 工具链) |
注意事项:
- 当
password不为None时,私钥将被加密存储。 - 所有输出均为二进制模式写入。
示例:
_write_private_key(private_key, "private_encrypted.pem", fmt="pkcs8", password=b"secret123")
🔍 公钥操作
_load_public_key(filepath: str) → RSAPublicKey
从文件加载公钥,自动识别格式。
参数:
filepath(str): 公钥文件路径。
支持格式:
| 文件内容开头 | 格式 |
|---|---|
ssh-rsa, ssh-ed25519 等 |
OpenSSH 公钥格式 |
-----BEGIN PUBLIC KEY----- |
PEM 编码的标准公钥(SubjectPublicKeyInfo) |
返回值:
RSAPublicKey: 成功时返回公钥对象。
异常:
ValueError: 不支持的公钥格式。
示例:
public_key = _load_public_key("id_rsa.pub")
_write_public_key(public_key, filepath, fmt="pem")
将公钥对象写入文件。
参数:
public_key(RSAPublicKey): 公钥对象。filepath(str): 输出文件路径。fmt(str): 输出格式,支持"pem"(默认)或"openssh"。
支持格式:
fmt |
输出格式 |
|---|---|
pem |
PEM 编码的 X.509 公钥(标准格式) |
openssh |
OpenSSH 风格的单行公钥(如用于 ~/.ssh/authorized_keys) |
示例:
_write_public_key(public_key, "public.pem", fmt="pem")
_write_public_key(public_key, "id_rsa_openssh.pub", fmt="openssh")
✍️ 数字签名与验证
_sign(prikey, data: bytes) → bytes
使用私钥对数据进行 SHA256 + PKCS1v15 签名。
参数:
prikey(RSAPrivateKey): 有效的 RSA 私钥。data(bytes): 待签名的原始数据。
返回值:
bytes: 签名结果(二进制)。
算法细节:
- 哈希算法:
SHA-256 - 填充方式:
PKCS1v15
⚠️ 注:也可替换为更现代的
PSS填充以增强安全性。
示例:
signature = _sign(private_key, b"Hello World")
_verify(pubkey, data: bytes, signature: bytes) → bool
验证数据签名是否有效。
参数:
pubkey(RSAPublicKey): 对应的公钥。data(bytes): 原始数据。signature(bytes): 签名值。
返回值:
True: 验证成功。False: 验证失败(包括异常捕获)。
内部机制:
- 使用与
_sign相同的参数(PKCS1v15,SHA256)进行校验。 - 捕获
InvalidSignature异常并返回False。
示例:
is_valid = _verify(public_key, b"Hello World", signature)
print(is_valid) # True or False
🧱 RSAer 类:高级封装接口
RSAer 提供面向对象的方式统一管理密钥与操作。
初始化
rsa_tool = RSAer()
属性初始化为空:
self.prikey = Noneself.pubkey = None
.create_key(keylen=2048)
生成新的 RSA 密钥对。
参数:
keylen(int): 密钥长度,默认2048,建议至少 2048 位。
生成规则:
- 公共指数固定为
65537(Fermat Prime,行业标准) - 使用安全随机源生成大素数
示例:
rsa_tool.create_key(2048)
.write_private_key(filepath, fmt="pkcs8", password=None)
导出私钥到文件。
参数:
filepath: 输出路径fmt: 格式(pkcs8,pkcs1,openssh)password: 可选加密口令(bytes)
❗ 抛出异常:若
self.prikey为None
示例:
rsa_tool.write_private_key("mykey.pem", fmt="pkcs8", password=b"pass123")
.write_public_key(filepath, fmt="pem")
导出公钥到文件。
参数:
filepath: 输出路径fmt:pem或openssh
⚠️ 自动从私钥推导公钥(如果尚未设置)
示例:
rsa_tool.write_public_key("mykey.pub", fmt="openssh")
.load_private_key(filepath, password=None)
加载已有私钥。
示例:
rsa_tool.load_private_key("private.pem", password=None)
.load_public_key(filepath)
加载已有公钥。
示例:
rsa_tool.load_public_key("public.pem")
.sign(data: bytes) → bytes
使用当前私钥签名数据。
示例:
sig = rsa_tool.sign(b"Important message")
.verify(data: bytes, signature: bytes) → bool
使用当前公钥验证签名。
示例:
valid = rsa_tool.verify(b"Important message", sig)
assert valid == True
❌ 待实现方法
以下两个方法在代码中声明但未实现:
def encode(self, data):
def decode(self, data):
后续可根据需求补充 RSA 加解密功能(通常用于小数据块加密,如密钥传输)。
推荐使用padding.OAEP或PKCS1v15进行加密填充。
🧪 示例用法(主程序)
if __name__ == '__main__':
# 示例:加载私钥和公钥
private_key = _load_private_key("path/to/private_key.pem", password=None)
public_key = _load_public_key("path/to/public_key.pub")
print("私钥类型:", type(private_key))
print("公钥类型:", type(public_key))
# 写出不同格式的私钥
_write_private_key(private_key, "private_pkcs8.pem", fmt="pkcs8")
_write_private_key(private_key, "private_pkcs1.pem", fmt="pkcs1")
_write_private_key(private_key, "private_openssh", fmt="openssh")
# 写出不同格式的公钥
_write_public_key(public_key, "public.pem", fmt="pem")
_write_public_key(public_key, "id_rsa.pub", fmt="openssh")
# 签名与验证
data = b"Secure message"
signature = _sign(private_key, data)
is_valid = _verify(public_key, data, signature)
print("Signature valid?", is_valid)
✅ 安全建议
-
密钥保护:
- 私钥应始终加密存储(使用强密码)。
- 权限设为
600(Linux/macOS)防止他人读取。
-
签名算法选择:
- 推荐使用
PSS填充替代PKCS1v15以获得更强的安全性。 - 示例修改:
padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH )
- 推荐使用
-
密钥长度:
- 至少使用 2048 位,推荐 3072 或 4096 以应对未来威胁。
-
避免直接加密大数据:
- RSA 不适合直接加密大量数据。
- 应结合 AES 等对称加密使用“混合加密”方案。
📚 参考资料
- cryptography 官方文档
- OpenSSH Key Format
- RFC 8017 — PKCS #1 v2.2
- NIST FIPS 186-4 — Digital Signature Standard (DSS)
🧾 版本信息
- 语言: Python 3.6+
- 库版本要求:
cryptography >= 3.0 - 许可证: MIT(示例代码,实际请根据项目授权)
✅ 本文档最后更新:2025年4月5日
作者:AI Assistant
用途:开发参考、API 文档、安全实践指南