如何将 RSA512 公钥和指数从.bin文件加载到 python 中



我在将 RSA512 公钥从.bin文件加载到 python 时遇到问题。问题主要源于我不知道密钥以什么格式存储的事实。这是我得到的文件的唯一描述。

"key.bin - RSA 512 位公钥和指数的原始二进制字节。用于验证传入的签名 包。

我不知道这是否有帮助,但这里有.bin文件的 python 打印的字节。

9902c4a66b1ff76392919e7bbc35d51a5128b9da03e131b489d5ed01c1d075fc4c139a9952e9a3b040d984219a4aef0d421f6b8f9c79e1c3c35a218ecba54dc9010001

实际挑战的目标是构建一个 udp 服务器,用于验证传入数据包的数字签名和完整性。目前,我正在使用python 2.7和加密库。文档可以在下面找到。 https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/?highlight=rsa%20512

我已经尝试了下面的代码,但是前两种格式出现相同的错误,第三种格式略有不同。

with open("key.bin", "rb") as key_file:
private_key = serialization.load_der_public_key(key_file.read(), backend=default_backend())
ValueError: Could not deserialize key data.
with open("key.bin", "rb") as key_file:
private_key = serialization.load_pem_public_key(key_file.read(), backend=default_backend())
ValueError: Could not deserialize key data.
with open("key.bin", "rb") as key_file:
private_key = serialization.load_ssh_public_key(key_file.read(), backend=default_backend())
ValueError: Key is not in the proper format or contains extra data.

此外,用于验证的哈希算法是 SHA256,但这可能无关紧要。

您的密钥未以已知标准编码。您需要提取模数和指数,然后从中构建公钥。

模数定义RSA 密钥大小,因此作为无符号大端值为 512 位或 64 字节。公共指数可以具有任何大小,但通常很小。最常用的指数值是十六进制的010001,这是费马的第五个素数(也称为F4,从零开始的指数)。但是,最好只是简单地获取前 64 个字节并假设其余编码是公共指数。

因此,您可以使用RSAPublicNumbers根据模n和指数e创建值。诀窍是确保将模数创建为正值而不是负值。


假设data是从文件中读取的二进制数据。然后,您可以通过以下方式获取公钥。

如果以下方法不起作用,您可能希望使用'little'而不是'big'(大端序是 RSA 默认值,但您永远不知道)。但是,在您的情况下,小端值可以除以例如 11,因此这不是一个可能的模值(素值应接近密钥大小的一半(以确保安全)。

modsize = 512 // 8
modBytes = data[slice(0, modsize)]
mod = int.from_bytes(modBytes, byteorder='big')
expBytes = data[slice(modsize, None)]
exp = int.from_bytes(expBytes, byteorder='big')
pubkey = RSAPublicNumbers(exp, mod).public_key(default_backend())

请注意,from_bytes仅在 Python 3.2 中添加。RSAPublicNumbers有点奇怪,因为它在模数之前采用指数参数。我见过的所有其他 API 都在指数之前取模。

key.bin - RSA 512 位公钥和指数的原始二进制字节。用于验证传入数据包的签名。

在 RSA-512 密钥中,模数是一个 512 位数字,适合 64 个字节或 128 个十六进制数字。您的文件由 134 个十六进制数字表示,因此其中 128 个数字可能是模数,其余数字是公共指数,可能是元数据。

公共指数几乎总是 3 或 65537=0x010001。鉴于key.bin以十六进制010001结尾,合理的猜测是最后 3 个字节是公共指数,前 64 个字节是模数。

with open("key.bin", "rb") as key_file:
n_bytes = key_file.read(64)
e_bytes = key_file.read(3)

您现在需要确定编码是小端序还是大端序。您无法从公共指数中分辨出来,因为它是回文的。因此,请尝试两种可能性:

n = int(n_bytes.encode('hex'), 16)

n = int(reversed(n_bytes).encode('hex'), 16)

由于密钥采用临时格式,而不是现实生活中使用的标准格式,因此您可能打算使用算术基元而不是加密库来处理密钥。

相关内容

最新更新