Last Updated: February 25, 2016
·
1.944K
· turtlebender

Convert openssh public key to rsa key object

I needed to convert an openssh key to an rsa key to be used for signature validation using this library: http://stuvel.eu/rsa. Here's how:

import base64
import struct

from pyasn1.type import univ
from pyasn1.codec.der import encoder as der_encoder
import rsa


def read_openssh_public_key(keydata):
    """
    Convert an openssl formatted key into a pkcs#1 formatted key as used by our rsa library

    :param keydata: The key in openssl encoded/formatted form.

    :return: An rsa PublicKey object
    """
    actual_keydata = base64.b64decode(keydata.split(None)[1])

    parts = []
    while actual_keydata:
        # read the length of the data
        dlen = struct.unpack('>I', actual_keydata[:4])[0]
        # read in <length> bytes
        data = actual_keydata[4:dlen + 4]
        actual_keydata = actual_keydata[4 + dlen:]
        parts.append(data)
    e_val_list = ['%02X' % struct.unpack('B', x)[0] for x in parts[1]]
    e_val = eval('0x' + ''.join(e_val_list))
    n_val_list = ['%02X' % struct.unpack('B', x)[0] for x in parts[2]]
    n_val = eval('0x' + ''.join(n_val_list))
    pkcs1_seq = univ.Sequence()
    pkcs1_seq.setComponentByPosition(0, univ.Integer(n_val))
    pkcs1_seq.setComponentByPosition(1, univ.Integer(e_val))
    encoded_string = base64.encodestring(der_encoder.encode(pkcs1_seq))
    key_data = ('-----BEGIN RSA PUBLIC KEY-----\n'
                       '{0}\n'
                       '-----END RSA PUBLIC KEY-----').format(encoded_string)
    return rsa.PublicKey.load_pkcs1(key_data)

adapted from :http://blog.oddbit.com/2011/05/converting-openssh-public-keys.html