EC2 Key

Overview

COSE EC2 keys can be used for signing and verifying cose.messages.sign1message.Sign1Message and cose.messages.signmessage.SignMessage COSE messages, and also for key agreement in KeyAgreementWithKeyWrap and DirectKeyAgreement COSE recipient structures.

COSE EC2 keys can be created using the EC2Key class or from a standard Python dictionary. The following two examples shows how to create COSE EC2 keys using both methods. The keys are serialized and subsequently deserialized.

>>> import os
>>> from binascii import unhexlify
>>> from cose.keys import EC2Key, CoseKey

>>> # get 32 random bytes as private key (potentially not a valid key for curve P_256)
>>> private_key = unhexlify(b'57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3')
>>> cose_key = EC2Key(crv='P_256', d=private_key, optional_params={'ALG': 'ES256'})

>>> #encode/serialize key
>>> serialized_key = cose_key.encode()
>>> serialized_key
b'\xa6\x01\x02\x03& \x01!X \xba\xc5\xb1\x1c\xad\x8f\x99\xf9\xc7+\x05\xcfK\x9e&\xd2D\xdc\x18\x9ftR(%Z!\x9a\x86\xd6\xa0\x9e\xff"X  \x13\x8b\xf8-\xc1\xb6\xd5b\xbe\x0f\xa5J\xb7\x80J:d\xb6\xd7,\xcf\xedko\xb6\xed(\xbb\xfc\x11~#X W\xc9 wfAF\xe8vv\x0c\x95 \xd0T\xaa\x93\xc3\xaf\xb0N0g\x05\xdb`\x900\x85\x07\xb4\xd3'
>>> # deserialize key
>>> CoseKey.decode(serialized_key)
<COSE_Key(EC2Key): {'EC2KpD': "b'W\\xc9 wf' ... (32 B)", 'EC2KpY': "b' \\x13\\x8b\\xf8-' ... (32 B)", 'EC2KpX': "b'\\xba\\xc5\\xb1\\x1c\\xad' ... (32 B)", 'EC2KpCurve': 'P256', 'KpKty': 'KtyEC2', 'KpAlg': 'Es256'}>
>>> from binascii import unhexlify
>>> from cose.keys import EC2Key, CoseKey

>>> # create key object from a dict, both the key type and key bytes (KTY and K) are mandatory attributes.
>>> key_attribute_dict = {
...     'KTY': 'EC2',
...     'CURVE': 'P_256',
...     'ALG': 'ES256',
...     'D': unhexlify(b'57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3')}

>>> cose_key = CoseKey.from_dict(key_attribute_dict)

>>> #encode/serialize key
>>> serialized_key = cose_key.encode()
>>> serialized_key
b'\xa6\x01\x02\x03& \x01!X \xba\xc5\xb1\x1c\xad\x8f\x99\xf9\xc7+\x05\xcfK\x9e&\xd2D\xdc\x18\x9ftR(%Z!\x9a\x86\xd6\xa0\x9e\xff"X  \x13\x8b\xf8-\xc1\xb6\xd5b\xbe\x0f\xa5J\xb7\x80J:d\xb6\xd7,\xcf\xedko\xb6\xed(\xbb\xfc\x11~#X W\xc9 wfAF\xe8vv\x0c\x95 \xd0T\xaa\x93\xc3\xaf\xb0N0g\x05\xdb`\x900\x85\x07\xb4\xd3'

>>> # deserialize key
>>> CoseKey.decode(serialized_key)
<COSE_Key(EC2Key): {'EC2KpD': "b'W\\xc9 wf' ... (32 B)", 'EC2KpY': "b' \\x13\\x8b\\xf8-' ... (32 B)", 'EC2KpX': "b'\\xba\\xc5\\xb1\\x1c\\xad' ... (32 B)", 'EC2KpCurve': 'P256', 'KpKty': 'KtyEC2', 'KpAlg': 'Es256'}>

Alternatively you can use the generate_key() method. It generates a random COSE EC2 Key for a given curve. Valid curves are P256, P384, and P521.

>>> from cose.keys import EC2Key

>>> # generate a random key
>>> cose_key = EC2Key.generate_key(crv='P_521')

When creating a COSE EC2 Key from a dictionary, you have to make sure that the dictionary holds the KpKty, EC2KpCurve, and either EC2KpD (for private COSE EC2 keys) or EC2KpX and EC2KpY (for public COSE EC2 keys) key attributes. These attributes are mandatory for a valid COSE EC2 Key. If you don’t specify them, the from_dict() will throw an exception.

>>> from cose.keys import EC2Key, CoseKey

>>> key_attribute_dict = {
...     'KTY': 'EC2',
...     'CURVE': 'P_384'}

>>> CoseKey.from_dict(key_attribute_dict)
Traceback (most recent call last):
  File "/usr/lib/python3.6/doctest.py", line 1330, in __run
    compileflags, 1), test.globs)
  File "<doctest default[2]>", line 1, in <module>
    CoseKey.from_dict(key_attribute_dict)
  File "/home/timothy/Projects/pycose/cose/keys/cosekey.py", line 69, in from_dict
    key_obj = cls._key_types[received[KpKty.fullname]].from_dict(received)
  File "/home/timothy/Projects/pycose/cose/keys/ec2.py", line 63, in from_dict
    return cls(crv=curve, x=x, y=y, d=d, optional_params=cose_key)
  File "/home/timothy/Projects/pycose/cose/keys/ec2.py", line 74, in __init__
    raise CoseInvalidKey("Either the public values or the private value must be specified")
cose.exceptions.CoseInvalidKey: Either the public values or the private value must be specified

The key attributes of the COSE EC2 Key can be represented by their string label, the integer identifier or the corresponding python class.

>>> from binascii import unhexlify
>>> from cose.keys import EC2Key, CoseKey
>>> from cose.keys.keytype import KtyEC2
>>> from cose.algorithms import Es256
>>> from cose.keys.curves import P256
>>> from cose.keys.keyparam import KpKty, KpAlg, EC2KpD, EC2KpCurve

>>> # key attribute dict using string representations
>>> key_attribute_dict1 = {
...     'KTY': 'EC2',
...     'CURVE': 'P_256',
...     'ALG': 'ES256',
...     'D': unhexlify(b'57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3')}

>>> cose_key1 = CoseKey.from_dict(key_attribute_dict1)

>>> # key attribute dict using integer identifiers
>>> key_attribute_dict2 = {
...     1: 2,
...     -1: 1,
...     3: -7,
...     -4: unhexlify(b'57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3')}

>>> cose_key2 = CoseKey.from_dict(key_attribute_dict2)

>>> # key attribute dict using Python classes
>>> key_attribute_dict3 = {
...     KpKty: KtyEC2,
...     EC2KpCurve: P256,
...     KpAlg: Es256,
...     EC2KpD: unhexlify(b'57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3')}

>>> cose_key3 = CoseKey.from_dict(key_attribute_dict3)

>>> # key attribute dict using a mix of attribute representations
>>> key_attribute_dict4 = {
...     1: 'EC2',
...     EC2KpCurve: 1,
...     'ALG': Es256,
...     EC2KpD: unhexlify(b'57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3')}

>>> cose_key4 = CoseKey.from_dict(key_attribute_dict4)

>>> # all COSE Symmetric key objects are equal
>>> cose_key1 == cose_key2 == cose_key3 == cose_key4
True

API

class cose.keys.ec2.EC2Key(crv, x=b'', y=b'', d=b'', optional_params=None, allow_unknown_key_attrs=True)

Initialize a COSE key from its components

Not passing a y component is accepted; in this case, one (of the two) valid y will be found for the x. This is good enough for everything that only operates on the x of any derived outputs (in “compact” mode), as per RFC 6090 Section 4.2.

classmethod from_dict(cose_key)

Returns an initialized COSE Key object of type EC2Key.

Parameters

cose_key – Dict containing COSE Key parameters and there values.

Returns

an initialized EC2Key key

property crv

Returns the mandatory EC2KpCurve attribute of the COSE EC2 Key object.

property x

Returns the mandatory EC2KpX attribute of the COSE EC2 Key object.

property alg

Returns the value of the KpAlg key parameter

static base64decode(to_decode)

Decodes BASE64 encoded keys to bytes.

Parameters

to_decode – BASE64 encoded key.

Returns

Key as bytes.

static base64encode(to_encode)

Encodes key bytes as a string.

Parameters

to_encode – Bytes to encode.

Returns

BASE64 encoding.

property base_iv

Returns the value of the KpBaseIV key parameter

encode()

Encodes the COSE key as a CBOR map

Returns

A COSE key encoded as CBOR map

property kid

Returns the value of the KpKid key parameter

property kty

Returns the value of the mandatory KpKty key parameter

property y

Returns the mandatory EC2KpY attribute of the COSE EC2 Key object.

property d

Returns the mandatory EC2KpD attribute of the COSE EC2 Key object.

property key_ops

Returns the value of the KpKeyOps key parameter

classmethod generate_key(crv, optional_params=None)

Generate a random EC2Key COSE key object.

Parameters
  • crv – Specify an CoseEllipticCurves.

  • optional_params – Optional key attributes for the EC2Key object, e.g., KpAlg or KpKid.

Returns

An COSE EC2Key key.