def create_cose_key( key_type: Type[CoseKey], input_data: dict, alg: Optional[CoseAlgorithms] = None, usage: Optional[KeyOps] = None) -> Union[EC2, SymmetricKey, OKP]: if key_type == EC2: key = EC2( kid=input_data.get(CoseKey.Common.KID), key_ops=usage, alg=alg, crv=input_data.get(EC2.EC2Prm.CRV), x=CoseKey.base64decode(input_data.get(EC2.EC2Prm.X)), y=CoseKey.base64decode(input_data.get(EC2.EC2Prm.Y)), d=CoseKey.base64decode(input_data.get(EC2.EC2Prm.D)), ) elif key_type == SymmetricKey: key = SymmetricKey(kid=input_data.get(CoseKey.Common.KID), alg=alg, key_ops=usage, k=CoseKey.base64decode( input_data.get(SymmetricKey.SymPrm.K))) elif key_type == OKP: key = OKP( kid=input_data.get(CoseKey.Common.KID), alg=alg, key_ops=usage, crv=input_data.get(OKP.OKPPrm.CRV), x=unhexlify(input_data.get(OKP.OKPPrm.X)), d=unhexlify(input_data.get(OKP.OKPPrm.D)), ) else: raise Exception return key
def setup_ec_receiver_keys(recipient: dict, received_key_obj) -> Tuple[EC2, EC2]: alg = recipient.get("protected", {}).get(CoseHeaderKeys.ALG) if alg is None: alg = recipient.get("unprotected", {}).get(CoseHeaderKeys.ALG) rcvr_static_key = EC2( kid=recipient['key'][CoseKey.Common.KID], crv=recipient['key'][EC2.EC2Prm.CRV], alg=alg, x=CoseKey.base64decode(recipient['key'][EC2.EC2Prm.X]), y=CoseKey.base64decode(recipient['key'][EC2.EC2Prm.Y]), d=CoseKey.base64decode(recipient['key'][EC2.EC2Prm.D]), ) # create CoseKey object for the sender key if 'sender_key' in recipient: sender_key = EC2( alg=alg, crv=recipient["sender_key"][EC2.EC2Prm.CRV], x=CoseKey.base64decode(recipient['sender_key'][EC2.EC2Prm.X]), y=CoseKey.base64decode(recipient['sender_key'][EC2.EC2Prm.Y])) else: sender_key = received_key_obj return rcvr_static_key, sender_key
def from_dict(cls, cose_key: dict) -> 'OKPKey': """ Returns an initialized COSE Key object of type OKPKey. :param cose_key: Dictionary containing COSE Key parameters and there values. :return: an initialized OKPKey key """ _optional_params = {} # extract and remove items from dict, if not found return default value x = CoseKey._extract_from_dict(cose_key, OKPKpX) d = CoseKey._extract_from_dict(cose_key, OKPKpD) curve = CoseKey._extract_from_dict(cose_key, OKPKpCurve, None) _optional_params.update(cose_key) CoseKey._remove_from_dict(_optional_params, OKPKpX) CoseKey._remove_from_dict(_optional_params, OKPKpD) CoseKey._remove_from_dict(_optional_params, OKPKpCurve) return cls(crv=curve, x=x, d=d, optional_params=_optional_params, allow_unknown_key_attrs=True)
def test_encrypt_hkdf_hmac_direct_decode( setup_encrypt_hkdf_hmac_direct_tests: tuple) -> None: _, test_input, test_output, test_intermediate, fail = setup_encrypt_hkdf_hmac_direct_tests # parse message and test for headers md: EncMessage = CoseMessage.decode(unhexlify(test_output)) assert md.phdr == extract_phdr(test_input, 'enveloped') assert md.uhdr == extract_uhdr(test_input, 'enveloped', 0) # check for external data and verify internal _enc_structure md.external_aad = unhexlify(test_input['enveloped'].get('external', b'')) assert md._enc_structure == unhexlify(test_intermediate['AAD_hex']) recipient = test_input['enveloped']['recipients'][0] assert md.recipients[0].phdr == recipient.get('protected', {}) # create HKDF contect v = PartyInfo( identity=md.recipients[0].uhdr.get(CoseHeaderKeys.PARTY_V_IDENTITY), nonce=md.recipients[0].uhdr.get(CoseHeaderKeys.PARTY_V_NONCE), other=md.recipients[0].uhdr.get(CoseHeaderKeys.PARTY_V_OTHER)) u = PartyInfo( identity=md.recipients[0].uhdr.get(CoseHeaderKeys.PARTY_U_IDENTITY), nonce=md.recipients[0].uhdr.get(CoseHeaderKeys.PARTY_U_NONCE), other=md.recipients[0].uhdr.get(CoseHeaderKeys.PARTY_U_OTHER)) public_data = test_input['enveloped']['recipients'][0].get( 'unsent', {}).get('pub_other') s = SuppPubInfo( len(test_intermediate['CEK_hex']) * 4, md.recipients[0].encode_phdr(), public_data.encode('utf-8') if public_data is not None else public_data) priv_data = test_input['enveloped']['recipients'][0].get('unsent', {}).get( 'priv_other', b'') hkdf_context = CoseKDFContext( md.phdr[CoseHeaderKeys.ALG], u, v, s, priv_data.encode('utf-8') if priv_data != b'' else priv_data) assert hkdf_context.encode() == unhexlify( test_intermediate["recipients"][0]['Context_hex']) # set shared secret key shared_secret = SymmetricKey( k=CoseKey.base64decode(test_input['enveloped']['recipients'][0]['key'][ SymmetricKey.SymPrm.K])) kek = md.recipients[0].derive_kek( shared_secret, alg=md.recipients[0].phdr[CoseHeaderKeys.ALG], context=hkdf_context, salt=md.recipients[0].uhdr.get(CoseHeaderKeys.SALT)) assert kek == unhexlify(test_intermediate["CEK_hex"]) cek = SymmetricKey(k=kek, alg=extract_alg(test_input['enveloped'])) assert md.decrypt(key=cek, nonce=extract_nonce( test_input, 0)) == test_input['plaintext'].encode('utf-8')
def from_dict(cls, cose_key: dict) -> 'SymmetricKey': """ Returns an initialized COSE Key object of type SymmetricKey. :param cose_key: Dict containing COSE Key parameters and their values. :return: an initialized COSE SymmetricKey object """ _optional_params = {} k = CoseKey._extract_from_dict(cose_key, SymKpK) _optional_params.update(cose_key) CoseKey._remove_from_dict(_optional_params, SymKpK) return cls(k=k, optional_params=_optional_params, allow_unknown_key_attrs=True)
def test_encrypt0_decoding(test_encrypt0): test_input = test_encrypt0['input'] test_output = test_encrypt0['output'] msg = CoseMessage.decode(cbor2.dumps(test_output['result'])) assert msg.phdr == test_input['protected'] assert msg.uhdr == test_input['unprotected'] key = CoseKey.from_dict(test_encrypt0["cek"]) key.key_ops = [DecryptOp] msg.key = key assert msg.decrypt() == test_input['plaintext']
def test_encrypt0_decoding(test_mac0): test_input = test_mac0['input'] test_output = test_mac0['output'] msg = CoseMessage.decode(cbor2.dumps(test_output['result'])) msg.external_aad = test_input['external_aad'] key = CoseKey.from_dict(test_mac0["cek"]) key.key_ops = [MacVerifyOp] msg.key = key assert msg.phdr == test_input['protected'] assert msg.uhdr == test_input['unprotected'] assert msg.verify_tag()
def _fix_header_algorithm_names(data: dict, key) -> None: try: header_dict = data[key] except KeyError: return temp = None if "epk" in header_dict: _fix_key_object(header_dict, "epk") temp = header_dict["epk"] if EC2.EC2Prm.X in temp and isinstance(temp[EC2.EC2Prm.X], str): temp[EC2.EC2Prm.X] = CoseKey.base64decode(temp[EC2.EC2Prm.X]) if EC2.EC2Prm.Y in temp and isinstance(temp[EC2.EC2Prm.Y], str): temp[EC2.EC2Prm.Y] = CoseKey.base64decode(temp[EC2.EC2Prm.Y]) del header_dict["epk"] header_dict = { k: (v if v not in algs_to_be_replaced else algs_to_be_replaced[v]) for k, v in header_dict.items() } if temp is not None: header_dict[CoseHeaderKeys.EPHEMERAL_KEY] = temp data[key] = header_dict
def test_sign1_decoding(test_sign1): test_input = test_sign1['input'] test_output = test_sign1['output'] msg = CoseMessage.decode(cbor2.dumps(test_output['result'])) msg.external_aad = test_input['external_aad'] key = CoseKey.from_dict(test_sign1["cek"]) key.key_ops = [VerifyOp] msg.key = key assert msg.phdr == test_input['protected'] assert msg.uhdr == test_input['unprotected'] assert msg.verify_signature()
def test_encrypt_direct_encryption_decoding(test_encrypt_direct_encryption_files): test_output = test_encrypt_direct_encryption_files['output'] test_input = test_encrypt_direct_encryption_files['input'] msg = CoseMessage.decode(cbor2.dumps((test_output['result']))) key = CoseKey.from_dict(test_encrypt_direct_encryption_files["cek"]) key.key_ops = [DecryptOp] msg.key = key assert msg.phdr == test_input['protected'] assert msg.uhdr == test_input['unprotected'] for r in msg.recipients: assert msg.decrypt(r) == test_input['plaintext']
def _parse_credentials( cred: Union[CBOR, Callable] ) -> Tuple[Union[CBOR, Callable], Union[Key, Callable]]: if isinstance(cred, bytes): if isinstance(cbor2.loads(cred), dict): # this is an RPK cose_key = CoseKey.decode(cbor2.loads(cred)) return cred, cose_key else: # TODO: update when test vectors for CBOR encoded certificates are correct return cred, None else: return cred, cred
def test_mac_direct_encryption_decoding(test_mac_direct_encryption_files): test_output = test_mac_direct_encryption_files['output'] test_input = test_mac_direct_encryption_files['input'] msg = CoseMessage.decode(cbor2.dumps((test_output['result']))) msg.external_aad = test_input['external_aad'] key = CoseKey.from_dict(test_mac_direct_encryption_files["cek"]) key.key_ops = [MacVerifyOp] msg.key = key assert msg.phdr == test_input['protected'] assert msg.uhdr == test_input['unprotected'] for r in msg.recipients: assert msg.verify_tag(r)
def test_encrypt_direct_encryption_encoding(test_encrypt_direct_encryption_files): test_input = test_encrypt_direct_encryption_files['input'] test_output = test_encrypt_direct_encryption_files['output'] recipients = _setup_direct_encryption_recipients(test_input['recipients']) msg = EncMessage(test_input['protected'], test_input['unprotected'], test_input['plaintext'], recipients=recipients) key = CoseKey.from_dict(test_encrypt_direct_encryption_files["cek"]) key.key_ops = [EncryptOp] msg.key = key assert msg.phdr_encoded == test_output['protected'] assert msg.uhdr_encoded == test_output['unprotected'] assert msg._enc_structure == test_output['structure'] assert cbor2.loads(msg.encode()) == test_output['result']
def test_mac0_encoding(test_mac0): test_input = test_mac0['input'] test_output = test_mac0['output'] msg = Mac0Message(phdr=test_input['protected'], uhdr=test_input['unprotected'], payload=test_input['plaintext'], external_aad=test_input['external_aad']) assert msg.phdr_encoded == test_output['protected'] assert msg.uhdr_encoded == test_output['unprotected'] assert msg._mac_structure == test_output['structure'] key = CoseKey.from_dict(test_mac0["cek"]) key.key_ops = [MacCreateOp, MacVerifyOp] msg.key = key assert msg.compute_tag() == test_output['tag'] assert cbor2.loads( msg.encode(tag=test_mac0['cbor_tag'])) == test_output['result']
def test_encrypt0_encoding(test_encrypt0): test_input = test_encrypt0['input'] test_output = test_encrypt0['output'] msg = Enc0Message( phdr=test_input['protected'], uhdr=test_input['unprotected'], payload=test_input['plaintext'], external_aad=test_input['external_aad']) assert msg.phdr_encoded == test_output['protected'] assert msg.uhdr_encoded == test_output['unprotected'] assert msg._enc_structure == test_output['structure'] key = CoseKey.from_dict(test_encrypt0["cek"]) key.key_ops = [EncryptOp, DecryptOp] msg.key = key assert msg.encrypt() == test_output['ciphertext'] assert cbor2.loads(msg.encode()) == test_output['result']
def test_sign1_encoding(test_sign1): test_input = test_sign1['input'] test_output = test_sign1['output'] msg = Sign1Message(phdr=test_input['protected'], uhdr=test_input['unprotected'], payload=test_input['plaintext'], external_aad=test_input['external_aad']) assert msg.phdr_encoded == test_output['protected'] assert msg.uhdr_encoded == test_output['unprotected'] assert msg._sig_structure == test_output['structure'] key = CoseKey.from_dict(test_sign1["cek"]) key.key_ops = [SignOp, VerifyOp] msg.key = key assert msg.compute_signature() == test_output['signature'] assert cbor2.loads( msg.encode(tag=test_sign1['cbor_tag'])) == test_output['result']
def test_encrypt0_round_trip(test_encrypt0): test_input = test_encrypt0['input'] test_output = test_encrypt0['output'] key = CoseKey.from_dict(test_encrypt0["cek"]) key.key_ops = [DecryptOp, EncryptOp] msg = Enc0Message( phdr=test_input['protected'], uhdr=test_input['unprotected'], payload=test_input['plaintext'], external_aad=test_input['external_aad'], key=key) assert msg.encrypt() == test_output['ciphertext'] assert cbor2.loads(msg.encode()) == test_output['result'] msg = msg.encode() msg = CoseMessage.decode(msg) msg.key = key assert msg.decrypt() == test_input['plaintext']
from binascii import unhexlify from pytest import mark as m from cose import OKP from cose.attributes.algorithms import CoseAlgorithms, CoseEllipticCurves from cose.attributes.context import CoseKDFContext, PartyInfo, SuppPubInfo from cose.keys.cosekey import CoseKey, KTY, KeyOps from cose.keys.ec2 import EC2 from cose.keys.symmetric import SymmetricKey @m.parametrize("crv, x, y, expected", [ (CoseEllipticCurves.P_256, CoseKey.base64decode("Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0"), CoseKey.base64decode("HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw"), { 1: 2, -1: 1, -2: unhexlify( b'98F50A4FF6C05861C8860D13A638EA56C3F5AD7590BBFBF054E1C7B4D91D6280' ), -3: unhexlify( b'F01400B089867804B8E9FC96C3932161F1934F4223069170D924B7E03BF822BB' ) }), (CoseEllipticCurves.P_521, CoseKey.base64decode(
# set the key and decode the message key.key_ops = KeyOps.DECRYPT assert decoded.decrypt(key=key, nonce=original.uhdr[CoseHeaderKeys.IV]) == payload @mark.parametrize("phdr, uhdr, alg, key1, key2, nonce, expected", [ ({CoseHeaderKeys.ALG: CoseAlgorithms.AES_CCM_16_64_128}, {CoseHeaderKeys.IV: unhexlify(b'89F52F65A1C580933B5261A72F')}, None, SymmetricKey( kid=b'our-secret', alg=CoseAlgorithms.AES_CCM_16_64_128, key_ops=KeyOps.ENCRYPT, k=CoseKey.base64decode("hJtXIZ2uSN5kbQfbtTNWbg")), None, unhexlify("89F52F65A1C580933B5261A72F"), b'6899DA0A132BD2D2B9B10915743EE1F7B92A4680E7C51BDBC1B320EA',), ({CoseHeaderKeys.ALG: CoseAlgorithms.AES_CCM_16_64_128}, {}, CoseAlgorithms.AES_CCM_16_64_128, SymmetricKey( kid=b'our-secret', key_ops=KeyOps.ENCRYPT, k=CoseKey.base64decode("hJtXIZ2uSN5kbQfbtTNWbg")), None, unhexlify(b'89F52F65A1C580933B5261A72F'), b'6899DA0A132BD2D2B9B10915743EE1F7B92A4680E7C51BDBC1B320EA',), ], ids=['standalone_encryption_1', 'standalone_encryption_2'] )
def from_dict(cls, cose_key: dict) -> 'RSAKey': """ Returns an initialized COSE Key object of type RSAKey. :param cose_key: Dict containing COSE Key parameters and there values. :return: an initialized RSAKey key """ _optional_params = {} e = CoseKey._extract_from_dict(cose_key, RSAKpE) n = CoseKey._extract_from_dict(cose_key, RSAKpN) d = CoseKey._extract_from_dict(cose_key, RSAKpD) p = CoseKey._extract_from_dict(cose_key, RSAKpP) q = CoseKey._extract_from_dict(cose_key, RSAKpQ) dp = CoseKey._extract_from_dict(cose_key, RSAKpDP) dq = CoseKey._extract_from_dict(cose_key, RSAKpDQ) qinv = CoseKey._extract_from_dict(cose_key, RSAKpQInv) other = CoseKey._extract_from_dict(cose_key, RSAKpOther, []) r_i = CoseKey._extract_from_dict(cose_key, RSAKpRi) d_i = CoseKey._extract_from_dict(cose_key, RSAKpDi) t_i = CoseKey._extract_from_dict(cose_key, RSAKpTi) _optional_params.update(cose_key) CoseKey._remove_from_dict(_optional_params, RSAKpE) CoseKey._remove_from_dict(_optional_params, RSAKpN) CoseKey._remove_from_dict(_optional_params, RSAKpD) CoseKey._remove_from_dict(_optional_params, RSAKpP) CoseKey._remove_from_dict(_optional_params, RSAKpQ) CoseKey._remove_from_dict(_optional_params, RSAKpDP) CoseKey._remove_from_dict(_optional_params, RSAKpDQ) CoseKey._remove_from_dict(_optional_params, RSAKpQInv) CoseKey._remove_from_dict(_optional_params, RSAKpOther) CoseKey._remove_from_dict(_optional_params, RSAKpQInv) CoseKey._remove_from_dict(_optional_params, RSAKpRi) CoseKey._remove_from_dict(_optional_params, RSAKpDi) CoseKey._remove_from_dict(_optional_params, RSAKpTi) return cls(e=e, n=n, d=d, p=p, q=q, dp=dp, dq=dq, qinv=qinv, other=other, r_i=r_i, d_i=d_i, t_i=t_i, optional_params=_optional_params, allow_unknown_key_attrs=True)
def test_cosekey_decode(encoded_key_obj): key = CoseKey.decode(encoded_key_obj) assert type(key) == EC2 assert key.kty == KTY.EC2 assert key.crv == CoseEllipticCurves.P_256