def default_encoder(encoder, value): if isinstance(value, dt.timedelta): encoder.encode( cbor2.CBORTag(2001, ( value.days, value.seconds, value.microseconds))) elif value is NoData: encoder.encode(cbor2.CBORTag(2002, None)) else: raise cbor2.CBOREncodeError( 'cannot serialize type %s' % value.__class__.__name__)
def encode(self, key: SymmetricKey, alg: Optional[CoseAlgorithms] = None, mac_params: Optional[List[RcptParams]] = None, tagged: bool = True, mac: bool = True) -> bytes: """ Encodes and protects the COSE_Mac message. """ # encode/encrypt the base fields if mac: message = [self.encode_phdr(), self.encode_uhdr(), self.payload, self.compute_tag(alg=alg, key=key)] else: message = [self.encode_phdr(), self.encode_uhdr(), self.payload] if mac_params is None: mac_params = [] if len(self.recipients) == len(mac_params): if len(mac_params) > 0: message.append(CoseRecipient.recursive_encode(self.recipients, mac_params)) else: raise ValueError("List with cryptographic parameters should have the same length as the recipient list.") if tagged: message = cbor2.dumps(cbor2.CBORTag(self.cbor_tag, message)) else: message = cbor2.dumps(message) return message
def encode(self, sign_params: Optional[List[SignerParams]] = None, tagged: bool = True) -> bytes: """ Encodes and protects the COSE_Sign message.""" signers = [] message = [self.encode_phdr(), self.encode_uhdr(), self.payload] if sign_params is None: sign_params = [] if len(sign_params) == len(self.signers): for signer, p in zip(self.signers, sign_params): signers.append(signer.encode(p)) else: raise ValueError( "List with cryptographic parameters should have the same length as the recipient list." ) message.append(signers) if tagged: message = cbor2.dumps(cbor2.CBORTag(self.cbor_tag, message)) else: message = cbor2.dumps(message) return message
def encode(self, private_key: Union[EC2, OKP], alg: Optional['CoseAlgorithms'] = None, curve: Optional['CoseEllipticCurves'] = None, tagged: bool = True, sign: bool = True) -> bytes: """ Encodes the message into a CBOR array with or without a CBOR tag. """ if sign: message = [ self.encode_phdr(), self.encode_uhdr(), self.payload, self.compute_signature(alg=alg, private_key=private_key, curve=curve) ] else: message = [self.encode_phdr(), self.encode_uhdr(), self.payload] if tagged: res = cbor2.dumps(cbor2.CBORTag(self.cbor_tag, message), default=self._special_cbor_encoder) else: res = cbor2.dumps(message, default=self._special_cbor_encoder) return res
def encode(self, message: list, tag: bool = True, *args, **kwargs) -> CBOR: if tag: message = cbor2.dumps(cbor2.CBORTag(self.cbor_tag, message), default=self._custom_cbor_encoder) else: message = cbor2.dumps(message, default=self._custom_cbor_encoder) return message
def default_encoder(encoder, obj): if not isinstance(obj, (Company, Employee)): raise Exception('cannot serialize type %s' % obj.__class__) serialized_state = encoder.encode_to_bytes(obj.__dict__) wrapped_state = [obj.__class__.__name__, serialized_state] with encoder.disable_value_sharing(): encoder.encode(cbor2.CBORTag(CBOR_TAGNUM, wrapped_state))
def binaryCborTag(value): ''' Encode CBOR as bytestring and tag the item. :param value: The CBOR item to encode. :return: The binary-enveloped item. ''' # Tag 24: Encoded CBOR data item return cbor2.CBORTag(24, cbor2.dumps(value))
def test_decoding_unknown_type(): ctx = Context() pull = ctx.socket(PULL) push = ctx.socket(PUSH) pull.bind('inproc://foo') push.connect('inproc://foo') push.send(cbor2.dumps(cbor2.CBORTag(4000, None))) with pytest.raises(IOError): pull.recv_msg() push.close() pull.close()
def encode(self, tag: bool = True, sign: bool = True, *args, **kwargs) -> CBOR: """ Encodes the message into a CBOR array with or without a CBOR tag. """ if sign: message = [self.phdr_encoded, self.uhdr_encoded, self.payload, self.compute_signature()] else: message = [self.phdr_encoded, self.uhdr_encoded, self.payload] if tag: res = cbor2.dumps(cbor2.CBORTag(self.cbor_tag, message), default=self._custom_cbor_encoder) else: res = cbor2.dumps(message, default=self._custom_cbor_encoder) return res
def test_cbor_pen(self): data = bytes.fromhex(p_test_vectors14[1].read_text().replace("\n", "")) struct = loads(data) struct2 = loads(struct.value[3]) # manifest struct3 = loads(struct2[3]) # common sequence struct4 = loads(struct3[4]) # override params self.assertEqual(struct4[0], 20) self.assertTrue(isinstance(struct4[1][1], bytes)) struct4[1][1] = cbor2.CBORTag( 112, struct4[1][1]) # Add the tag for cbor-pen struct3[4] = dumps(struct4) struct2[3] = dumps(struct3) struct.value[3] = dumps(struct2) data = dumps(struct) self.decode_string(data, p_manifest14, p_cose)
def test_map_bstr(self): args = [ "zcbor", "--cddl", str(p_map_bstr_cddl), "convert", "--input", str(p_map_bstr_yaml), "-t", "map", "--output", "-" ] call1 = Popen(args, stdout=PIPE) stdout1, _ = call1.communicate() self.assertEqual(0, call1.returncode) self.assertEqual( dumps({ "test": bytes.fromhex("1234abcd"), "test2": cbor2.CBORTag(1234, bytes.fromhex("1a2b3c4d")), ("test3", ): dumps(1234) }), stdout1)
def cbor_tag_encoder(self, encoder: cbor2.CBOREncoder, obj): try: typename, marshaller, wrap_state = self.serializer.marshallers[obj.__class__] except KeyError: raise LookupError('no marshaller found for type "{}"' .format(qualified_name(type(obj)))) from None marshalled_state = marshaller(obj) if wrap_state: serialized_state = encoder.encode_to_bytes(marshalled_state) wrapped_state = [typename, serialized_state] with encoder.disable_value_sharing(): encoder.encode(cbor2.CBORTag(self.type_tag, wrapped_state)) else: encoder.encode(marshalled_state)
def encode(self, tag: bool = True, *args, **kwargs) -> bytes: """ Encodes and protects the COSE_Sign message. """ message = [self.phdr_encoded, self.uhdr_encoded, self.payload] if len(self.signers): message.append([s.encode() for s in self.signers]) if tag: message = cbor2.dumps(cbor2.CBORTag(self.cbor_tag, message), default=self._custom_cbor_encoder) else: message = cbor2.dumps(message, default=self._custom_cbor_encoder) return message
def encode(self, key: SymmetricKey, alg: Optional[CoseAlgorithms] = None, tagged: bool = True, mac: bool = True) -> bytes: """ Encode and protect the COSE_Mac0 message. """ if mac: message = [self.encode_phdr(), self.encode_uhdr(), self.payload, self.compute_tag(alg=alg, key=key)] else: message = [self.encode_phdr(), self.encode_uhdr(), self.payload] if tagged: res = cbor2.dumps(cbor2.CBORTag(self.cbor_tag, message), default=self._special_cbor_encoder) else: res = cbor2.dumps(message, default=self._special_cbor_encoder) return res
def encode(self, nonce: bytes, key: SymmetricKey, alg: Optional[CoseAlgorithms] = None, enc_params: Optional[List[RcptParams]] = None, tagged: bool = True, encrypt: bool = True) -> bytes: """ Encodes and protects the COSE_Encrypt message """ # encode/encrypt the base fields if encrypt: message = [ self.encode_phdr(), self.encode_uhdr(), self.encrypt(nonce=nonce, key=key, alg=alg) ] else: message = [self.encode_phdr(), self.encode_uhdr(), self.payload] if enc_params is None: enc_params = [] if len(self.recipients) == len(enc_params): if len(enc_params) > 0: message.append( CoseRecipient.recursive_encode(self.recipients, enc_params)) else: raise ValueError( "List with cryptographic parameters should have the same length as the recipient list." ) if tagged: message = cbor2.dumps(cbor2.CBORTag(self.cbor_tag, message), default=self._special_cbor_encoder) else: message = cbor2.dumps(message, default=self._special_cbor_encoder) return message
def encode(self, nonce: bytes, key: SymmetricKey, alg: Optional[CoseAlgorithms] = None, tagged: bool = True, encrypt: bool = True) -> bytes: """ Encode and protect the COSE_Encrypt0 message. """ if encrypt: message = [ self.encode_phdr(), self.encode_uhdr(), self.encrypt(nonce=nonce, alg=alg, key=key) ] else: message = [self.encode_phdr(), self.encode_uhdr(), self.payload] if tagged: res = cbor2.dumps(cbor2.CBORTag(self.cbor_tag, message)) else: res = cbor2.dumps(message) return res
def to_suit(self): for k, f in self.fields.items(): v = getattr(self, k, None) if v: return cbor.CBORTag(tag=f.suit_key, value=v.to_suit()) return None
class TestCOSE: """ Tests for COSE. """ def test_cose_constructor_with_options(self): ctx = COSE.new() assert isinstance(ctx, COSE) def test_cose_alg_auto_inclusion(self): ctx = COSE.new() ctx.alg_auto_inclusion = True assert ctx.alg_auto_inclusion is True def test_cose_kid_auto_inclusion(self): ctx = COSE.new() ctx.kid_auto_inclusion = True assert ctx.kid_auto_inclusion is True def test_cose_verify_kid(self): ctx = COSE.new() ctx.verify_kid = True assert ctx.verify_kid is True def test_cose_encode_and_decode_mac0_with_options(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) # MAC0 mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01") encoded = ctx.encode_and_mac(b"Hello world!", mac_key) assert b"Hello world!" == ctx.decode(encoded, mac_key) def test_cose_encode_and_decode_mac_with_options(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) # MAC mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01") encoded = ctx.encode_and_mac( b"Hello world!", mac_key, recipients=[RecipientInterface(unprotected={ 1: -6, 4: b"01" })], ) assert b"Hello world!" == ctx.decode(encoded, mac_key) def test_cose_encode_and_decode_encrypt0_with_options(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) # Encrypt0 enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="02") encoded = ctx.encode_and_encrypt(b"Hello world!", enc_key) assert b"Hello world!" == ctx.decode(encoded, enc_key) def test_cose_encode_and_decode_encrypt_with_options(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) # Encrypt enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="02") rec = Recipient.from_jwk({"alg": "direct", "kid": "02"}) encoded = ctx.encode_and_encrypt( b"Hello world!", enc_key, recipients=[rec], ) assert b"Hello world!" == ctx.decode(encoded, enc_key) def test_cose_encode_and_decode_signature1_with_options(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) # Signature1 sig_key = COSEKey.from_jwk({ "kty": "EC", "kid": "03", "crv": "P-256", "x": "usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8", "y": "IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4", "d": "V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM", }) encoded = ctx.encode_and_sign(b"Hello world!", sig_key) assert b"Hello world!" == ctx.decode(encoded, sig_key) def test_cose_encode_and_decode_mac0_with_protected_bytes(self): ctx = COSE.new(kid_auto_inclusion=True) # MAC0 mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01") encoded = ctx.encode_and_mac(b"Hello world!", mac_key, protected=b"a0") assert b"Hello world!" == ctx.decode(encoded, mac_key) def test_cose_encode_and_decode_mac_with_protected_bytes(self): ctx = COSE.new() # MAC mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01") encoded = ctx.encode_and_mac( b"Hello world!", mac_key, protected=b"a0", recipients=[RecipientInterface(unprotected={ 1: -6, 4: b"01" })], ) assert b"Hello world!" == ctx.decode(encoded, mac_key) def test_cose_encode_and_decode_encrypt0_with_protected_bytes(self): ctx = COSE.new(kid_auto_inclusion=True) # Encrypt0 enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="02") encoded = ctx.encode_and_encrypt(b"Hello world!", enc_key, protected=b"a0") assert b"Hello world!" == ctx.decode(encoded, enc_key) def test_cose_encode_and_decode_encrypt_with_protected_bytes(self): ctx = COSE.new(kid_auto_inclusion=True) # Encrypt enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="02") encoded = ctx.encode_and_encrypt( b"Hello world!", enc_key, protected=b"a0", recipients=[RecipientInterface(unprotected={ 1: -6, 4: b"02" })], ) assert b"Hello world!" == ctx.decode(encoded, enc_key) def test_cose_encode_and_decode_signature1_with_protected_bytes(self): ctx = COSE.new(kid_auto_inclusion=True) # Signature1 sig_key = COSEKey.from_jwk({ "kty": "EC", "kid": "03", "crv": "P-256", "x": "usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8", "y": "IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4", "d": "V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM", }) encoded = ctx.encode_and_sign(b"Hello world!", sig_key, protected=b"a0") assert b"Hello world!" == ctx.decode(encoded, sig_key) def test_cose_encode_and_decode_mac0_with_verify_kid(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True, verify_kid=True) # MAC0 mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01") encoded = ctx.encode_and_mac(b"Hello world!", mac_key) assert b"Hello world!" == ctx.decode(encoded, mac_key) def test_cose_encode_and_decode_mac0_without_kid_with_verify_kid(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True, verify_kid=True) # MAC0 mac_key = COSEKey.from_symmetric_key(alg="HS256") encoded = ctx.encode_and_mac(b"Hello world!", mac_key) with pytest.raises(ValueError) as err: ctx.decode(encoded, mac_key) pytest.fail("decode() should fail.") assert "kid should be specified." in str(err.value) def test_cose_encode_and_decode_with_recipient_builder(self): ctx = COSE.new() mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01") recipient = Recipient.from_jwk({ "alg": "direct", "kid": "01", }) encoded = ctx.encode_and_mac( b"Hello world!", mac_key, recipients=[recipient], ) assert b"Hello world!" == ctx.decode(encoded, mac_key) def test_cose_constructor_with_invalid_kid_auto_inclusion(self): with pytest.raises(ValueError) as err: COSE.new(kid_auto_inclusion="xxx") pytest.fail("COSE() should fail.") assert "kid_auto_inclusion should be bool." in str(err.value) def test_cose_constructor_with_invalid_alg_auto_inclusion(self): with pytest.raises(ValueError) as err: COSE.new(alg_auto_inclusion="xxx") pytest.fail("COSE() should fail.") assert "alg_auto_inclusion should be bool." in str(err.value) def test_cose_constructor_with_invalid_verify_kid(self): with pytest.raises(ValueError) as err: COSE.new(verify_kid="xxx") pytest.fail("COSE() should fail.") assert "verify_kid should be bool." in str(err.value) def test_cose_constructor_with_invalid_ca_certs(self): with pytest.raises(ValueError) as err: COSE.new(ca_certs=b"xxx") pytest.fail("COSE() should fail.") assert "ca_certs should be str." in str(err.value) @pytest.mark.parametrize( "invalid, msg", [ ( { "xxx": "yyy" }, "Unsupported or unknown COSE header parameter: xxx.", ), ( { "alg": "xxx" }, "Unsupported or unknown alg: xxx.", ), ], ) def test_cose_encode_and_mac_with_invalid_protected( self, ctx, invalid, msg): key = COSEKey.from_symmetric_key(alg="HS256") with pytest.raises(ValueError) as err: ctx.encode_and_mac(b"This is the content.", key, protected=invalid) pytest.fail("encode_and_mac should fail.") assert msg in str(err.value) def test_cose_encode_and_mac_with_recipient_has_unsupported_alg(self, ctx): key = COSEKey.from_symmetric_key(alg="HS256") with pytest.raises(NotImplementedError) as err: ctx.encode_and_mac( b"This is the content.", key, recipients=[ RecipientInterface(unprotected={ 1: 0, 4: b"our-secret" }) ], ) pytest.fail("encode_and_mac should fail.") assert "Algorithms other than direct are not supported for recipients." in str( err.value) def test_cose_encode_and_encrypt_with_recipient_has_unsupported_alg( self, ctx): key = COSEKey.from_jwk({ "kty": "oct", "alg": "AES-CCM-16-64-128", "kid": "our-secret", "use": "enc", "k": "hJtXIZ2uSN5kbQfbtTNWbg", }) with pytest.raises(NotImplementedError) as err: ctx.encode_and_encrypt( b"This is the content.", key, nonce=bytes.fromhex("89F52F65A1C580933B5261A72F"), recipients=[ RecipientInterface(unprotected={ 1: 0, 4: b"our-secret" }) ], ) pytest.fail("encode_and_encrypt should fail.") assert "Algorithms other than direct are not supported for recipients." in str( err.value) def test_cose_encode_and_mac_with_invalid_payload(self, ctx): key = COSEKey.from_symmetric_key(alg="HS256") with pytest.raises(EncodeError) as err: ctx.encode_and_mac(datetime.datetime.now(), key, {}, {}) pytest.fail("encode_and_mac should fail.") assert "Failed to encode." in str(err.value) @pytest.mark.parametrize( "invalid, msg", [ ( "invalid_string_data", "Invalid COSE format.", ), ( {}, "Invalid COSE format.", ), ( [], "Invalid COSE format.", ), ( 123, "Invalid COSE format.", ), ( cbor2.CBORTag(16, "invalid_string_data"), "Invalid Encrypt0 format.", ), ( cbor2.CBORTag(16, {}), "Invalid Encrypt0 format.", ), ( cbor2.CBORTag(16, []), "Invalid Encrypt0 format.", ), ( cbor2.CBORTag(16, 123), "Invalid Encrypt0 format.", ), ( cbor2.CBORTag(16, [b"", b"invalid byte data", b""]), "unprotected header should be dict.", ), ( cbor2.CBORTag(16, [b"", "invalid string data", b""]), "unprotected header should be dict.", ), ( cbor2.CBORTag(16, [b"", [], b""]), "unprotected header should be dict.", ), ( cbor2.CBORTag(16, [b"", 123, b""]), "unprotected header should be dict.", ), ( cbor2.dumps(CBORTag(96, [])), "Invalid Encrypt format.", ), ( cbor2.dumps(CBORTag(96, {})), "Invalid Encrypt format.", ), ( cbor2.dumps(CBORTag(96, b"")), "Invalid Encrypt format.", ), ( cbor2.dumps(CBORTag(96, 123)), "Invalid Encrypt format.", ), ( cbor2.dumps(CBORTag(96, [b"", b"", b""])), "Invalid Encrypt format.", ), ( cbor2.dumps(CBORTag(96, [b"", b"", b"", [b""]])), "unprotected header should be dict.", ), ( cbor2.CBORTag(17, "invalid_string_data"), "Invalid MAC0 format.", ), ( cbor2.CBORTag(17, {}), "Invalid MAC0 format.", ), ( cbor2.CBORTag(17, []), "Invalid MAC0 format.", ), ( cbor2.CBORTag(17, 123), "Invalid MAC0 format.", ), ( cbor2.CBORTag(97, "invalid_string_data"), "Invalid MAC format.", ), ( cbor2.CBORTag(97, {}), "Invalid MAC format.", ), ( cbor2.CBORTag(97, []), "Invalid MAC format.", ), ( cbor2.CBORTag(97, 123), "Invalid MAC format.", ), ( cbor2.CBORTag(18, "invalid_string_data"), "Invalid Signature1 format.", ), ( cbor2.CBORTag(18, {}), "Invalid Signature1 format.", ), ( cbor2.CBORTag(18, []), "Invalid Signature1 format.", ), ( cbor2.CBORTag(18, 123), "Invalid Signature1 format.", ), ( cbor2.dumps(CBORTag(98, [])), "Invalid Signature format.", ), ( cbor2.dumps(CBORTag(98, {})), "Invalid Signature format.", ), ( cbor2.dumps(CBORTag(98, b"")), "Invalid Signature format.", ), ( cbor2.dumps(CBORTag(98, 123)), "Invalid Signature format.", ), ( cbor2.dumps(CBORTag(98, [b"", b"", b"", b""])), "unprotected header should be dict.", ), ( cbor2.dumps(CBORTag(98, [b"", b"", b"", [b""]])), "unprotected header should be dict.", ), ( cbor2.dumps(CBORTag(98, [b"", {}, b"", b""])), "Invalid Signature format.", ), ( cbor2.dumps(CBORTag(98, [b"", {}, b"", [b""]])), "Invalid Signature format.", ), ( cbor2.dumps(CBORTag(98, [b"", {}, b"", [[b"", b"", b""]]])), "unprotected header in signature structure should be dict.", ), ], ) def test_cose_decode_with_invalid_data(self, ctx, invalid, msg): with open(key_path("public_key_es256.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="01") with pytest.raises(ValueError) as err: ctx.decode(invalid, public_key) pytest.fail("decode should fail.") assert msg in str(err.value) def test_cose_decode_mac0_without_key_and_materials(self, ctx): key = COSEKey.from_symmetric_key(alg="HS256") encoded = cwt.encode({"iss": "coap://as.example"}, key) with pytest.raises(ValueError) as err: ctx.decode(encoded, b"") pytest.fail("decode should fail.") assert "key in keys should have COSEKeyInterface." in str(err.value) def test_cose_decode_mac0_with_multiple_keys_without_kid(self, ctx): key1 = COSEKey.from_symmetric_key(alg="HS256") key2 = COSEKey.from_symmetric_key(alg="HS256") encoded = ctx.encode_and_mac(b"Hello world!", key1) decoded = ctx.decode(encoded, [key1, key2]) assert decoded == b"Hello world!" def test_cose_decode_mac0_with_different_multiple_keys(self, ctx): key1 = COSEKey.from_symmetric_key(alg="HS256") key2 = COSEKey.from_symmetric_key(alg="HS256") key3 = COSEKey.from_symmetric_key(alg="HS256") encoded = ctx.encode_and_mac(b"Hello world!", key1) with pytest.raises(VerifyError) as err: ctx.decode(encoded, [key2, key3]) pytest.fail("decode() should fail.") assert "Failed to compare digest." in str(err.value) def test_cose_decode_mac0_with_different_multiple_keys_2(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) key1 = COSEKey.from_symmetric_key(alg="HS256", kid="01") key2 = COSEKey.from_symmetric_key(alg="HS256") key3 = COSEKey.from_symmetric_key(alg="HS256") encoded = ctx.encode_and_mac(b"Hello world!", key1) with pytest.raises(ValueError) as err: ctx.decode(encoded, [key2, key3]) pytest.fail("decode() should fail.") assert "key is not found." in str(err.value) def test_cose_decode_mac0_with_multiple_kid(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) key1 = COSEKey.from_symmetric_key(alg="HS256", kid="01") key2 = COSEKey.from_symmetric_key(alg="HS256", kid="01") key3 = COSEKey.from_symmetric_key(alg="HS256", kid="02") encoded = ctx.encode_and_mac(b"Hello world!", key2) assert b"Hello world!" == ctx.decode(encoded, [key1, key2, key3]) def test_cose_decode_mac_with_multiple_keys_without_kid(self, ctx): key = COSEKey.from_symmetric_key(alg="HS256") material1 = base64.urlsafe_b64encode(token_bytes(16)).decode() material2 = base64.urlsafe_b64encode(token_bytes(16)).decode() material3 = base64.urlsafe_b64encode(token_bytes(16)).decode() r1 = Recipient.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material1 }) r2 = Recipient.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material2 }) r1.apply(key) r2.apply(key) encoded = ctx.encode_and_mac(b"Hello world!", key, recipients=[r2, r1]) shared_key1 = COSEKey.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material1 }) shared_key3 = COSEKey.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material3 }) assert b"Hello world!" == ctx.decode(encoded, keys=[shared_key3, shared_key1]) def test_cose_decode_mac_with_multiple_keys_with_verify_kid(self): ctx = COSE.new(alg_auto_inclusion=True, verify_kid=True) key = COSEKey.from_symmetric_key(alg="HS256") material1 = base64.urlsafe_b64encode(token_bytes(16)).decode() material2 = base64.urlsafe_b64encode(token_bytes(16)).decode() material3 = base64.urlsafe_b64encode(token_bytes(16)).decode() r1 = Recipient.from_jwk({ "kid": "01", "kty": "oct", "alg": "A128KW", "k": material1 }) r2 = Recipient.from_jwk({ "kid": "02", "kty": "oct", "alg": "A128KW", "k": material2 }) r1.apply(key) r2.apply(key) encoded = ctx.encode_and_mac(b"Hello world!", key, recipients=[r2, r1]) shared_key1 = COSEKey.from_jwk({ "kid": "01", "kty": "oct", "alg": "A128KW", "k": material1 }) shared_key3 = COSEKey.from_jwk({ "kid": "03", "kty": "oct", "alg": "A128KW", "k": material3 }) assert b"Hello world!" == ctx.decode(encoded, keys=[shared_key3, shared_key1]) def test_cose_decode_mac_with_multiple_keys_with_verify_kid_and_protected_kid( self): ctx = COSE.new(alg_auto_inclusion=True, verify_kid=True) key = COSEKey.from_symmetric_key(alg="HS256") material1 = base64.urlsafe_b64encode(token_bytes(16)).decode() material2 = base64.urlsafe_b64encode(token_bytes(16)).decode() material3 = base64.urlsafe_b64encode(token_bytes(16)).decode() shared_key1 = COSEKey.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material1 }) shared_key2 = COSEKey.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material2 }) shared_key3 = COSEKey.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material3 }) r1 = Recipient.new(protected={1: -3, 4: b"01"}, sender_key=shared_key1) r2 = Recipient.new(protected={1: -3, 4: b"02"}, sender_key=shared_key2) r1.apply(key) r2.apply(key) encoded = ctx.encode_and_mac(b"Hello world!", key, recipients=[r2, r1]) shared_key1 = COSEKey.from_jwk({ "kid": "01", "kty": "oct", "alg": "A128KW", "k": material1 }) shared_key3 = COSEKey.from_jwk({ "kid": "03", "kty": "oct", "alg": "A128KW", "k": material3 }) assert b"Hello world!" == ctx.decode(encoded, keys=[shared_key3, shared_key1]) def test_cose_decode_mac_with_multiple_keys_without_kid_with_verify_kid( self): ctx = COSE.new(alg_auto_inclusion=True, verify_kid=True) key = COSEKey.from_symmetric_key(alg="HS256") material1 = base64.urlsafe_b64encode(token_bytes(16)).decode() material2 = base64.urlsafe_b64encode(token_bytes(16)).decode() material3 = base64.urlsafe_b64encode(token_bytes(16)).decode() r1 = Recipient.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material1 }) r2 = Recipient.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material2 }) r1.apply(key) r2.apply(key) encoded = ctx.encode_and_mac(b"Hello world!", key, recipients=[r2, r1]) shared_key1 = COSEKey.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material1 }) shared_key3 = COSEKey.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material3 }) with pytest.raises(ValueError) as err: ctx.decode(encoded, keys=[shared_key3, shared_key1]) pytest.fail("decode() should fail.") assert "kid should be specified in recipient." in str(err.value) def test_cose_decode_mac_with_multiple_keys_without_recipient_kid_with_verify_kid( self, ): ctx = COSE.new(alg_auto_inclusion=True, verify_kid=True) key = COSEKey.from_symmetric_key(alg="HS256") material1 = base64.urlsafe_b64encode(token_bytes(16)).decode() material2 = base64.urlsafe_b64encode(token_bytes(16)).decode() material3 = base64.urlsafe_b64encode(token_bytes(16)).decode() r1 = Recipient.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material1 }) r2 = Recipient.from_jwk({ "kty": "oct", "alg": "A128KW", "k": material2 }) r1.apply(key) r2.apply(key) encoded = ctx.encode_and_mac(b"Hello world!", key, recipients=[r2, r1]) shared_key1 = COSEKey.from_jwk({ "kid": "01", "kty": "oct", "alg": "A128KW", "k": material1 }) shared_key3 = COSEKey.from_jwk({ "kid": "02", "kty": "oct", "alg": "A128KW", "k": material3 }) with pytest.raises(ValueError) as err: ctx.decode(encoded, keys=[shared_key3, shared_key1]) pytest.fail("decode() should fail.") assert "kid should be specified in recipient." in str(err.value) def test_cose_decode_mac_with_different_multiple_keys(self, ctx): ctx = COSE.new(alg_auto_inclusion=True, verify_kid=True) key = COSEKey.from_symmetric_key(alg="HS256") material1 = base64.urlsafe_b64encode(token_bytes(16)).decode() material2 = base64.urlsafe_b64encode(token_bytes(16)).decode() material3 = base64.urlsafe_b64encode(token_bytes(16)).decode() r2 = Recipient.from_jwk({ "kid": "03", "kty": "oct", "alg": "A128KW", "k": material2 }) r2.apply(key) encoded = ctx.encode_and_mac(b"Hello world!", key, recipients=[r2]) shared_key1 = COSEKey.from_jwk({ "kid": "01", "kty": "oct", "alg": "A128KW", "k": material1 }) shared_key3 = COSEKey.from_jwk({ "kid": "03", "kty": "oct", "alg": "A128KW", "k": material3 }) with pytest.raises(DecodeError) as err: ctx.decode(encoded, keys=[shared_key1, shared_key3]) pytest.fail("decode() should fail.") assert "Failed to decode key." in str(err.value) def test_cose_decode_mac_with_different_multiple_keys_2(self): ctx = COSE.new(alg_auto_inclusion=True, verify_kid=True) key = COSEKey.from_symmetric_key(alg="HS256") material1 = base64.urlsafe_b64encode(token_bytes(16)).decode() material2 = base64.urlsafe_b64encode(token_bytes(16)).decode() material3 = base64.urlsafe_b64encode(token_bytes(16)).decode() r2 = Recipient.from_jwk({ "kid": "03", "kty": "oct", "alg": "A128KW", "k": material2 }) r2.apply(key) encoded = ctx.encode_and_mac(b"Hello world!", key, recipients=[r2]) shared_key1 = COSEKey.from_jwk({ "kid": "01", "kty": "oct", "alg": "A128KW", "k": material1 }) shared_key3 = COSEKey.from_jwk({ "kid": "02", "kty": "oct", "alg": "A128KW", "k": material3 }) with pytest.raises(ValueError) as err: ctx.decode(encoded, keys=[shared_key1, shared_key3]) pytest.fail("decode() should fail.") assert "key is not found." in str(err.value) def test_cose_decode_mac_with_multiple_kid(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) key1 = COSEKey.from_symmetric_key(alg="HS256", kid="01") key2 = COSEKey.from_symmetric_key(alg="HS256", kid="01") key3 = COSEKey.from_symmetric_key(alg="HS256", kid="02") encoded = ctx.encode_and_mac(b"Hello world!", key2) decoded = ctx.decode(encoded, [key1, key2, key3]) assert decoded == b"Hello world!" def test_cose_decode_encrypt0_with_multiple_keys_without_kid(self, ctx): key1 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305") key2 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305") encoded = ctx.encode_and_encrypt(b"Hello world!", key1) decoded = ctx.decode(encoded, [key2, key1]) assert decoded == b"Hello world!" def test_cose_decode_encrypt0_with_different_multiple_keys(self, ctx): key1 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305") key2 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305") key3 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305") encoded = ctx.encode_and_encrypt(b"Hello world!", key1) with pytest.raises(DecodeError) as err: ctx.decode(encoded, [key2, key3]) pytest.fail("decode() should fail.") assert "Failed to decrypt." in str(err.value) def test_cose_decode_encrypt0_with_different_multiple_keys_2(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) key1 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01") key2 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305") key3 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305") encoded = ctx.encode_and_encrypt(b"Hello world!", key1) with pytest.raises(ValueError) as err: ctx.decode(encoded, [key2, key3]) pytest.fail("decode() should fail.") assert "key is not found." in str(err.value) def test_cose_decode_encrypt0_with_multiple_kid(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) key1 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01") key2 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01") key3 = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="02") encoded = ctx.encode_and_encrypt(b"Hello world!", key2) decoded = ctx.decode(encoded, [key1, key2, key3]) assert decoded == b"Hello world!" def test_cose_decode_encrypt_with_multiple_keys_with_verify_kid(self): ctx = COSE.new(alg_auto_inclusion=True, verify_kid=True) key = COSEKey.from_symmetric_key(alg="A128GCM") material1 = base64.urlsafe_b64encode(token_bytes(16)).decode() material2 = base64.urlsafe_b64encode(token_bytes(16)).decode() material3 = base64.urlsafe_b64encode(token_bytes(16)).decode() r1 = Recipient.from_jwk({ "kid": "01", "kty": "oct", "alg": "A128KW", "k": material1 }) r2 = Recipient.from_jwk({ "kid": "02", "kty": "oct", "alg": "A128KW", "k": material2 }) r1.apply(key) r2.apply(key) encoded = ctx.encode_and_encrypt(b"Hello world!", key, recipients=[r2, r1]) shared_key1 = COSEKey.from_jwk({ "kid": "01", "kty": "oct", "alg": "A128KW", "k": material1 }) shared_key3 = COSEKey.from_jwk({ "kid": "03", "kty": "oct", "alg": "A128KW", "k": material3 }) assert b"Hello world!" == ctx.decode(encoded, keys=[shared_key3, shared_key1]) def test_cose_decode_signature1_with_multiple_keys_without_kid(self, ctx): with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read()) with open(key_path("public_key_ed25519.pem")) as key_file: key2 = COSEKey.from_pem(key_file.read()) with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read()) encoded = ctx.encode_and_sign(b"Hello world!", private_key) decoded = ctx.decode(encoded, [key1, key2]) assert decoded == b"Hello world!" def test_cose_decode_signature1_with_ca_certs_without_kid(self): with open(key_path("cert_es256.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read()) with open(key_path("private_key_cert_es256.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read()) ctx = COSE.new(alg_auto_inclusion=True, ca_certs=key_path("cacert.pem")) encoded = ctx.encode_and_sign(b"Hello world!", private_key) decoded = ctx.decode(encoded, [public_key]) assert decoded == b"Hello world!" def test_cose_decode_signature1_with_different_multiple_keys(self, ctx): with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read()) # with open(key_path("public_key_ed25519.pem")) as key_file: # key2 = COSEKey.from_pem(key_file.read()) with open(key_path("public_key_ed448.pem")) as key_file: key3 = COSEKey.from_pem(key_file.read()) with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read()) encoded = ctx.encode_and_sign(b"Hello world!", private_key) with pytest.raises(VerifyError) as err: ctx.decode(encoded, [key1, key3]) pytest.fail("decode() should fail.") assert "Failed to verify." in str(err.value) def test_cose_decode_signature1_with_different_multiple_keys_2(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read()) # with open(key_path("public_key_ed25519.pem")) as key_file: # key2 = COSEKey.from_pem(key_file.read()) with open(key_path("public_key_ed448.pem")) as key_file: key3 = COSEKey.from_pem(key_file.read()) with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="01") encoded = ctx.encode_and_sign(b"Hello world!", private_key) with pytest.raises(ValueError) as err: ctx.decode(encoded, [key1, key3]) pytest.fail("decode() should fail.") assert "key is not found." in str(err.value) def test_cose_decode_signature1_with_multiple_kid(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read(), kid="01") with open(key_path("public_key_ed25519.pem")) as key_file: key2 = COSEKey.from_pem(key_file.read(), kid="01") with open(key_path("public_key_ed448.pem")) as key_file: key3 = COSEKey.from_pem(key_file.read(), kid="02") with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="01") encoded = ctx.encode_and_sign(b"Hello world!", private_key) decoded = ctx.decode(encoded, [key1, key2, key3]) assert decoded == b"Hello world!" def test_cose_decode_signature1_with_same_kid_bound_to_different_key(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read(), kid="01") with open(key_path("public_key_ed25519.pem")) as key_file: key2 = COSEKey.from_pem(key_file.read(), kid="02") with open(key_path("public_key_ed448.pem")) as key_file: key3 = COSEKey.from_pem(key_file.read(), kid="03") with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="01") encoded = ctx.encode_and_sign(b"Hello world!", private_key) with pytest.raises(VerifyError) as err: ctx.decode(encoded, [key1, key2, key3]) pytest.fail("decode() should fail.") assert "Failed to verify." in str(err.value) def test_cose_decode_signature1_with_key_not_found(self, ctx): with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read(), kid="01") with open(key_path("public_key_ed25519.pem")) as key_file: key2 = COSEKey.from_pem(key_file.read(), kid="02") with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="03") encoded = cwt.encode({"iss": "coap://as.example"}, private_key) with pytest.raises(ValueError) as err: ctx.decode(encoded, [key1, key2]) pytest.fail("decode should fail.") assert "key is not found." in str(err.value) def test_cose_decode_signature_with_multiple_keys_without_kid(self, ctx): with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read()) with open(key_path("public_key_ed25519.pem")) as key_file: key2 = COSEKey.from_pem(key_file.read()) with open(key_path("private_key_ed25519.pem")) as key_file: signer = Signer.from_pem(key_file.read()) encoded = ctx.encode_and_sign(b"Hello world!", signers=[signer]) decoded = ctx.decode(encoded, [key1, key2]) assert decoded == b"Hello world!" def test_cose_decode_signature_with_different_multiple_keys(self, ctx): with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read()) # with open(key_path("public_key_ed25519.pem")) as key_file: # key2 = COSEKey.from_pem(key_file.read()) with open(key_path("public_key_ed448.pem")) as key_file: key3 = COSEKey.from_pem(key_file.read()) with open(key_path("private_key_ed25519.pem")) as key_file: signer = Signer.from_pem(key_file.read()) encoded = ctx.encode_and_sign(b"Hello world!", signers=[signer]) with pytest.raises(VerifyError) as err: ctx.decode(encoded, [key1, key3]) pytest.fail("decode() should fail.") assert "Failed to verify." in str(err.value) def test_cose_decode_signature_with_different_multiple_keys_2(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read()) # with open(key_path("public_key_ed25519.pem")) as key_file: # key2 = COSEKey.from_pem(key_file.read()) with open(key_path("public_key_ed448.pem")) as key_file: key3 = COSEKey.from_pem(key_file.read()) with open(key_path("private_key_ed25519.pem")) as key_file: signer = Signer.from_pem(key_file.read(), kid="01") encoded = ctx.encode_and_sign(b"Hello world!", signers=[signer]) with pytest.raises(ValueError) as err: ctx.decode(encoded, [key1, key3]) pytest.fail("decode() should fail.") assert "key is not found." in str(err.value) def test_cose_decode_signature_with_multiple_kid(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read(), kid="01") with open(key_path("public_key_ed25519.pem")) as key_file: key2 = COSEKey.from_pem(key_file.read(), kid="01") with open(key_path("public_key_ed448.pem")) as key_file: key3 = COSEKey.from_pem(key_file.read(), kid="02") with open(key_path("private_key_ed25519.pem")) as key_file: signer = Signer.from_pem(key_file.read(), kid="01") encoded = ctx.encode_and_sign(b"Hello world!", signers=[signer]) decoded = ctx.decode(encoded, [key1, key2, key3]) assert decoded == b"Hello world!" def test_cose_decode_signature_with_same_kid_bound_to_different_key(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read(), kid="01") with open(key_path("public_key_ed25519.pem")) as key_file: key2 = COSEKey.from_pem(key_file.read(), kid="02") with open(key_path("public_key_ed448.pem")) as key_file: key3 = COSEKey.from_pem(key_file.read(), kid="03") with open(key_path("private_key_ed25519.pem")) as key_file: signer = Signer.from_pem(key_file.read(), kid="01") encoded = ctx.encode_and_sign(b"Hello world!", signers=[signer]) with pytest.raises(VerifyError) as err: ctx.decode(encoded, [key1, key2, key3]) pytest.fail("decode() should fail.") assert "Failed to verify." in str(err.value) def test_cose_decode_signature_with_key_not_found(self): ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True) with open(key_path("public_key_es256.pem")) as key_file: key1 = COSEKey.from_pem(key_file.read(), kid="01") with open(key_path("public_key_ed25519.pem")) as key_file: key2 = COSEKey.from_pem(key_file.read(), kid="02") with open(key_path("private_key_ed25519.pem")) as key_file: signer = Signer.from_pem(key_file.read(), kid="03") encoded = ctx.encode_and_sign(b"Hello world!", signers=[signer]) with pytest.raises(ValueError) as err: ctx.decode(encoded, [key1, key2]) pytest.fail("decode should fail.") assert "key is not found." in str(err.value) def test_cose_decode_ecdh_es_hkdf_256_without_context(self): with open(key_path("public_key_es256.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="01") recipient = Recipient.from_jwk({ "kty": "EC", "crv": "P-256", "alg": "ECDH-ES+HKDF-256" }) enc_key = recipient.apply(recipient_key=public_key, context={"alg": "A128GCM"}) ctx = COSE.new(alg_auto_inclusion=True) encoded = ctx.encode_and_encrypt( b"This is the content.", key=enc_key, recipients=[recipient], ) with open(key_path("private_key_es256.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="01") with pytest.raises(ValueError) as err: ctx.decode(encoded, private_key) pytest.fail("decode should fail.") assert "context should be set." in str(err.value) def test_cose_decode_ecdh_aes_key_wrap_without_context(self): with open(key_path("public_key_es256.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="01") enc_key = COSEKey.from_symmetric_key(alg="A128GCM") recipient = Recipient.from_jwk({ "kty": "EC", "crv": "P-256", "alg": "ECDH-ES+A128KW" }) recipient.apply(enc_key, recipient_key=public_key, context={"alg": "A128GCM"}) ctx = COSE.new(alg_auto_inclusion=True) encoded = ctx.encode_and_encrypt( b"This is the content.", key=enc_key, recipients=[recipient], ) with open(key_path("private_key_es256.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="01") with pytest.raises(ValueError) as err: ctx.decode(encoded, private_key) pytest.fail("decode should fail.") assert "context should be set." in str(err.value)
def mk_cipherlink(t, val): if not val: return None return cbor2.CBORTag(GG_TAG_CIPHERLINK, t + val)
def cborify(encoder, o): """Helper function to convert non-native types to CBOR serializable values.""" if isinstance(o, datetime.timedelta): o: datetime.timedelta encoder.encode(cbor.CBORTag(1337, o.total_seconds()))