def test_key_builder_from_pem_with_kid(self, kid, expected): with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid=kid) with open(key_path("public_key_ed25519.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid=kid) assert private_key.kid == expected assert public_key.kid == expected
def test_key_builder_from_pem_private_with_invalid_key_ops( self, invalid, msg): with open(key_path("private_key_ed25519.pem")) as key_file: with pytest.raises(ValueError) as err: COSEKey.from_pem(key_file.read(), key_ops=invalid) pytest.fail("from_pem should fail.") assert msg in str(err.value)
def test_sample_readme_cwt_with_user_defined_claims(self): with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="01") token = cwt.encode( { 1: "coaps://as.example", # iss 2: "dajiaji", # sub 7: b"123", # cti -70001: "foo", -70002: ["bar"], -70003: {"baz": "qux"}, -70004: 123, }, private_key, ) with open(key_path("public_key_ed25519.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="01") raw = cwt.decode(token, public_key) assert raw[-70001] == "foo" assert isinstance(raw[-70002], list) assert raw[-70002][0] == "bar" assert isinstance(raw[-70003], dict) assert raw[-70003]["baz"] == "qux" assert raw[-70004] == 123 readable = Claims.new(raw) assert readable.get(-70001) == "foo" assert readable.get(-70002)[0] == "bar" assert readable.get(-70003)["baz"] == "qux" assert readable.get(-70004) == 123
def test_sample_readme_cwt_with_pop_cose_key(self): with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="issuer-01") with open(key_path("public_key_es256.pem")) as key_file: pop_key = COSEKey.from_pem(key_file.read()) token = cwt.encode( { 1: "coaps://as.example", # iss 2: "dajiaji", # sub 7: b"123", # cti 8: { # cnf 1: pop_key.to_dict(), }, }, private_key, ) with open(key_path("public_key_ed25519.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="issuer-01") decoded = cwt.decode(token, public_key) assert 8 in decoded and isinstance(decoded[8], dict) assert 1 in decoded[8] and isinstance(decoded[8][1], dict) extracted = COSEKey.new(decoded[8][1]) assert extracted.kty == 2 # EC2 assert extracted.crv == 1 # P-256
def test_sample_readme_cwt_with_pop_encrypted_cose_key(self): with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="issuer-01") enc_key = COSEKey.from_symmetric_key( "a-client-secret-of-cwt-recipient", # Just 32 bytes! alg="ChaCha20/Poly1305", kid="presenter-01", ) pop_key = COSEKey.from_symmetric_key( "a-client-secret-of-cwt-presenter", alg="HMAC 256/256", ) token = cwt.encode( { 1: "coaps://as.example", # iss 2: "dajiaji", # sub 7: b"123", # cti 8: { # cnf 2: EncryptedCOSEKey.from_cose_key(pop_key, enc_key), }, }, private_key, ) with open(key_path("public_key_ed25519.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="issuer-01") decoded = cwt.decode(token, public_key) assert 8 in decoded and isinstance(decoded[8], dict) assert 2 in decoded[8] and isinstance(decoded[8][2], list) extracted = EncryptedCOSEKey.to_cose_key(decoded[8][2], enc_key) assert extracted.kty == 4 # Symmetric assert extracted.alg == 5 # HMAC 256/256 assert extracted.key == b"a-client-secret-of-cwt-presenter"
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 test_sample_readme_cwt_with_pop_encrypted_cose_key_readable(self): with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="issuer-01") enc_key = COSEKey.from_symmetric_key( "a-client-secret-of-cwt-recipient", # Just 32 bytes! alg="ChaCha20/Poly1305", kid="presenter-01", ) pop_key = COSEKey.from_symmetric_key( "a-client-secret-of-cwt-presenter", alg="HMAC 256/256", ) token = cwt.encode( { "iss": "coaps://as.example", "sub": "dajiaji", "cti": "123", "cnf": { # 'eck'(Encrypted Cose Key) is a keyword defined by this library. "eck": EncryptedCOSEKey.from_cose_key(pop_key, enc_key), }, }, private_key, ) with open(key_path("public_key_ed25519.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="issuer-01") decoded = cwt.decode(token, public_key) assert 8 in decoded and isinstance(decoded[8], dict) assert 2 in decoded[8] and isinstance(decoded[8][2], list) c = Claims.new(decoded) extracted = EncryptedCOSEKey.to_cose_key(c.cnf, enc_key) assert extracted.kty == 4 # Symmetric assert extracted.alg == 5 # HMAC 256/256 assert extracted.key == b"a-client-secret-of-cwt-presenter"
def test_key_builder_from_pem_okp_with_invalid_alg(self, invalid_alg): with open(key_path("private_key_ed25519.pem")) as key_file: with pytest.raises(ValueError) as err: COSEKey.from_pem(key_file.read(), alg=invalid_alg) pytest.fail("from_pem() should fail.") assert f"Unsupported or unknown alg for OKP: {invalid_alg}." in str( err.value)
def test_key_builder_from_pem(self, private_key_path, public_key_path): try: with open(key_path(private_key_path)) as key_file: COSEKey.from_pem(key_file.read()) with open(key_path(public_key_path)) as key_file: COSEKey.from_pem(key_file.read()) except Exception: pytest.fail("from_pem should not fail.")
def test_sample_readme_signed_cwt_ps256(self): with open(key_path("private_key_rsa.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), alg="PS256", kid="01") token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key) with open(key_path("public_key_rsa.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), alg="PS256", kid="01") decoded = cwt.decode(token, public_key) assert 1 in decoded and decoded[1] == "coaps://as.example"
def test_key_builder_from_pem_with_alg(self, private_key_path, public_key_path): try: with open(key_path(private_key_path)) as key_file: COSEKey.from_pem(key_file.read(), alg="ECDH-SS+HKDF-256") with open(key_path(public_key_path)) as key_file: COSEKey.from_pem(key_file.read(), alg="ECDH-SS+HKDF-256") except Exception: pytest.fail("from_pem should not fail.")
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_sample_readme_nested_cwt(self): with open(key_path("private_key_es256.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="01") token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key) enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="02") nested = cwt.encode(token, enc_key) with open(key_path("public_key_es256.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="01") decoded = cwt.decode(nested, [enc_key, public_key]) assert 1 in decoded and decoded[1] == "coaps://as.example"
def test_sample_readme_signed_cwt_ed25519_old(self): with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="01") encoded = cwt.encode_and_sign( Claims.from_json({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}), private_key, ) with open(key_path("public_key_ed25519.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="01") decoded = cwt.decode(encoded, public_key) assert 1 in decoded and decoded[1] == "coaps://as.example"
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_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_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_sample_readme_cwt_with_pop_jwk(self): # issuer: with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="issuer-01") token = cwt.encode( { "iss": "coaps://as.example", "sub": "dajiaji", "cti": "123", "cnf": { "jwk": { "kty": "OKP", "use": "sig", "crv": "Ed25519", "kid": "01", "x": "2E6dX83gqD_D0eAmqnaHe1TC1xuld6iAKXfw2OVATr0", "alg": "EdDSA", }, }, }, private_key, ) # presenter: msg = b"could-you-sign-this-message?" # Provided by recipient. pop_key_private = COSEKey.from_jwk( { "kty": "OKP", "d": "L8JS08VsFZoZxGa9JvzYmCWOwg7zaKcei3KZmYsj7dc", "use": "sig", "crv": "Ed25519", "kid": "01", "x": "2E6dX83gqD_D0eAmqnaHe1TC1xuld6iAKXfw2OVATr0", "alg": "EdDSA", } ) sig = pop_key_private.sign(msg) # recipient: with open(key_path("public_key_ed25519.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="issuer-01") decoded = cwt.decode(token, public_key) assert 8 in decoded and isinstance(decoded[8], dict) assert 1 in decoded[8] and isinstance(decoded[8][1], dict) c = Claims.new(decoded) extracted = COSEKey.new(c.cnf) try: extracted.verify(msg, sig) except Exception: pytest.fail("verify should not fail.")
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_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_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_sample_readme_nested_cwt_without_kid(self): enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305") with open(key_path("private_key_es256.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read()) ctx = CWT.new() ctx.cose.verify_kid = False token = ctx.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key) nested = ctx.encode(token, enc_key) with open(key_path("public_key_es256.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read()) decoded = ctx.decode(nested, [enc_key, public_key]) assert 1 in decoded and decoded[1] == "coaps://as.example"
def refresh_trustlist(self): self._dscs = [] self._trustlist = [] # Get a trust-list signer certificate. r = requests.get(self._base_url + "/cert") if r.status_code != 200: raise Exception(f"Received {r.status_code} from /cert") key = r.text cose_key = COSEKey.from_pem(key) # Get DSCs r = requests.get(self._base_url + "/trust-list") if r.status_code != 200: raise Exception(f"Received {r.status_code} from /trust-list") decoded = jwt.decode( r.text, cose_key.key, algorithms=["ES256"], options={"verify_aud": False}, ) for v in decoded["dsc_trust_list"].values(): for k in v["keys"]: if "use" in k and k["use"] == "enc": # Workaround for Swedish DSC. del k["use"] if k["kty"] == "RSA": k["alg"] = "PS256" self._dscs.append(COSEKey.from_jwk(k)) self._trustlist.append(k) # Update trustlist store. with open(self._trustlist_store_path, "w") as f: json.dump(self._trustlist, f, indent=4) return
def test_sample_readme_nested_cwt_old(self): with open(key_path("private_key_es256.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="01") encoded = cwt.encode_and_sign( Claims.from_json({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}), private_key, ) nonce = token_bytes(13) mysecret = token_bytes(32) enc_key = COSEKey.from_symmetric_key(mysecret, alg="AES-CCM-16-64-256", kid="02") nested = cwt.encode_and_encrypt(encoded, enc_key, nonce=nonce) with open(key_path("public_key_es256.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="01") decoded = cwt.decode(nested, [enc_key, public_key]) assert 1 in decoded and decoded[1] == "coaps://as.example"
def test_key_builder_from_pem_private_with_key_ops(self, key_ops, expected): with open(key_path("private_key_ed25519.pem")) as key_file: k = COSEKey.from_pem(key_file.read(), key_ops=key_ops) assert len(k.key_ops) == len(key_ops) for ops in k.key_ops: assert ops in expected
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_sample_readme_decode_with_multiple_keys(self): with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="02") token = cwt.encode( { "iss": "coaps://as.example", "sub": "dajiaji", "cti": b"123", }, private_key, ) with open(key_path("public_key_es256.pem")) as key_file: public_key_1 = COSEKey.from_pem(key_file.read(), kid="01") with open(key_path("public_key_ed25519.pem")) as key_file: public_key_2 = COSEKey.from_pem(key_file.read(), kid="02") decoded = cwt.decode(token, [public_key_1, public_key_2]) assert 1 in decoded and decoded[1] == "coaps://as.example"
def test_sample_readme_cwt_with_pop_kid(self): with open(key_path("private_key_ed25519.pem")) as key_file: private_key = COSEKey.from_pem(key_file.read(), kid="01") token = cwt.encode( { 1: "coaps://as.example", # iss 2: "dajiaji", # sub 7: b"123", # cti 8: { # cnf 3: b"pop-key-id-of-cwt-presenter", }, }, private_key, ) with open(key_path("public_key_ed25519.pem")) as key_file: public_key = COSEKey.from_pem(key_file.read(), kid="01") decoded = cwt.decode(token, public_key) assert 8 in decoded and isinstance(decoded[8], dict) assert 3 in decoded[8] and decoded[8][3] == b"pop-key-id-of-cwt-presenter"
def test_sample_readme_signed_cwt_es256_with_cert_without_intermediates(self): with open(key_path("private_key_cert_es256.pem")) as f: private_key = COSEKey.from_pem(f.read(), kid="P-256-01") with open(key_path("cert_es256_2.json")) as f: public_key = COSEKey.from_jwk(f.read()) token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key) decoder = CWT.new(ca_certs=key_path("cacert.pem")) decoded = decoder.decode(token, public_key) assert 1 in decoded and decoded[1] == "coaps://as.example"