能否用公钥加密私钥?Python cryptography代码报错求助
如何用公钥加密私钥?
你的代码报错ValueError: Encryption/decryption failed.的核心原因和你猜测的一致:RSA加密存在明文长度限制,直接加密大体积的私钥PEM数据超出了这个限制。
为什么会报错?
RSA加密的最大明文长度取决于密钥长度和填充方式:
以你用的2048位RSA+OAEP-SHA256为例,可加密的明文最大长度计算公式为:密钥长度(字节) - 2*哈希算法输出长度 - 2
2048位密钥对应256字节,SHA256的输出长度是32字节,代入后得到:256 - 2*32 -2 = 190字节。
而你序列化后的未加密RSA私钥PEM数据,长度大概在1KB左右,远大于190字节,直接加密必然触发长度超限错误。
正确的解决方案:混合加密
RSA天生不适合加密大体积数据,业界标准方案是用对称加密算法加密私钥,再用公钥加密对称密钥,具体步骤如下:
- 生成随机的对称加密密钥(比如AES-256密钥)
- 用对称密钥加密RSA私钥
- 用对方的公钥加密这个对称密钥
- 传输时将加密后的私钥、加密后的对称密钥(以及对称加密需要的IV等参数)一起发送
修改后的可运行代码
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import padding, rsa from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes import os # 生成RSA密钥对 generated_private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend() ) bytes_private_key = generated_private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) # 模拟接收方的公钥(实际场景替换为对方的公钥) peer_public_key = generated_private_key.public_key() # 1. 生成AES-256密钥和CBC模式所需的IV aes_key = os.urandom(32) iv = os.urandom(16) # 2. 用AES-CBC加密RSA私钥(自动处理PKCS7填充) cipher = Cipher(algorithms.AES(aes_key), modes.CBC(iv), backend=default_backend()) encryptor = cipher.encryptor() encrypted_private_key = encryptor.update(bytes_private_key) + encryptor.finalize() # 3. 用对方公钥加密AES密钥 encrypted_aes_key = peer_public_key.encrypt( aes_key, padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None, ), ) # 后续可将 encrypted_private_key、iv、encrypted_aes_key 一起保存或传输 # 解密流程:用自己的RSA私钥解密出AES密钥 → 用AES密钥+IV解密得到原始私钥
额外说明
- 不要尝试拆分私钥分块加密,这种方式实现复杂、效率极低,完全没有实际应用价值。
- 混合加密结合了对称加密的高效性和公钥加密的安全性,是传输敏感大体积数据的标准方案。
内容的提问来源于stack exchange,提问作者danielmoessner
相关产品推荐
相关产品推荐

