如何使用Python cryptography模块导出公私钥为字节形式?
问题:使用Python
cryptography模块导出/导入公私钥为字节并转为Base64编码 我尝试了rsa.RSAPrivateKey.private_bytes的多种参数组合,但均无法正常运行,代码及错误如下:
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, PublicFormat, NoEncryption private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) pvt_bytes = private_key.private_bytes(Encoding.Raw, PrivateFormat.Raw, NoEncryption()) # 报错:ValueError: format is invalid with this key public_key = private_key.public_key() pub_bytes = public_key.public_bytes(Encoding.Raw, PublicFormat.Raw) print(pvt_bytes, pub_bytes)
需求是将公私钥导出为字节形式,最终得到类似uFWnMdqUALp2NcvKRxE8Fw2uWDbBjnSk5wveuL3DOp7Ct4AyYKpvccMEE63ooYoj4nblafAwXikakGPbCM4amg==的Base64编码版本,同时支持导入操作。
解决方案
一、导出公私钥并转为Base64编码
RSA私钥不支持Encoding.Raw+PrivateFormat.Raw的组合,必须使用标准编码格式(PEM/DER)配合规范密钥格式,再将字节转为Base64。以下是正确实现:
方式1:PEM编码(带头部尾部,可读性高)
import base64 from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, PublicFormat, NoEncryption # 生成RSA密钥对 private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048) # 导出私钥为字节并转Base64 private_bytes = private_key.private_bytes( encoding=Encoding.PEM, format=PrivateFormat.PKCS8, encryption_algorithm=NoEncryption() ) private_b64 = base64.b64encode(private_bytes).decode('utf-8') # 导出公钥为字节并转Base64 public_key = private_key.public_key() public_bytes = public_key.public_bytes( encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo ) public_b64 = base64.b64encode(public_bytes).decode('utf-8') print("Base64编码的私钥:") print(private_b64) print("\nBase64编码的公钥:") print(public_b64)
方式2:DER编码(无头部尾部,更紧凑)
如果需要更精简的字节内容,可将Encoding.PEM替换为Encoding.DER:
# DER格式导出私钥并转Base64 private_bytes_der = private_key.private_bytes( encoding=Encoding.DER, format=PrivateFormat.PKCS8, encryption_algorithm=NoEncryption() ) private_b64_der = base64.b64encode(private_bytes_der).decode('utf-8') # DER格式导出公钥并转Base64 public_bytes_der = public_key.public_bytes( encoding=Encoding.DER, format=PublicFormat.SubjectPublicKeyInfo ) public_b64_der = base64.b64encode(public_bytes_der).decode('utf-8')
二、从Base64编码导入公私钥
将Base64解码为字节后,使用对应格式的加载方法还原密钥:
从PEM格式Base64导入
import base64 from cryptography.hazmat.primitives.serialization import load_pem_private_key, load_pem_public_key from cryptography.hazmat.backends import default_backend # 导入私钥 private_b64 = "你的Base64编码私钥" private_bytes = base64.b64decode(private_b64) private_key = load_pem_private_key(private_bytes, password=None, backend=default_backend()) # 导入公钥 public_b64 = "你的Base64编码公钥" public_bytes = base64.b64decode(public_b64) public_key = load_pem_public_key(public_bytes, backend=default_backend())
从DER格式Base64导入
如果是DER编码的Base64,替换为对应的加载方法:
from cryptography.hazmat.primitives.serialization import load_der_private_key, load_der_public_key # 导入DER格式私钥 private_key = load_der_private_key(private_bytes, password=None, backend=default_backend()) # 导入DER格式公钥 public_key = load_der_public_key(public_bytes, backend=default_backend())
关键注意事项
- RSA私钥不支持
Raw编码/格式,必须使用PKCS8、PKCS1等标准格式;公钥Raw格式仅适用于EC密钥等特定场景,RSA公钥建议用SubjectPublicKeyInfo格式。 - 如果需要加密私钥(带密码),可将
NoEncryption()替换为BestAvailableEncryption(b"你的密码"),导入时需传入对应密码。
内容的提问来源于stack exchange,提问作者Basj
相关产品推荐
相关产品推荐

