如何在Python Cryptography中读取二进制格式的RSA密钥?
用cryptography加载二进制格式的RSA模数与指数
你之前的问题出在用错了加载函数——load_pem_private_key是专门用来解析PEM格式密钥的,但你手里的是原始二进制的RSA参数(模数、指数),两者格式完全不兼容,自然会报反序列化错误。
下面分公钥和私钥两种情况,给你具体的实现方案:
一、加载RSA公钥(仅模数n+公钥指数e)
RSA公钥只需要模数(n)和公钥指数(e)两个参数,步骤如下:
- 把二进制的
n和e转换成大整数(注意字节序,RSA参数通常用大端字节序存储) - 用
RSAPublicNumbers构造公钥对象
示例代码:
from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization # 假设你从文件读取二进制的模数和指数 with open("public_n.bin", "rb") as f: n_bytes = f.read() with open("public_e.bin", "rb") as f: e_bytes = f.read() # 二进制转大整数(大端字节序) n = int.from_bytes(n_bytes, byteorder='big') e = int.from_bytes(e_bytes, byteorder='big') # 构造公钥 public_numbers = rsa.RSAPublicNumbers(e, n) public_key = public_numbers.public_key(default_backend()) # 验证:可以导出成PEM格式确认正确性 pem = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) print(pem.decode())
二、加载RSA私钥(需要更多参数)
私钥的结构比公钥复杂,仅靠模数n和私钥指数d是不够的,还需要质数因子p、q,以及三个辅助参数:
dmp1 = d % (p-1)dmq1 = d % (q-1)iqmp = pow(q, -1, p)(q的模p逆元)
如果你的二进制文件包含这些参数,代码示例如下:
from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization # 读取所有二进制参数 with open("private_n.bin", "rb") as f: n_bytes = f.read() with open("private_e.bin", "rb") as f: e_bytes = f.read() with open("private_d.bin", "rb") as f: d_bytes = f.read() with open("private_p.bin", "rb") as f: p_bytes = f.read() with open("private_q.bin", "rb") as f: q_bytes = f.read() # 转成大整数 n = int.from_bytes(n_bytes, byteorder='big') e = int.from_bytes(e_bytes, byteorder='big') d = int.from_bytes(d_bytes, byteorder='big') p = int.from_bytes(p_bytes, byteorder='big') q = int.from_bytes(q_bytes, byteorder='big') # 计算辅助参数 dmp1 = d % (p - 1) dmq1 = d % (q - 1) iqmp = pow(q, -1, p) # 构造私钥 public_numbers = rsa.RSAPublicNumbers(e, n) private_numbers = rsa.RSAPrivateNumbers( p=p, q=q, d=d, dmp1=dmp1, dmq1=dmq1, iqmp=iqmp, public_numbers=public_numbers ) private_key = private_numbers.private_key(default_backend()) # 验证:导出成PEM格式确认正确性 pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption() ) print(pem.decode())
注意:如果你的二进制文件是把所有参数打包在一起的(比如按顺序存储n、e、d、p、q),需要先按参数的字节长度拆分二进制数据,再分别转换。
内容的提问来源于stack exchange,提问作者drum




