Standard key conversion to/from cryptography library
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):
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)