Loading a PKCS#1 public key using M2Crypto

Piet van Oostrum piet at vanoostrum.org
Thu Jan 17 17:39:57 CET 2013

Piet van Oostrum <piet at vanoostrum.org> wrote:

> Converting to X.501 isn't difficult (assuming this is a 2048 bit key):
> Get rid of the 'RSA' in header and trailer
> Prepend X.501 header 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' to the data
> Reformat the lines to 64 characters.

This solution is a bit restricted as it only works if the key is 2048
bits and uses an exponent of 65537 (which is the default). Otherwise it

Here is a robust solution that works for all PKCS#1 keys. Instead of
using a fixed X.501 header it calculates the header. We could do a
complete ASN.1 encoding, but most of the parts are fixed. The only
variable parts are two length fields. So I just plug these into the
fixed stuff. This saves using one of the ASN.1 libraries. We do have to
work in binary (DER format) instead of base64, however.

from M2Crypto import BIO, RSA
import base64

def der_length(length):
    """DER encoding of a length"""
    if length < 128:
        return chr(length)
    prefix = 0x80
    result = ''
    while length > 0:
        result = chr(length & 0xff) + result
        length >>= 8
        prefix += 1
    return chr(prefix) + result
pubkey="""-----BEGIN RSA PUBLIC KEY-----

pk = pubkey.split('\n')
pk = '\0' + base64.decodestring("".join(pk[1:-2]))
pk = '\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03' + \
     der_length(len(pk)) + pk
pk = '\x30' + der_length(len(pk)) + pk
pk = '-----BEGIN PUBLIC KEY-----\n' + base64.encodestring(pk) + '-----END PUBLIC KEY-----'

bio = BIO.MemoryBuffer(pk)
key = RSA.load_pub_key_bio(bio)

Piet van Oostrum <piet at vanoostrum.org>
WWW: http://pietvanoostrum.com/
PGP key: [8DAE142BE17999C4]

More information about the Python-list mailing list