Skip to content

Add support for COSE keys and key sets#712

Open
MarcoPolo wants to merge 3 commits intomarco/pkixfrom
marco/cose
Open

Add support for COSE keys and key sets#712
MarcoPolo wants to merge 3 commits intomarco/pkixfrom
marco/cose

Conversation

@MarcoPolo
Copy link
Copy Markdown
Contributor

See multiformats/multicodec#400 for a detailed motivation.

cc @lidel

MarcoPolo and others added 2 commits April 14, 2026 10:33
Copy link
Copy Markdown
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we need to explicitly require deterministic CBOR variant (details inline)

Comment thread peer-ids/peer-ids.md
Comment on lines +214 to +217
#### COSE Key

The Data field is defined by [Section 7 of RFC
9052](https://www.rfc-editor.org/rfc/rfc9052#section-7).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something I realized in the context of libp2p is that PeerID is a hash of this protobuf.

RFC 9052 COSE_Key is plain CBOR; no deterministic encoding is required. But this spec requires deterministic protobuf encoding so peer IDs are stable.

Problem: Two conformant COSE encoders can produce different Data bytes for the same key, yielding different peer IDs.

Fix: unsure, maybe require RFC 8949 §4.2 Core Deterministic Encoding for COSEKEY*, and reject non-deterministic encodings on decode?

Suggested change
#### COSE Key
The Data field is defined by [Section 7 of RFC
9052](https://www.rfc-editor.org/rfc/rfc9052#section-7).
#### COSE Key
The Data field is defined by [Section 7 of RFC
9052](https://www.rfc-editor.org/rfc/rfc9052#section-7).
The `COSE_Key` MUST be encoded using [CBOR Core Deterministic Encoding (RFC 8949 §4.2)](https://www.rfc-editor.org/rfc/rfc8949#section-4.2). Implementations MUST reject non-deterministic encodings.
Signing and verification for each member are defined by that member's COSE `alg` parameter.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. 9052 has encoding restrictions, but they don't apply to the keys.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also found this RFC: https://datatracker.ietf.org/doc/html/rfc9679 which sounds like what we should use instead of trying to define this.

Comment thread peer-ids/peer-ids.md
Comment on lines +219 to +222
#### COSE KeySet

The Data field is defined by [Section 7 of RFC
9052](https://www.rfc-editor.org/rfc/rfc9052#section-7).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PeerID semantics feel undefined?

Fix: spell out identity and verification rules, or drop COSE_KEY_SET from this PR until the use case is settled.

I think it may be beneficial to keep it to support hybrid keys and signatures, for example when we have both ed25519+something post-quantum secure, and requiring both sigs/handshakes etc.

so maybe:

Suggested change
#### COSE KeySet
The Data field is defined by [Section 7 of RFC
9052](https://www.rfc-editor.org/rfc/rfc9052#section-7).
#### COSE KeySet
The Data field is defined by [Section 7 of RFC
9052](https://www.rfc-editor.org/rfc/rfc9052#section-7).
`COSE_KeySet` is intended for hybrid keys and signatures, for example pairing Ed25519 with a post-quantum scheme so that handshakes and signatures combine both. The following rules apply:
- The `COSE_KeySet` MUST be encoded using [CBOR Core Deterministic Encoding (RFC 8949 §4.2)](https://www.rfc-editor.org/rfc/rfc8949#section-4.2). Implementations MUST reject non-deterministic encodings.
- Members MUST be ordered in ascending lexicographic order of their deterministic CBOR encoding. This ensures independent encoders produce identical bytes for the same set, so the resulting PeerID is stable.
- A `COSE_KeySet` MUST contain at least two members. A single-member set MUST be encoded as `COSE_Key` instead, so the same identity has exactly one on-the-wire representation.
- Each COSE `alg` (and key-type family) MUST appear at most once in the set, removing ambiguity about which member is expected to produce a given signature or handshake component.
- A signature or handshake over a `COSE_KeySet` identity is valid only if **every** member validates its corresponding component. Peers MUST NOT accept proofs that cover only a subset; doing so would defeat the purpose of the hybrid.
Signing and verification for each member are defined by that member's COSE `alg` parameter.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to back out the cose keyset changes. It only gives us an array of cose keys. You could imagine having a array of these protobufs instead.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you mean? Current wire format for libp2p-key does not have repeatable fields, we don't have a spec for libp2p-key[], that is something you would have to invent, and add a new multicodec for it.

RFC for COSE_KeySet already exists, and could provide a backward-compatible way for hardening things with multiple keys (e.g. hybrid ed25519 + post-quantum).

Of course this is just an option, we dont have to support o require hybrid signatures this way, or at all, and can defer to future codes, but feels sensible to preregister COSE_KeySet here to allow libp2p ecosystem to experiment and evolve without gatekeepers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean using multiple protobuf messages instead of a COSE array. Maybe this doesn't work and the COSE array is better. I'm not sure. We'd also need to define how to hash the key set properly.

Comment thread peer-ids/peer-ids.md
Comment on lines +69 to +70
COSE_KEY = 0x42;
COSE_KEY_SET = 0x43;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
COSE_KEY = 0x42;
COSE_KEY_SET = 0x43;
COSE_Key = 0x42;
COSE_KeySet = 0x43;

Other ones look like Secp256k1 and RFC 9052 uses COSE_KeySet.

Perhaps rename to match the RFC?

Co-authored-by: Marcin Rataj <lidel@lidel.org>
@dennis-tra
Copy link
Copy Markdown

dennis-tra commented Apr 15, 2026

Doesn't this PR allow to e.g. represent an RSA key in three different ways? All of which would result in a differently encoded PeerID while all use the same key. The same is true when one peer uses COSE and the other PKIX with the same key.

Why is such flexibility needed? The last change to the PeerID spec was three years ago. The rate of change doesn't really signal that fast iterations with new key types is required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

3 participants