serialized delusions

To content | To menu | To search

Programming

Entries feed - Comments feed

Thursday 2 June 2016

Converting RSA public keys from OpenSSH into GPG

All snippets are for Python 2.

Extracting parameters from SSH key.

The format is blessedly simple, so we can do this without additional libraries. For anything beyond, paramiko probably has it.

import base64
import struct
import binascii

def parsersakey(data):
    """:param data: RSA ssh pubkey string in rfc4253 ssh-rsa format
    :returns tuple exponent,modulus,comment. """
    data = data.encode('ascii').split(b' ',2)
    x = base64.b64decode(data[1])
    res = []
    start = 0
    while(start < len(x)-4):
        l = struct.unpack('>l',x[start:start+4])[0]
        r = struct.unpack('%ds' % l, x[start+4:start+4+l])
        start = start+4+l
        res.append(r[0])
    if(len(res) != 3):
        raise Exception("unexpected # of pieces: %d" % len(res))
    if(start != len(x)):
        print("len got: %d expected: %d" % (len(x),start))
        res.append(x[start:])
    else:
        res.append([])
    if res[0] != b"ssh-rsa":
        raise Exception("not rsa key: %s" % binascii.hexlify(res[0]))
    e = 0
    for i in res[1]:
        e = (e<<8) + ord(i)
    N = 0
    for i in res[2]:
        N = (N<<8) + ord(i)
    return (e,N,data[2] if len(data) == 3 else '')

Creating an PGP pubkey from the parameters

Uses PGPy 0.4.0. There is no API for creating keys from known RSA parameters, so the classes need some massaging. YMMV using other PGPy version.

The resulting key can be converted to rfc4880 form just by applying str() on it.

import pgpy
from pgpy.packet.fields import RSAPub,MPI
from pgpy.packet.packets import PubKeyV4
from pgpy.constants import PubKeyAlgorithm

def custRSAPub(n,e):
    res = RSAPub()
    res.n = MPI(n)
    res.e = MPI(e)
    return res

def custPubKeyV4(custkey):
    res = PubKeyV4()
    res.pkalg = PubKeyAlgorithm.RSAEncryptOrSign
    res.keymaterial = custkey
    res.update_hlen()
    return res

def rsatogpg(e,N,name,**idargs):
    """
    :param e,N: RSA parameters as Python integers or longints
    :param name: Identity name
    :param idargs: PGP Identity parameters, such as comment,email
    :return: PGPy pubkey object
    """
    rsakey = custPubKeyV4(custRSAPub(N,e))
    pgpkey = pgpy.PGPKey()
    pgpkey._key = rsakey

    uid = pgpy.PGPUID.new(name, **idargs)
    uid._parent = pgpkey
    pgpkey._uids.append(uid)
    return pgpkey

Sunday 27 October 2013

Programming, my take on

Where JuroV is trying to tackle that aspect between monitor and chair.

Continue reading...