Python RSA 非对称加密实现:公钥加密切钥解密完整流程

Mia
Mia
发布时间:2026-10-10| 4人浏览过
原创

本文详解在 Python 环境下利用 cryptography 库实现 RSA 非对称加密的具体方法。内容涵盖环境准备、密钥对生成与加密存储、基于公钥的数据加密以及使用带密码私钥的解密还原全流程。脚本采用 OAEP 填充与 SHA-256 算法保障安全性,附带常见报错排查与生产环境存储建议,助开发者快速搭建可靠的数据加密通道。

操作目标与环境准备

目标是基于 Python 实现一套可靠的非对称加解密流程,利用生成的公钥对外发送密文,接收方凭独占的私钥还原原文。操作前需确保运行环境已安装基础密码学依赖库,可通过终端执行安装命令:

pip install cryptography

准备一个独立的工作目录用于存放生成的 .pem 密钥文件与加密后的二进制密文,避免敏感数据被意外覆盖或泄露。

第一步:生成并存储非对称密钥对

目的:创建符合 PKCS#8 格式的 RSA 密钥对,并对私钥附加密码保护以防止未授权读取。公钥用于加密,私钥严格保密。

  1. 调用 rsa.generate_private_key 生成主密钥,指定指数为 65537、长度为 2048 位。
  2. 提取对应的公钥对象。
  3. 使用 serialization.BestAvailableEncryption 对私钥进行 PEM 编码并写入磁盘,同时设置强密码。
  4. 以 SubjectPublicKeyInfo 格式导出公钥并保存。
# step1_generate_keys.py
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend


def generate_and_save_keys(private_key_filename="private_key.pem",
                           public_key_filename="public_key.pem",
                           password=None):
    # 1. 生成密钥对
    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    )
    public_key = private_key.public_key()

    # 2. 私钥加密
    if password:
        encryption_algorithm = serialization.BestAvailableEncryption(password.encode('utf-8'))
    else:
        encryption_algorithm = serialization.NoEncryption()

    private_pem = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=encryption_algorithm
    )
    with open(private_key_filename, "wb") as f:
        f.write(private_pem)
    print(f"私钥已保存到:{private_key_filename}")

    public_pem = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
    )
    with open(public_key_filename, "wb") as f:
        f.write(public_pem)
    print(f"公钥已保存到:{public_key_filename}")


if __name__ == "__main__":
    # 实际使用时请将密码替换为复杂字符串
    generate_and_save_keys("my_private_key.pem", "my_public_key.pem", password="my_secret_password")

执行后目录下将产出两个文件:明文公钥 my_public_key.pem 与密码保护的私钥 my_private_key.pem。

第二步:加载公钥并加密传输数据

目的:模拟发送端行为,将待传文本转换为不可逆密文。采用 OAEP 填充机制搭配 SHA-256 算法,防止静态密文被暴力破解。

# step2_encrypt.py
import os
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend


def generate_random_message(length=100):
    return ''.join(os.urandom(1).hex() for _ in range(length // 2))


def load_public_key(filename):
    with open(filename, "rb") as f:
        pem_data = f.read()
    return serialization.load_pem_public_key(pem_data, backend=default_backend())


def encrypt_data(public_key, message):
    encoded_message = message.encode('utf-8')
    ciphertext = public_key.encrypt(
        encoded_message,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    return ciphertext


def main():
    send_message = generate_random_message(100)
    print(f"原始明文:{send_message}")
    public_key_object = load_public_key("my_public_key.pem")
    encrypted_msg = encrypt_data(public_key_object, send_message)
    print(f"密文十六进制片段: {encrypted_msg.hex()[:64]}...")
    
    with open("encrypted_message.bin", "wb") as f:
        f.write(encrypted_msg)
    print("密文已成功写入 encrypted_message.bin")

if __name__ == "__main__":
    main()

运行该脚本后,屏幕会打印原始内容与密文摘要,工作目录中新增 encrypted_message.bin 即完成加密归档。

第三步:读取受保护私钥并还原明文

目的:模拟接收端使用持有者凭证解密数据。需严格匹配生成密钥时设定的密码,且解密使用的填充参数必须与加密端完全一致。

# step3_decrypt.py
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization


def load_private_key(filename, password=None):
    with open(filename, "rb") as f:
        pem_data = f.read()
    password_bytes = password.encode('utf-8') if password else None
    return serialization.load_pem_private_key(
        pem_data, password=password_bytes, backend=default_backend()
    )


def decrypt_data(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')


def main():
    private_key_object = load_private_key("my_private_key.pem", password="my_secret_password")
    with open("encrypted_message.bin", "rb") as f:
        encrypted_msg_from_alice = f.read()
        
    decrypted_message = decrypt_data(private_key_object, encrypted_msg_from_alice)
    print(f"解密还原成功: {decrypted_message}")

if __name__ == "__main__":
    main()

执行完毕后,终端输出与初始随机生成的内容逐字一致,表示非对称加解密链路验证通过。

关键注意事项与排错建议

  • 密码一致性校验:加载私钥时提供的密码必须与生成时的密码完全相同,错误会导致 ValueError: Padding is incorrect. 或认证失败异常。
  • 填充模式匹配:加密与解密必须共用同一组填充配置(本例为 padding.OAEP + hashes.SHA256),混用 PKCS1v15 等旧式填充将导致解析崩溃。
  • 长文本限制:RSA 直接加密长度受密钥位数限制(2048 位约限制 190 字节)。如需加密大文件或连续文本,应仅用 RSA 加密对称会话密钥,再改用 AES 等分组密码处理主体数据。
  • 安全存储:生产环境中切勿将 .pem 文件提交至版本控制系统,建议配合环境变量管理密钥路径与口令。

以上就是使用 Python 结合 cryptography 库实现数据公钥加密与私钥解密的详细内容,更多关于非对称加密实战与安全通信的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。