diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e95893ae98..cacaf51495a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - The `read_ledger.py` tool now has a `--quiet` option which avoids printing anything per-transaction, as well as other performance improvements, which should make it more useful in verifying the integrity of large ledgers. +- COSE signatures now set a kid that is a hex-encoded SHA-256 of the DER representation of the key used to produce them (#6703). ## [6.0.0-dev8] diff --git a/cddl/ccf-merkle-tree-cose-signature.cddl b/cddl/ccf-merkle-tree-cose-signature.cddl index 7ad74096b34..60171302ff0 100644 --- a/cddl/ccf-merkle-tree-cose-signature.cddl +++ b/cddl/ccf-merkle-tree-cose-signature.cddl @@ -13,7 +13,7 @@ unprotected-headers = { protected-headers = { &(alg: 1) => int, ; signing algoritm ID, as per RFC8152 - &(kid: 4) => bstr, ; signing key hash + &(kid: 4) => bstr, ; Opaque key identifier, hex-encoded SHA-256 of the public key encoded as DER. &(cwt: 15) => cwt-map, ; CWT claims, as per RFC8392 &(vds: 395) => int, ; verifiable data structure, as per COSE Receipts (draft) RFC (https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs/) "ccf.v1" => ccf-map ; a set of CCF-specific parameters diff --git a/python/src/ccf/cose.py b/python/src/ccf/cose.py index 573e2c13f44..553dbff90f3 100644 --- a/python/src/ccf/cose.py +++ b/python/src/ccf/cose.py @@ -211,9 +211,12 @@ def verify_receipt( # Extract the expected KID from the public key used for verification, # and check it against the value set in the COSE header before using # it to verify the proofs. - expected_kid = sha256( - key.public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo) - ).digest() + expected_kid = ( + sha256(key.public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)) + .digest() + .hex() + .encode() + ) receipt = Sign1Message.decode(receipt_bytes) cose_key = from_cryptography_eckey_obj(key) assert receipt.phdr[pycose.headers.KID] == expected_kid diff --git a/src/crypto/openssl/cose_sign.cpp b/src/crypto/openssl/cose_sign.cpp index 5b6f421181e..047e117e13e 100644 --- a/src/crypto/openssl/cose_sign.cpp +++ b/src/crypto/openssl/cose_sign.cpp @@ -200,7 +200,7 @@ namespace ccf::crypto } std::shared_ptr cose_params_int_bytes( - int64_t key, const std::vector& value) + int64_t key, std::span value) { const size_t args_size = sizeof(key) + value.size() + +extra_size_for_int_tag + extra_size_for_seq_tag; @@ -213,7 +213,7 @@ namespace ccf::crypto } std::shared_ptr cose_params_string_bytes( - const std::string& key, const std::vector& value) + const std::string& key, std::span value) { const size_t args_size = key.size() + value.size() + extra_size_for_seq_tag + extra_size_for_seq_tag; diff --git a/src/crypto/openssl/cose_sign.h b/src/crypto/openssl/cose_sign.h index a8513cca91b..5300962ca45 100644 --- a/src/crypto/openssl/cose_sign.h +++ b/src/crypto/openssl/cose_sign.h @@ -129,10 +129,10 @@ namespace ccf::crypto const std::string& key, const std::string& value); std::shared_ptr cose_params_int_bytes( - int64_t key, const std::vector& value); + int64_t key, std::span value); std::shared_ptr cose_params_string_bytes( - const std::string& key, const std::vector& value); + const std::string& key, std::span value); class COSEParametersPair : public COSEParametersFactory { diff --git a/src/node/history.h b/src/node/history.h index d0a91cb3f11..0dcd0fd420a 100644 --- a/src/node/history.h +++ b/src/node/history.h @@ -379,8 +379,8 @@ namespace ccf constexpr int64_t vds_merkle_tree = 2; const auto& service_key_der = service_kp.public_key_der(); - std::vector kid(SHA256_DIGEST_LENGTH); - SHA256(service_key_der.data(), service_key_der.size(), kid.data()); + auto kid = ccf::crypto::Sha256Hash(service_key_der).hex_str(); + std::span kid_span{(uint8_t*)kid.data(), kid.size()}; const auto time_since_epoch = std::chrono::duration_cast( @@ -415,7 +415,7 @@ namespace ccf const auto pheaders = { // Key digest ccf::crypto::cose_params_int_bytes( - ccf::crypto::COSE_PHEADER_KEY_ID, kid), + ccf::crypto::COSE_PHEADER_KEY_ID, kid_span), // VDS ccf::crypto::cose_params_int_int( ccf::crypto::COSE_PHEADER_KEY_VDS, vds_merkle_tree),