Repository navigation
Add did:key node IDs and certificate-free member/user identities - #8602
Draft
Amaury Chamayou (achamayou) wants to merge 9 commits into
Draft
Amaury Chamayou (achamayou) wants to merge 9 commits into
Amaury Chamayou (achamayou) wants to merge 9 commits into
Conversation
Keep SHA-256 defaults and digest behavior unchanged while supporting canonical public-key IDs throughout enrollment, authentication, node lifecycle, and SDK tooling. Preserve legacy enrollment during CCF 7 rolling upgrades and cover mixed-format lifecycle and recovery. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Amaury Chamayou (achamayou)
marked this pull request as draft
October 19, 2026 17:32
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Disk-based DID recovery and encoded node requests remain broken, and legacy enrollment adds quadratic table scanning.
3 open issues
What changed in this PR
Adds opt-in public-key identities across CCF while retaining SHA-256 defaults. This supports same-key certificate replacement, not the digest agility requested in #2419.
Changes:
- Adds canonical
did:keyderivation, enrollment, and authentication. - Integrates identity formats into joining, recovery, signing tools, and governance paths.
- Updates schemas, migration documentation, and regression coverage.
Custom instructions used
.github/instructions/reviewing.instructions.md
| File | Description |
|---|---|
| tests/lts_compatibility.py | Checks legacy enrollment during upgrades. |
| tests/infra/remote.py | Propagates node identity format. |
| tests/infra/openapi.py | Decodes schema-validation path parameters. |
| tests/infra/node.py | Supports format-aware node identities. |
| tests/infra/network.py | Configures member and user formats. |
| tests/infra/member.py | Supports DID signing and recovery paths. |
| tests/infra/crypto.py | Adds identity derivation helpers. |
| tests/infra/consortium.py | Passes enrollment formats. |
| tests/infra/clients.py | Supports DID COSE identities. |
| tests/governance.py | Adds DID lifecycle and recovery scenarios. |
| tests/config.jinja | Emits node identity configuration. |
| src/node/startup_inputs.h | Passes genesis member formats. |
| src/node/rpc/test/node_frontend_test.cpp | Tests DID configuration and joining. |
| src/node/rpc/test/internal_tables_access_test.cpp | Tests enrollment conflict handling. |
| src/node/rpc/test/frontend_test.cpp | Tests DID certificate authentication. |
| src/node/rpc/serialization.h | Serializes join identity format. |
| src/node/rpc/self_cert_auth.h | Matches the local node's format. |
| src/node/rpc/node_frontend.h | Handles DID joining and duplicates. |
| src/node/rpc/node_call_types.h | Adds join format selection. |
| src/node/node_state.h | Derives and confirms node IDs. |
| src/node/internal_tables_access.h | Enforces enrollment format constraints. |
| src/node/gov/handlers/helpers.h | Decodes and validates identity paths. |
| src/node/gov/handlers/acks.h | Decodes member action paths. |
| src/node/gov/gov_endpoint_registry.h | Updates identity schemas. |
| src/js/extensions/ccf/converters.cpp | Exposes native identity converters. |
| src/endpoints/test/endpoint_registry.cpp | Tests encoded DID action paths. |
| src/endpoints/authentication/cose_auth.cpp | Checks enrolled DID key binding. |
| src/endpoints/authentication/cert_auth.cpp | Adds DID certificate lookup. |
| src/enclave/enclave.h | Passes configured node format. |
| src/crypto/test/crypto.cpp | Tests DID encoding and key equality. |
| src/crypto/did_key.cpp | Implements canonical DID conversion. |
| samples/constitutions/default/actions.js | Adds DID enrollment safeguards. |
| python/utils/submit_recovery_share.sh | Supports DID recovery signing. |
| python/tests/test_identity.py | Tests SDK identity derivation. |
| python/tests/test_cose_sign.py | Tests both signing formats. |
| python/src/ccf/identity.py | Adds identity helpers and CLI. |
| python/src/ccf/cose.py | Adds signing format selection. |
| js/ccf-app/test/polyfill.test.ts | Tests identity polyfills. |
| js/ccf-app/src/polyfill.ts | Implements local identity conversion. |
| js/ccf-app/src/global.ts | Declares identity APIs. |
| include/ccf/service/tables/users.h | Adds user enrollment format. |
| include/ccf/service/tables/nodes.h | Adds format-aware node derivation. |
| include/ccf/service/tables/members.h | Adds member enrollment format. |
| include/ccf/node/configuration.h | Adds startup format options. |
| include/ccf/identity_id_format.h | Defines supported formats. |
| include/ccf/entity_id.h | Validates and describes DID IDs. |
| include/ccf/crypto/did_key.h | Declares DID conversion APIs. |
| include/ccf/crypto/cert_id.h | Adds certificate identity derivation. |
| doc/use_apps/issue_commands.rst | Documents DID signing options. |
| doc/schemas/node_openapi.json | Allows DID node IDs. |
| doc/schemas/gov/2024-07-01/gov.json | Updates stable governance schemas. |
| doc/schemas/gov/2023-06-01-preview/gov.json | Updates preview governance schemas. |
| doc/schemas/gov_openapi.json | Updates latest governance schemas. |
| doc/operations/configuration.rst | Documents startup identity settings. |
| doc/host_config_schema/host_config.json | Describes format configuration fields. |
| doc/governance/open_network.rst | Documents DID user enrollment. |
| doc/governance/adding_member.rst | Documents DID member workflows. |
| doc/build_apps/auth/cert.rst | Explains replacement-certificate authentication. |
| doc/architecture/cryptography.rst | Defines identity and migration semantics. |
| cmake/crypto.cmake | Includes DID implementation in builds. |
| CHANGELOG.md | Announces opt-in identity support. |
Review effort: Balanced
Use a one-byte identity format enum and explicit QuickJS boolean conversions to satisfy Virtual A's clang-tidy checks. Normalize DER-imported RSA public keys through JWK before canonical PKCS#1 re-encoding. This preserves DID encoding while fixing the Node 24 failure in modules_test and programmability_and_jwt. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Preserve enrolled member formats and recovery roles during disk-based recovery. Avoid scanning legacy certificate rosters and decode node identity path parameters, with native and end-to-end regression coverage. Allow certificate DID results to move into optional returns, fixing the required clang-tidy CI failure. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…errors - set_member no longer no-ops for an already-enrolled did:key member: it replaces the stored certificate, encryption key and member data and resets the member to Accepted, exactly like legacy members. - Join requests whose caller key cannot be identified in the requested ID format now fail with 400 instead of 500; DID derivation failures in cert/node/self authentication policies fall through to generic reasons rather than leaking parser error text. - Clarify in docs that enrolled-certificate validity does not bound access for DID identities. - Add JS unit, native and e2e regression coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Refresh against main at 9cdc86c without rewriting published history. Adapt the unsupported-key join regression to the updated certificate helper's separate validity arguments, and move the DID release note and SDK version to the next patch, 7.0.24. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…59d-f93e-40fd-9f2f-a0b4f11e15c0
Store public keys without identity certificates, authenticate DID COSE requests directly, and migrate legacy identities atomically in ordered governance proposals. Update genesis, SDK/CLI, recovery tooling, schemas, regression coverage, and the RST migration guide. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 264fbdd6871f4086ab3af9b5484907c3
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Motivation
Remove the certificate dependency from member/user enrollment and COSE authentication, and use IDs containing public keys rather than hard-coded SHA-256 fingerprints.
Related to #2419; existing signature, receipt, and attestation digest algorithms are unchanged.
Implementation summary
did_key, withoutcertorid_format, and store DER public keys in separate governance tables instead of identity certificates.remove_member/set_memberorremove_user/set_useractions in one proposal, while retaining application-time duplicate checks and member activation/recovery constraints.did:keynode IDs, legacy certificate enrollment, and optional TLS client-certificate compatibility; update caller types and API/configuration schemas.Safety and compatibility
Legacy certificate identities retain their SHA-256 IDs and existing behavior.
Canonical DIDs embed supported public keys, have no certificate validity period, and are authorized and revoked explicitly through governance.
Certificate-free COSE retains the existing supported ECDSA algorithms.
DIDs are enrolled identities, not aliases or authorization grants; same-role cross-format duplicate keys are rejected.
Migration actions apply in one transaction, with rollback if any action fails.
Migrated members start
Acceptedand must acknowledge again; recovery thresholds cannot be bypassed by atomic replacement.There is no backfill or automatic transfer of historical metadata or recovery state.
Upgrade every node before opting in to DID identities.
The legacy constitution path retains compatibility with older nodes during rolling upgrades.
Validation
Current certificate-free changes pass:
scripts/ci-checks.shwithout auto-fix.Full extended compatibility is not passing.
With
-DLONG_TESTS=ON,cd build && ./tests.sh --output-on-failure -R '^lts_compatibility$' --no-tests=errorreproduces the existing failure while released CCF 6.0.28 initiates private recovery (HTTP 500), before that ledger-recovery sequence reaches the current build.Remaining extended ledger-compatibility cases and required GitHub CI checks must pass before merge.
Custom instructions used
Applied
.github/copilot-instructions.md,.github/instructions/reviewing.instructions.md,.github/instructions/changelog.instructions.md, and.github/CONTRIBUTING.md.