pycose icon indicating copy to clipboard operation
pycose copied to clipboard

Standard key conversion to/from cryptography library

Open BrianSipos opened this issue 4 years ago • 1 comments

Currently the EC2Key and OKPKey classes use the cryptography library internally to do work but don't expose API to use these intermediate representations. When interoperating between cose and other libraries it would be convenient to have a standard API to get these representations.

Without this API an application needs to do some special data manipulation which duplicates already-present internal state of functions within those classes.

For my own use and as an example the RSAKey class in my branch uses the following API (but the names are arbitrary and I have no special need for them):

    @classmethod
    def from_cryptograpy_key_obj(cls, ext_key) -> 'RSAKey':

and

    def to_cryptograpy_key_obj(self):

BrianSipos avatar Mar 08 '21 17:03 BrianSipos

In case someone has an urgent need for this for EC keys, here's what I use currently, adapted from @BrianSipos' RSA equivalent:

from cose.keys.ec2 import EC2Key
from cose.keys.curves import P256, P384, P521
from cose.keys.keyparam import EC2KpCurve, EC2KpX, EC2KpY, EC2KpD

def from_cryptography_eckey_obj(ext_key) -> EC2Key:
    """
    Returns an initialized COSE Key object of type EC2Key.
    :param ext_key: Python cryptography key.
    :return: an initialized EC key
    """
    def to_bstr(dec):
        blen = (dec.bit_length() + 7) // 8
        return dec.to_bytes(blen, byteorder='big')

    if hasattr(ext_key, 'private_numbers'):
        priv_nums = ext_key.private_numbers()
        pub_nums = priv_nums.public_numbers
    else:
        priv_nums = None
        pub_nums = ext_key.public_numbers()

    if pub_nums.curve.name == 'secp256r1':
        curve = P256
    elif pub_nums.curve.name == 'secp384r1':
        curve = P384
    elif pub_nums.curve.name == 'secp521r1':
        curve = P521
    else:
        raise NotImplementedError("unsupported curve")

    cose_key = {}
    if pub_nums:
        cose_key.update({
            EC2KpCurve: curve,
            EC2KpX: to_bstr(pub_nums.x),
            EC2KpY: to_bstr(pub_nums.y),
        })
    if priv_nums:
        cose_key.update({
            EC2KpD: to_bstr(priv_nums.private_value),
        })
    return EC2Key.from_dict(cose_key)

letmaik avatar Mar 14 '22 18:03 letmaik