M2Crypto - 从非标准文件导入密钥?

时间:2012-04-28 20:02:04

标签: python rsa m2crypto

我有一个带有公共指数和模数的文件。它们不是pem或xml或der格式,它们只是在它们的偏移处写入的值。

如何使用M2Crypto从中创建公钥?我也有相同格式的私钥。我已经设法使用有人在Stackoverflow上发布的代码生成一个带有php的PEM文件,但这似乎是一种非常荒谬的方式。

这也不是一次性的事情,我需要能够从这种格式的文件中读取公共指数和模数来检查签名。

1 个答案:

答案 0 :(得分:1)

非常感谢Lars:http://blog.oddbit.com/2011/05/09/signing-data-with-ssh-agent/

e是公共指数的Python longn是公共模数的Python long

他发布的代码是:

import M2Crypto
key = M2Crypto.RSA.new_pub_key((
    M2Crypto.m2.bn_to_mpi(M2Crypto.m2.hex_to_bn(hex(e)[2:])),
    M2Crypto.m2.bn_to_mpi(M2Crypto.m2.hex_to_bn(hex(n)[2:])),
    ))

hex会生成排序0xA45E的十六进制字符串,所以他只是抓住0x之后的所有内容。

我正在从文件中读取密钥,因此我不会长篇大论。我最终使用了:

import M2Crypto
from binascii import hexlify 
e = f.read(4)
n = f.read(0x80)
key = M2Crypto.RSA.new_pub_key((
    M2Crypto.m2.bn_to_mpi(M2Crypto.m2.hex_to_bn(hexlify(e))),
    M2Crypto.m2.bn_to_mpi(M2Crypto.m2.hex_to_bn(hexlify(n))),
    ))

像魅力一样工作!

根据文档,new_pub_key的可接受格式需要

  

OpenSSL的MPINT格式 - 4字节大端位计数后跟   适当的位数

我不确定这是否是一个拼写错误,但是我的指数(十六进制)00010001最终成为000003010001。我认为这是一个字节数,而不是位数。他们还剥离了第一个0x00。我不知道这个标准是不是因为它是一个空字节。

编辑:我想我对格式有了更好的了解。

如果第一个字节为负数,则在开头添加一个零字节。 如果有任何前导(开头)零字节,它们将被剥离,除非第一个字节变为负数,在这种情况下,只剩下一个零字节。

一些例子:

Unformatted:
\x23\x24\x25\x26
Formatted:
\x00\x00\x00\x04\x23\x24\x25\x26
Explanation:
String left as is and count of bytes packed in

Unformatted:
\x00\x23\x55\x35
Formatted:
\x00\x00\x00\x03\x23\x55\x35
Explanation:
leading zero byte removed, byte count now 3

Unformatted:
\x80\x43\x55\x27
Formatted:
\x00\x00\x00\x05\x00\x80\x43\x55\x27
Explanation:
leading zero byte added because \x80 is negative

Unformatted:
\x00\xff\x43\x23
Formatted:
\x00\x00\x00\x04\x00\xff\x43\x23
Explanation:
Leading zero byte left because \xff is negative

Unformatted:
\x23\x53\66\x00
Formatted:
\x00\x00\x00\x04\x23\x53\66\x00
Explanation:
Trailing zero byte left in string