《Python下读取公私钥做加解密实例详解》
在信息安全领域,公私钥加密(非对称加密)是保护数据传输和存储的核心技术。Python通过`cryptography`、`pycryptodome`等库提供了强大的加密支持。本文将详细讲解如何生成RSA公私钥对、读取本地密钥文件,并实现基于公钥加密和私钥解密的完整流程,包含代码示例和关键步骤解析。
一、非对称加密基础
非对称加密使用一对数学相关的密钥:公钥(Public Key)和私钥(Private Key)。公钥用于加密数据,私钥用于解密。其核心特点包括:
- 安全性:私钥必须保密,公钥可自由分发
- 用途:常用于数字签名、SSL/TLS证书、加密敏感数据
- 算法:RSA、ECC、DSA等,本文以RSA为例
二、生成RSA公私钥对
使用Python的`cryptography`库生成2048位的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格式
pem_private = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
# 序列化公钥为PEM格式
pem_public = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# 保存到文件
with open("private_key.pem", "wb") as f:
f.write(pem_private)
with open("public_key.pem", "wb") as f:
f.write(pem_public)
生成的`private_key.pem`和`public_key.pem`文件将用于后续加解密操作。
三、读取密钥文件
从PEM格式文件中加载公私钥的代码:
from cryptography.hazmat.primitives import serialization
def load_private_key(file_path):
with open(file_path, "rb") as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None # 无密码保护时设为None
)
return private_key
def load_public_key(file_path):
with open(file_path, "rb") as key_file:
public_key = serialization.load_pem_public_key(
key_file.read()
)
return public_key
# 使用示例
private_key = load_private_key("private_key.pem")
public_key = load_public_key("public_key.pem")
四、公钥加密实现
使用公钥加密数据的完整流程(需配合填充方案):
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
def encrypt_with_public_key(public_key, plaintext):
ciphertext = public_key.encrypt(
plaintext.encode('utf-8'),
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
return ciphertext
# 示例使用
message = "这是一条需要加密的敏感信息"
encrypted_data = encrypt_with_public_key(public_key, message)
print(f"加密结果(Base64): {encrypted_data.hex()}")
关键点说明:
- 使用OAEP填充方案增强安全性
- SHA256作为哈希算法
- 加密结果为二进制数据,可转为Base64或十六进制存储
五、私钥解密实现
使用私钥解密数据的完整流程:
def decrypt_with_private_key(private_key, ciphertext):
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
return plaintext.decode('utf-8')
# 示例使用
decrypted_message = decrypt_with_private_key(private_key, encrypted_data)
print(f"解密结果: {decrypted_message}")
注意事项:
- 必须使用与加密时相同的填充方案
- 私钥解密操作需严格保护,避免泄露
- 解密失败会抛出`ValueError`异常
六、完整加解密流程示例
整合生成密钥、加密、解密的完整代码:
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
# 1. 生成密钥对
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
# 2. 保存密钥
with open("private.pem", "wb") as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
))
with open("public.pem", "wb") as f:
f.write(public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
))
# 3. 加载密钥(模拟从文件读取)
def load_key(file_path, is_private=False):
with open(file_path, "rb") as f:
if is_private:
return serialization.load_pem_private_key(f.read(), password=None)
else:
return serialization.load_pem_public_key(f.read())
public_key = load_key("public.pem")
private_key = load_key("private.pem", is_private=True)
# 4. 加密解密测试
original_message = "Python非对称加密测试"
print(f"原始消息: {original_message}")
# 加密
encrypted = public_key.encrypt(
original_message.encode('utf-8'),
padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None)
)
print(f"加密结果(十六进制): {encrypted.hex()}")
# 解密
decrypted = private_key.decrypt(
encrypted,
padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None)
).decode('utf-8')
print(f"解密结果: {decrypted}")
七、常见问题与解决方案
问题1:加密数据过大报错
RSA加密有长度限制(2048位密钥最多加密245字节)。解决方案:
- 使用混合加密:用RSA加密对称密钥(如AES),再用对称密钥加密大数据
- 分段加密(不推荐,性能差)
问题2:密钥文件保护
私钥文件应设置访问权限:
# Linux/Mac设置文件权限
chmod 600 private_key.pem
或使用密码保护私钥:
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.backends import default_backend
import os
password = b"my_secure_password"
salt = os.urandom(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
backend=default_backend()
)
key = kdf.derive(password)
# 加密私钥时使用
encrypted_private = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.BestAvailableEncryption(key)
)
八、性能优化建议
1. **密钥长度选择**:2048位RSA足够安全,3072位更安全但性能下降
2. **缓存密钥对象**:避免频繁加载密钥文件
3. **使用ECC算法**:同等安全下ECC(如ECDSA)密钥更短、速度更快
4. **多线程处理**:加密解密操作可并行化
九、实际应用场景
1. **安全通信**:客户端用服务器公钥加密,服务器用私钥解密
2. **数字签名**:用私钥签名数据,公钥验证签名
3. **配置加密**:加密数据库连接字符串等敏感配置
4. **文件加密**:加密重要文档后仅允许特定私钥解密
关键词:Python加密、RSA算法、公私钥对、非对称加密、PEM格式、OAEP填充、cryptography库、密钥生成、数据安全
简介:本文详细介绍Python环境下使用RSA算法实现非对称加密的完整流程,包括生成公私钥对、PEM格式密钥文件读写、基于公钥的数据加密和私钥解密操作。通过代码示例展示从密钥生成到实际加解密的全过程,同时分析常见问题及优化方案,适合需要实现安全数据传输的Python开发者。