28

I have a RSA public key in PEM format + PKCS#1(I guess):

-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAJNrHWRFgWLqgzSmLBq2G89exgi/Jk1NWhbFB9gHc9MLORmP3BOCJS9k
onzT/+Dk1hdZf00JGgZeuJGoXK9PX3CIKQKRQRHpi5e1vmOCrmHN5VMOxGO4d+zn
JDEbNHODZR4HzsSdpQ9SGMSx7raJJedEIbr0IP6DgnWgiA7R1mUdAgMBAAE=
-----END RSA PUBLIC KEY-----

I want to get the SHA1 digest of its ASN1 encoded version in Python. The first step should be to read this key, but I failed to do it in PyCrypto:

>> from Crypto.PublicKey import RSA
>> RSA.importKey(my_key)
ValueError: RSA key format is not supported

The documentation of PyCrypto says PEM + PKCS#1 is supported, so I'm confused. I've also tried M2Crypto, but it turns out that M2Crypto does not support PKCS#1 but only X.509.

tshepang
  • 10,772
  • 21
  • 84
  • 127
Mr.Teen
  • 571
  • 1
  • 6
  • 17

1 Answers1

25

PyCrypto supports PKCS#1 in the sense that it can read in X.509 SubjectPublicKeyInfo objects that contain an RSA public key encoded in PKCS#1.

Instead, the data encoded in your key is a pure RSAPublicKey object (that is, an ASN.1 SEQUENCE with two INTEGERs, modulus and public exponent).

You can still read it in though. Try something like:

from Crypto.PublicKey import RSA
from Crypto.Util import asn1
from base64 import b64decode

key64 = 'MIGJAoGBAJNrHWRFgWLqgzSmLBq2G89exgi/Jk1NWhbFB9gHc9MLORmP3BOCJS9k\
onzT/+Dk1hdZf00JGgZeuJGoXK9PX3CIKQKRQRHpi5e1vmOCrmHN5VMOxGO4d+znJDEbNHOD\
ZR4HzsSdpQ9SGMSx7raJJedEIbr0IP6DgnWgiA7R1mUdAgMBAAE='

keyDER = b64decode(key64)
seq = asn1.DerSequence()
seq.decode(keyDER)
keyPub = RSA.construct( (seq[0], seq[1]) )

Starting from version 2.6, PyCrypto can import also RsaPublicKey ASN.1 objects. The code is then much simpler:

from Crypto.PublicKey import RSA
from base64 import b64decode

key64 = b'MIGJAoGBAJNrHWRFgWLqgzSmLBq2G89exgi/Jk1NWhbFB9gHc9MLORmP3BOCJS9k\
onzT/+Dk1hdZf00JGgZeuJGoXK9PX3CIKQKRQRHpi5e1vmOCrmHN5VMOxGO4d+znJDEbNHOD\
ZR4HzsSdpQ9SGMSx7raJJedEIbr0IP6DgnWgiA7R1mUdAgMBAAE='

keyDER = b64decode(key64)
keyPub = RSA.importKey(keyDER)
  • 3
    It is generated via PEM_write_bio_RSAPublicKey in OpenSSL. I believe it is an valid PEM key, and I managed to read it using python-rsa. – Mr.Teen May 18 '12 at 14:25
  • Starting from version 2.6, PyCrypto can import also RsaPublic key objects so the code above is not necessary anymore. – SquareRootOfTwentyThree Jul 19 '13 at 10:15
  • Using Python 3, the ASN1 decode returns bytes, while `construct` needs ints. Which byte order is used? – Janus Troelsen Feb 26 '14 at 20:47
  • @SquareRootOfTwentyThree: What do you mean when you say "RsaPublic"? I don't see how this code could be shortened. Please update the answer. – Janus Troelsen Feb 26 '14 at 20:48
  • @janus-troelsen RsaPublicKey is the simple ASN.1 object with modulus and public exponent (see A.1.1 in RFC3447). With PyCrypto 2.6, you can simply use `RSA.importKey`. – SquareRootOfTwentyThree Mar 01 '14 at 12:56
  • The author asked about PEM, not ASN1 (or DER). The statement that the key provided by Mr.Teen is *invalid* is simply wrong. Try it out: `$ openssl rsa -RSAPublicKey_in -in pub-key.pem -inform PEM -text -noout`. – jww Apr 20 '14 at 10:37
  • @jww PEM is encoded DER, which is one of the possible ways to encode ASN.1. I agree that my statement about invalidity is not fully correct. I will remove it. BTW, is the openssl option "RSAPublicKey_in" documented anywhere? – SquareRootOfTwentyThree Apr 20 '14 at 11:21