M2Crypto - import keys from non-standard file?
Domanda
I have a file with the public exponent and modulus in it. They're not in pem or xml or der format, they're just the values written in at their offsets.
How can I make a public key out of them with M2Crypto? I also have the private key in the same format. I've managed to use code that someone posted here on Stackoverflow to generate a PEM file with php, but this seems like an extremely ridiculous way to do it.
This isn't a one-time thing either, I need to be able to read the public exponent and modulus from files in this format to check the signature.
Soluzione
Thank you very much to Lars here: http://blog.oddbit.com/2011/05/09/signing-data-with-ssh-agent/
e
is a Python long
of the public exponent.
n
is a Python long
of the public Modulus.
The code he posted was:
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 will generate a hex string of the sort 0xA45E
, so he's just grabbing everything after the 0x
.
I'm reading the key from a file, so I don't have it as a long. I ended up using:
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))),
))
Worked like a charm!
The accepted format of new_pub_key
, as per the documentation, needs to be
OpenSSL's MPINT format - 4-byte big-endian bit-count followed by the appropriate number of bits
I'm not sure if this is a typo, but for my exponent of (in hex) 00010001
ended up being 000003010001
. I think it's a byte count, not bit count. They also stripped the first 0x00. I don't know if that's standard or if because it was an empty byte.
edit: I think I have a bit of a better understanding of the format.
If the first byte is negative, a zero byte is added to the beginning. If there are any leading (at the beginning) zero bytes, they are stripped unless the first byte would become negative, in which case, only one zero byte is left.
Some examples:
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