位置: 文档库 > Python > python下读取公私钥做加解密实例详解

python下读取公私钥做加解密实例详解

云霄 上传于 2022-07-30 01:40

《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开发者。