From ee56b215f0c6f56c0a236ac1349686b4101f4e87 Mon Sep 17 00:00:00 2001 From: felix hoops <9974641+flhps@users.noreply.github.com> Date: Wed, 18 Mar 2026 12:12:42 +0100 Subject: [PATCH 1/8] feat(EVES-009): new draft on evidence Signed-off-by: felix hoops <9974641+flhps@users.noreply.github.com> --- EVES/EVES-009/eves-009.md | 188 ++++++++++++++++++++++++++++++++++++++ EVES/SUMMARY.md | 1 + README.md | 1 + 3 files changed, 190 insertions(+) create mode 100644 EVES/EVES-009/eves-009.md diff --git a/EVES/EVES-009/eves-009.md b/EVES/EVES-009/eves-009.md new file mode 100644 index 0000000..03f5530 --- /dev/null +++ b/EVES/EVES-009/eves-009.md @@ -0,0 +1,188 @@ +--- +eves-identifier: 009 +title: ENVITED-X Evidence-Based Consent Using Verifiable Presentations +author: Felix Hoops (@flhps) +discussions-to: https://github.com/ASCS-eV/EVES/issues/ +status: Draft +type: Standards +created: 2026-03-17 +requires: ["EVES-001", "EVES-002"] +replaces: None +--- + +## Abstract + +This specification defines a protocol for generating and verifying cryptographic evidence of user consent in the ENVITED-X Data Space. +It uses Verifiable Presentations (VPs) via OID4VP as the evidence format, binding consent to a specific action through a challenge-response mechanism. +The protocol enables services to act on behalf of users (e.g., for example, submitting blockchain transactions or finalizing contracts) while providing independently verifiable proof that the user authorized the action. + +## Motivation + +In the ENVITED-X Data Space, services frequently need to perform actions on behalf of users because users cannot directly perform these actions themselves with their SSI wallet. +A provider system may need to submit a blockchain transaction to list an asset, or issue a credential on behalf of a user. +In all cases, the service requires provable consent from the user before acting. + +Traditional approaches require users to hold and manage blockchain-specific keys. +In a Verifiable Credential ecosystem, however, users already hold credentials in SSI wallets and authenticate via OpenID-based flows. +Requiring additional key management imposes unnecessary complexity and fragments the user experience. + +This specification addresses the delegation problem by reusing the OID4VP protocol that users already interact with. +Users provide consent with their existing SSI wallet — no blockchain key management is needed. +The resulting evidence is a cryptographic artifact that: + +- **Binds consent to a specific action** through a deterministic challenge derived from the message describing the action. +- **Is independently verifiable** by any party with access to the evidence, without requiring contact with the original Requester. +- **Serves as a tamper-proof audit trail** that can be stored and verified at any later point. +- **Supports privacy-preserving disclosure** when SD-JWT VCs are used, allowing Holders to present only the claims required. + +The protocol is designed to be reusable across ENVITED-X processes. + +## Specification + +### 1. Evidence + +Evidence is cryptographic proof that a specific user consented to a specific action. +At minimum, evidence consists of the following components: + +- A **message** describing the action the user is consenting to. +- A **challenge** deterministically derived from that message via cryptographic hash function. +- A **signature object** proving the user saw and approved the message identified by the challenge. + +The challenge binds the signature object to the message. +Any modification to the message produces a different challenge, invalidating existing signature objects. +This ensures that consent cannot be transferred from one action to another. + +Three roles are involved in the evidence lifecycle: + +- **Requester**: The service that needs evidence of user consent for a specific action (e.g., to execute a blockchain transaction on the user's behalf). The Requester initiates the evidence request. +- **Holder**: The user whose consent is captured. The Holder reviews the action and approves or rejects the request. +- **Verifier**: Any party that checks whether a piece of evidence is valid. + +The Requester and Verifier MAY be the same party or different parties. + +The message format is not prescribed by this specification. +Implementations SHOULD include at minimum: + +- A human-readable description of the action +- A domain or origin identifying the Requester +- A unique nonce ensuring the message is not reused +- A timestamp indicating when the message was created + +[EIP-4361 (Sign-In with Ethereum)](https://eips.ethereum.org/EIPS/eip-4361) provides inspiration for structured message formats that include these elements. + +Future EVES MAY define additional evidence types with different signature objects and challenge derivation mechanisms. + +### 2. VP-Based Evidence + +This specification defines the first concrete evidence type using Verifiable Presentations: + +- The **challenge** is the cryptographic hash of the serialized message (e.g., `SHA-256(serialize(message))`). +- The **signature object** is a Verifiable Presentation (VP) where the challenge is embedded in the VP's `nonce` or challenge field. +- The VP contains one or more Verifiable Credentials (VCs) proving the Holder's identity and attributes. + +The VC format is not prescribed. +SD-JWT VCs (see [SD-JWT-based Verifiable Credentials](https://www.ietf.org/archive/id/draft-ietf-oauth-sd-jwt-vc-00.html)) are RECOMMENDED because selective disclosure allows Holders to redact unnecessary claims, minimizing personal data contained in the evidence. +Other VC formats conforming to the [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) are also valid. + +All VP formats include a challenge field (commonly `nonce`) that can carry the message hash. +This is the binding mechanism that ties the VP to the specific action. + +A key advantage of VP-based evidence is that the VP can include VCs carrying authorization-related data. +For example, a VC might prove that the Holder's key is affiliated with a specific organization, or that the Holder holds a particular role. +This means evidence does not just prove consent — it proves _authorized_ consent. +The Requester communicates what VCs are needed as part of the standard OID4VP flow. + +### 3. Evidence Creation Flow + +#### 3.1 Abstract Flow + +1. The Requester constructs a **message** describing the action and a **policy** specifying acceptable credentials. +2. A **challenge** is derived from the message. +3. The challenge and policy are presented to the Holder. +4. The Holder reviews the action and decides to approve or reject. +5. If approved, the Holder produces a **signature object** bound to the challenge. +6. The signature object is returned to the Requester, completing the evidence. + +#### 3.2 VP-Based Flow Using OID4VP + +The following sequence describes the VP-based evidence creation flow using [OpenID for Verifiable Presentations (OID4VP)](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html): + +1. The Requester displays a **message**, the **challenge** derived form it, and a way to verify this challenge. He also provides an OID4VP Authorization Request. Usually via QR-Code. +2. The Holder ingests the request and his wallet downloads the request object containing the **challenge** and requested VCs. +3. The Holder selects matching VCs, reviews the challenge, and provides consent. +4. The wallet creates a VP with the challenge as the `nonce` and submits it via `direct_post` to the Requester. +5. The VP is stored as evidence by the requester and may be used to trigger further actions. + +```mermaid +sequenceDiagram + participant R as Requester + participant H as Holder (Wallet) + + R->>R: Construct message + policy + R->>R: challenge = hash(message) + R->>H: OID4VP request (nonce=challenge, credentail request) + H->>H: Select VCs, review action + H->>H: Create VP (nonce=challenge) + H->>R: POST vp_token (direct_post) + R->>R: Verify & store evidence +``` + +### 4. Evidence Verification + +#### 4.1 Abstract Verification + +A Verifier MUST confirm the following for evidence to be considered valid: + +1. The **signature object** was produced by the claimed Holder. +2. The **signature object** is bound to the claimed message via the challenge. +3. The **credential requirements** specified in the policy are met. + +If any of these checks fail, the evidence MUST be considered invalid. + +#### 4.2 VP-Based Verification + +For VP-based evidence, the Verifier MUST perform the following checks: + +1. **VP signature verification**: The VP signature is verified against the Holder's DID (see [W3C Decentralized Identifiers](https://www.w3.org/TR/did-core/)). +2. **Credential verification**: Each VC inside the VP is independently verified, including issuer signature validation and format-specific integrity checks. +3. **VC requirement check**: The VCs in the VP satisfy the requirements that the Requester specified in the OID4VP request. +4. **Challenge binding**: The VP's `nonce` MUST equal `hash(message)`. This binds the evidence to the specific action. +5. **Holder verification** (OPTIONAL): If a specific Holder was expected, the VP subject MUST match the expected Holder's identifier. + +If any check fails, the evidence MUST be considered invalid. + +### 5. Security Considerations + +- **Replay prevention**: Each message MUST include a unique nonce, ensuring that the derived challenge is unique per action. This prevents a signature object from being replayed for a different action with an identical message. +- **Message integrity**: The deterministic hash binding between message and challenge ensures that any modification to the message invalidates the evidence. +- **Time-bounding**: Implementations SHOULD set an expiration on evidence requests to prevent stale requests from being fulfilled after an unreasonable delay. +- **Holder binding**: The Requester MAY specify an expected Holder. If specified, the Verifier MUST check that the VP subject matches the expected Holder. +- **Policy immutability**: The policy associated with an evidence request MUST NOT be modified after the request is created. Changing the policy after the Holder has consented would invalidate the relationship between what was requested and what was approved. +- **Transport security**: OID4VP requests and responses MUST be transmitted over TLS. Implementations SHOULD use signed authorization requests to prevent tampering. +- **Credential freshness**: Verifiers SHOULD check the revocation status of presented VCs. + +### 6. Privacy Considerations + +- **Minimal disclosure**: Policies SHOULD request only the claims necessary for the specific action. Over-requesting claims exposes unnecessary personal data. +- **Selective disclosure with SD-JWT VCs**: When SD-JWT VCs are used, Holders present only the claims required by the policy. All other claims are redacted from the presentation. This is the RECOMMENDED approach for new implementations. +- **Storage protection**: Stored evidence contains credential data and MUST be protected with appropriate access controls. Access to stored evidence SHOULD be limited to authorized parties on a need-to-know basis. + +## Backwards Compatibility + +This specification introduces a new protocol and does not modify any existing EVES. +It is compatible with the existing VC, DID, and wallet infrastructure described in [EVES-002](../EVES-002/eves-002.md). + +## References + +1. **EVES-001**: [ENVITED-X Ecosystem Specification Process](../EVES-001/eves-001.md) +2. **EVES-002**: [ENVITED-X Data Space Architecture Overview](../EVES-002/eves-002.md) +3. **OpenID for Verifiable Presentations (OID4VP)**: [Specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html) +4. **W3C Verifiable Credentials Data Model**: [Specification](https://www.w3.org/TR/vc-data-model/) +5. **W3C Decentralized Identifiers (DIDs)**: [Specification](https://www.w3.org/TR/did-core/) +6. **EIP-4361 (Sign-In with Ethereum / SIWE)**: [Specification](https://eips.ethereum.org/EIPS/eip-4361) +7. **RFC 2119**: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) +8. **SD-JWT-based Verifiable Credentials**: [Specification](https://www.ietf.org/archive/id/draft-ietf-oauth-sd-jwt-vc-00.html) + +## Implementation + +An initial implementation is planned for the [ENVITED-X Data Space](https://staging.envited-x.net). diff --git a/EVES/SUMMARY.md b/EVES/SUMMARY.md index 720f825..c93546d 100644 --- a/EVES/SUMMARY.md +++ b/EVES/SUMMARY.md @@ -13,3 +13,4 @@ * [EVES-005: ENVITED-X Contract Negotiation Process](./EVES-005/eves-005.md) * [EVES-006: ENVITED-X Scaling Architecture](./EVES-006/eves-006.md) * [EVES-007: ENVITED-X Blockchain Identifier URN Schema](./EVES-007/eves-007.md) +* [EVES-009: ENVITED-X Evidence-Based Consent Using Verifiable Presentations](./EVES-009/eves-009.md) diff --git a/README.md b/README.md index 2326b34..9962847 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,4 @@ The process on how to write, submit or change specifications in defined in [EVES | [005](./EVES/EVES-005/eves-005.md) | ENVITED-X Contract Negotiation Process | Process | Review | | [006](./EVES/EVES-006/eves-006.md) | ENVITED-X Scaling Architecture | Process | Draft | | [007](./EVES/EVES-007/eves-007.md) | ENVITED-X Blockchain Identifier URN Schema | Standards | Draft | +| [009](./EVES/EVES-009/eves-009.md) | ENVITED-X Evidence-Based Consent Using Verifiable Presentations | Standards | Draft | From 1b28ef228ed158dc60844fd657201c0a7b8b0915 Mon Sep 17 00:00:00 2001 From: jdsika Date: Sat, 4 Apr 2026 18:16:15 +0200 Subject: [PATCH 2/8] fix(EVES-009): address implementation review findings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align spec with harbour-credentials and simpulse-id-credentials reference implementations based on cross-implementation review. Specification changes: - §2: Mandate canonical serialization (RFC 8785 or sorted-key no-whitespace JSON) for deterministic challenge hashing - §2: Allow zero-VC VPs (pure consent proofs where Holder DID binding alone demonstrates authorization) - §2: Support both nonce-based and OID4VP KB-JWT transaction_data_hashes binding mechanisms for challenge binding - §2: Allow multiple evidence items per VP via hash arrays - §4.2: Relax challenge binding check to accommodate OID4VP dual-binding (VP nonce for replay prevention + KB-JWT hashes for message binding) - §4.2: Add SD-JWT-specific verification requirements (sd_hash, disclosure hash validation per RFC 9901) - §4.2: Clarify VC requirement check is skipped for zero-VC VPs - §5: Add canonical serialization as a security consideration - §6: Add consent-only evidence privacy guidance for zero-VC VPs Style and references: - Fix gendered language: "He also provides" -> "The Requester also provides" - Fix "his wallet" -> "the Holder's wallet" - Fix "e.g., for example" -> "e.g.," - Fix typos: "derived form" -> "derived from", "credentail" -> "credential" - Update ref #8 from expired draft to RFC 9901 - Add RFC 8785 (JSON Canonicalization Scheme) as ref #9 - Add OID4VP Appendix B.3.3 as ref #10 - Update Implementation section: cite harbour-credentials and simpulse-id-credentials as existing reference implementations Signed-off-by: jdsika --- EVES/EVES-009/eves-009.md | 51 ++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/EVES/EVES-009/eves-009.md b/EVES/EVES-009/eves-009.md index 03f5530..d551b1a 100644 --- a/EVES/EVES-009/eves-009.md +++ b/EVES/EVES-009/eves-009.md @@ -14,7 +14,7 @@ replaces: None This specification defines a protocol for generating and verifying cryptographic evidence of user consent in the ENVITED-X Data Space. It uses Verifiable Presentations (VPs) via OID4VP as the evidence format, binding consent to a specific action through a challenge-response mechanism. -The protocol enables services to act on behalf of users (e.g., for example, submitting blockchain transactions or finalizing contracts) while providing independently verifiable proof that the user authorized the action. +The protocol enables services to act on behalf of users (e.g., submitting blockchain transactions or finalizing contracts) while providing independently verifiable proof that the user authorized the action. ## Motivation @@ -64,7 +64,7 @@ The message format is not prescribed by this specification. Implementations SHOULD include at minimum: - A human-readable description of the action -- A domain or origin identifying the Requester +- A domain, origin, or DID identifying the Requester - A unique nonce ensuring the message is not reused - A timestamp indicating when the message was created @@ -76,22 +76,26 @@ Future EVES MAY define additional evidence types with different signature object This specification defines the first concrete evidence type using Verifiable Presentations: -- The **challenge** is the cryptographic hash of the serialized message (e.g., `SHA-256(serialize(message))`). -- The **signature object** is a Verifiable Presentation (VP) where the challenge is embedded in the VP's `nonce` or challenge field. -- The VP contains one or more Verifiable Credentials (VCs) proving the Holder's identity and attributes. +- The **challenge** is the cryptographic hash of the canonically serialized message. Implementations MUST use SHA-256 as the hash function. The message MUST be serialized using [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785) or an equivalent deterministic serialization (sorted keys, no whitespace: `json.dumps(sort_keys=True, separators=(",",":"))`). +- The **signature object** is a Verifiable Presentation (VP) where the challenge is bound to the VP. The binding mechanism depends on the VP format (see below). +- The VP contains zero or more Verifiable Credentials (VCs). When VCs are present, they prove the Holder's identity and attributes. When no VCs are included, the VP serves as a pure consent proof — the Holder's DID binding alone demonstrates authorization. + +The challenge binding mechanism depends on the VP format: + +- **Simple VP (VC-JOSE-COSE)**: The challenge SHOULD be embedded in the VP's `nonce` field directly (e.g., `nonce = hash(message)` or a composite format like ` `). +- **SD-JWT VP**: The challenge is bound via the KB-JWT `transaction_data_hashes` array per [OID4VP Appendix B.3.3](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html). The VP `nonce` field carries a random value for replay prevention. This dual-binding approach separates replay prevention from message binding and supports multiple evidence items per VP. The VC format is not prescribed. -SD-JWT VCs (see [SD-JWT-based Verifiable Credentials](https://www.ietf.org/archive/id/draft-ietf-oauth-sd-jwt-vc-00.html)) are RECOMMENDED because selective disclosure allows Holders to redact unnecessary claims, minimizing personal data contained in the evidence. +SD-JWT VCs (see [SD-JWT-based Verifiable Credentials (RFC 9901)](https://www.rfc-editor.org/rfc/rfc9901)) are RECOMMENDED because selective disclosure allows Holders to redact unnecessary claims, minimizing personal data contained in the evidence. Other VC formats conforming to the [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) are also valid. -All VP formats include a challenge field (commonly `nonce`) that can carry the message hash. -This is the binding mechanism that ties the VP to the specific action. - A key advantage of VP-based evidence is that the VP can include VCs carrying authorization-related data. For example, a VC might prove that the Holder's key is affiliated with a specific organization, or that the Holder holds a particular role. This means evidence does not just prove consent — it proves _authorized_ consent. The Requester communicates what VCs are needed as part of the standard OID4VP flow. +A single VP MAY contain evidence for multiple actions. In this case, the binding mechanism MUST support binding to multiple messages (e.g., the KB-JWT `transaction_data_hashes` array contains one hash per action). + ### 3. Evidence Creation Flow #### 3.1 Abstract Flow @@ -107,11 +111,11 @@ The Requester communicates what VCs are needed as part of the standard OID4VP fl The following sequence describes the VP-based evidence creation flow using [OpenID for Verifiable Presentations (OID4VP)](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html): -1. The Requester displays a **message**, the **challenge** derived form it, and a way to verify this challenge. He also provides an OID4VP Authorization Request. Usually via QR-Code. -2. The Holder ingests the request and his wallet downloads the request object containing the **challenge** and requested VCs. +1. The Requester displays a **message**, the **challenge** derived from it, and a way to verify this challenge. The Requester also provides an OID4VP Authorization Request, usually via QR-Code. +2. The Holder ingests the request and the Holder's wallet downloads the request object containing the **challenge** and requested VCs. 3. The Holder selects matching VCs, reviews the challenge, and provides consent. 4. The wallet creates a VP with the challenge as the `nonce` and submits it via `direct_post` to the Requester. -5. The VP is stored as evidence by the requester and may be used to trigger further actions. +5. The VP is stored as evidence by the Requester and may be used to trigger further actions. ```mermaid sequenceDiagram @@ -120,7 +124,7 @@ sequenceDiagram R->>R: Construct message + policy R->>R: challenge = hash(message) - R->>H: OID4VP request (nonce=challenge, credentail request) + R->>H: OID4VP request (nonce=challenge, credential request) H->>H: Select VCs, review action H->>H: Create VP (nonce=challenge) H->>R: POST vp_token (direct_post) @@ -135,7 +139,7 @@ A Verifier MUST confirm the following for evidence to be considered valid: 1. The **signature object** was produced by the claimed Holder. 2. The **signature object** is bound to the claimed message via the challenge. -3. The **credential requirements** specified in the policy are met. +3. The **credential requirements** specified in the policy are met (when VCs are present). If any of these checks fail, the evidence MUST be considered invalid. @@ -144,9 +148,9 @@ If any of these checks fail, the evidence MUST be considered invalid. For VP-based evidence, the Verifier MUST perform the following checks: 1. **VP signature verification**: The VP signature is verified against the Holder's DID (see [W3C Decentralized Identifiers](https://www.w3.org/TR/did-core/)). -2. **Credential verification**: Each VC inside the VP is independently verified, including issuer signature validation and format-specific integrity checks. -3. **VC requirement check**: The VCs in the VP satisfy the requirements that the Requester specified in the OID4VP request. -4. **Challenge binding**: The VP's `nonce` MUST equal `hash(message)`. This binds the evidence to the specific action. +2. **Credential verification**: Each VC inside the VP is independently verified, including issuer signature validation and format-specific integrity checks. For SD-JWT VCs, this includes disclosure hash validation per [RFC 9901](https://www.rfc-editor.org/rfc/rfc9901). +3. **VC requirement check**: When VCs are present, they MUST satisfy the requirements that the Requester specified in the OID4VP request. When no VCs are present (pure consent VP), this check is skipped. +4. **Challenge binding**: The VP MUST be bound to the claimed message. This binding MAY be achieved by setting the VP's `nonce` equal to `hash(message)`, or by using the OID4VP `transaction_data` mechanism ([Appendix B.3.3](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html)) where the KB-JWT `transaction_data_hashes` array contains `hash(transaction_data_param)`. For SD-JWT VPs, the KB-JWT `sd_hash` binding (RFC 9901 §4.3.1) MUST also be verified. 5. **Holder verification** (OPTIONAL): If a specific Holder was expected, the VP subject MUST match the expected Holder's identifier. If any check fails, the evidence MUST be considered invalid. @@ -155,6 +159,7 @@ If any check fails, the evidence MUST be considered invalid. - **Replay prevention**: Each message MUST include a unique nonce, ensuring that the derived challenge is unique per action. This prevents a signature object from being replayed for a different action with an identical message. - **Message integrity**: The deterministic hash binding between message and challenge ensures that any modification to the message invalidates the evidence. +- **Canonical serialization**: Implementations MUST use a deterministic serialization for message hashing. Failure to canonicalize messages means two implementations could produce different challenges for the same logical message, breaking interoperability. - **Time-bounding**: Implementations SHOULD set an expiration on evidence requests to prevent stale requests from being fulfilled after an unreasonable delay. - **Holder binding**: The Requester MAY specify an expected Holder. If specified, the Verifier MUST check that the VP subject matches the expected Holder. - **Policy immutability**: The policy associated with an evidence request MUST NOT be modified after the request is created. Changing the policy after the Holder has consented would invalidate the relationship between what was requested and what was approved. @@ -165,6 +170,7 @@ If any check fails, the evidence MUST be considered invalid. - **Minimal disclosure**: Policies SHOULD request only the claims necessary for the specific action. Over-requesting claims exposes unnecessary personal data. - **Selective disclosure with SD-JWT VCs**: When SD-JWT VCs are used, Holders present only the claims required by the policy. All other claims are redacted from the presentation. This is the RECOMMENDED approach for new implementations. +- **Consent-only evidence**: When the policy does not require identity attributes, implementations SHOULD use zero-VC VPs to minimize data exposure. The Holder's DID binding alone provides proof of consent. - **Storage protection**: Stored evidence contains credential data and MUST be protected with appropriate access controls. Access to stored evidence SHOULD be limited to authorized parties on a need-to-know basis. ## Backwards Compatibility @@ -181,8 +187,15 @@ It is compatible with the existing VC, DID, and wallet infrastructure described 5. **W3C Decentralized Identifiers (DIDs)**: [Specification](https://www.w3.org/TR/did-core/) 6. **EIP-4361 (Sign-In with Ethereum / SIWE)**: [Specification](https://eips.ethereum.org/EIPS/eip-4361) 7. **RFC 2119**: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) -8. **SD-JWT-based Verifiable Credentials**: [Specification](https://www.ietf.org/archive/id/draft-ietf-oauth-sd-jwt-vc-00.html) +8. **RFC 9901 (SD-JWT-based Verifiable Credentials)**: [Specification](https://www.rfc-editor.org/rfc/rfc9901) +9. **RFC 8785 (JSON Canonicalization Scheme)**: [Specification](https://www.rfc-editor.org/rfc/rfc8785) +10. **OID4VP Appendix B.3.3 (Transaction Data)**: [Specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html) ## Implementation -An initial implementation is planned for the [ENVITED-X Data Space](https://staging.envited-x.net). +Reference implementations exist in the following repositories: + +- **[harbour-credentials](https://github.com/reachhaven/harbour-credentials)** — Cryptographic library implementing the delegation challenge protocol, SD-JWT VP issuance and verification, and KB-JWT transaction data binding. Provides both Python and TypeScript implementations with feature parity. +- **[simpulse-id-credentials](https://github.com/ASCS-eV/simpulse-id-credentials)** — Domain-specific credential framework for the ENVITED-X Data Space, using harbour-credentials for evidence VP creation with the `credential.issue` action type. + +The evidence protocol is deployed in the [ENVITED-X Data Space](https://staging.envited-x.net). From 2de6db86d1ef71f129c6edd31d22f0e670871839 Mon Sep 17 00:00:00 2001 From: Carlo van Driesten Date: Mon, 18 May 2026 11:56:28 +0200 Subject: [PATCH 3/8] fix(EVES-009): wrap long lines to comply with 300-char lint limit Signed-off-by: Carlo van Driesten --- EVES/EVES-009/eves-009.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/EVES/EVES-009/eves-009.md b/EVES/EVES-009/eves-009.md index d551b1a..8c1107c 100644 --- a/EVES/EVES-009/eves-009.md +++ b/EVES/EVES-009/eves-009.md @@ -76,14 +76,21 @@ Future EVES MAY define additional evidence types with different signature object This specification defines the first concrete evidence type using Verifiable Presentations: -- The **challenge** is the cryptographic hash of the canonically serialized message. Implementations MUST use SHA-256 as the hash function. The message MUST be serialized using [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785) or an equivalent deterministic serialization (sorted keys, no whitespace: `json.dumps(sort_keys=True, separators=(",",":"))`). -- The **signature object** is a Verifiable Presentation (VP) where the challenge is bound to the VP. The binding mechanism depends on the VP format (see below). +- The **challenge** is the cryptographic hash of the canonically serialized message. + Implementations MUST use SHA-256 as the hash function. + The message MUST be serialized using [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785) + or an equivalent deterministic serialization (sorted keys, no whitespace: `json.dumps(sort_keys=True, separators=(",",":"))`). +- The **signature object** is a Verifiable Presentation (VP) where the challenge is bound to the VP. + The binding mechanism depends on the VP format (see below). - The VP contains zero or more Verifiable Credentials (VCs). When VCs are present, they prove the Holder's identity and attributes. When no VCs are included, the VP serves as a pure consent proof — the Holder's DID binding alone demonstrates authorization. The challenge binding mechanism depends on the VP format: - **Simple VP (VC-JOSE-COSE)**: The challenge SHOULD be embedded in the VP's `nonce` field directly (e.g., `nonce = hash(message)` or a composite format like ` `). -- **SD-JWT VP**: The challenge is bound via the KB-JWT `transaction_data_hashes` array per [OID4VP Appendix B.3.3](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html). The VP `nonce` field carries a random value for replay prevention. This dual-binding approach separates replay prevention from message binding and supports multiple evidence items per VP. +- **SD-JWT VP**: The challenge is bound via the KB-JWT `transaction_data_hashes` array + per [OID4VP Appendix B.3.3](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html). + The VP `nonce` field carries a random value for replay prevention. + This dual-binding approach separates replay prevention from message binding and supports multiple evidence items per VP. The VC format is not prescribed. SD-JWT VCs (see [SD-JWT-based Verifiable Credentials (RFC 9901)](https://www.rfc-editor.org/rfc/rfc9901)) are RECOMMENDED because selective disclosure allows Holders to redact unnecessary claims, minimizing personal data contained in the evidence. @@ -150,7 +157,12 @@ For VP-based evidence, the Verifier MUST perform the following checks: 1. **VP signature verification**: The VP signature is verified against the Holder's DID (see [W3C Decentralized Identifiers](https://www.w3.org/TR/did-core/)). 2. **Credential verification**: Each VC inside the VP is independently verified, including issuer signature validation and format-specific integrity checks. For SD-JWT VCs, this includes disclosure hash validation per [RFC 9901](https://www.rfc-editor.org/rfc/rfc9901). 3. **VC requirement check**: When VCs are present, they MUST satisfy the requirements that the Requester specified in the OID4VP request. When no VCs are present (pure consent VP), this check is skipped. -4. **Challenge binding**: The VP MUST be bound to the claimed message. This binding MAY be achieved by setting the VP's `nonce` equal to `hash(message)`, or by using the OID4VP `transaction_data` mechanism ([Appendix B.3.3](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html)) where the KB-JWT `transaction_data_hashes` array contains `hash(transaction_data_param)`. For SD-JWT VPs, the KB-JWT `sd_hash` binding (RFC 9901 §4.3.1) MUST also be verified. +4. **Challenge binding**: The VP MUST be bound to the claimed message. + This binding MAY be achieved by setting the VP's `nonce` equal to `hash(message)`, + or by using the OID4VP `transaction_data` mechanism + ([Appendix B.3.3](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html)) + where the KB-JWT `transaction_data_hashes` array contains `hash(transaction_data_param)`. + For SD-JWT VPs, the KB-JWT `sd_hash` binding (RFC 9901 §4.3.1) MUST also be verified. 5. **Holder verification** (OPTIONAL): If a specific Holder was expected, the VP subject MUST match the expected Holder's identifier. If any check fails, the evidence MUST be considered invalid. From a3a796ef6780ab7617791db24c75e4062b9f731f Mon Sep 17 00:00:00 2001 From: felix hoops <9974641+flhps@users.noreply.github.com> Date: Thu, 16 Jul 2026 11:34:42 +0200 Subject: [PATCH 4/8] refactor(EVES-009): split spec into generic evidence model and SD-JWT VC profile Restructure the specification into two clearly labeled layers: a generic, technology-agnostic evidence model (sections 1-3) and a concrete profile for VPs of SD-JWT VCs in dc+sd-jwt format (sections 4-6). Remove the unimplemented transaction_data dual-binding mechanism; the profile now specifies the actual binding used in practice (challenge in the KB-JWT key-binding nonce). Keep transaction_data as a non-normative future-work note. Loosen the RFC 8785 canonicalization MUST to a SHOULD scoped to JSON messages, since the message format is intentionally not standardized by this spec. Signed-off-by: felix hoops <9974641+flhps@users.noreply.github.com> Co-Authored-By: Claude Fable 5 --- EVES/EVES-009/eves-009.md | 118 ++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 61 deletions(-) diff --git a/EVES/EVES-009/eves-009.md b/EVES/EVES-009/eves-009.md index 8c1107c..34c68e1 100644 --- a/EVES/EVES-009/eves-009.md +++ b/EVES/EVES-009/eves-009.md @@ -39,7 +39,12 @@ The protocol is designed to be reusable across ENVITED-X processes. ## Specification -### 1. Evidence +The specification is organized in two layers. +Sections 1–3 define the **generic** evidence model, which is independent of any particular credential or signature technology. +Sections 4–6 define the first **concrete profile** that realizes the generic model using Verifiable Presentations of SD-JWT VCs (`dc+sd-jwt`). +Future EVES MAY define additional profiles without changing the generic model. + +### 1. Evidence (Generic) Evidence is cryptographic proof that a specific user consented to a specific action. At minimum, evidence consists of the following components: @@ -54,7 +59,7 @@ This ensures that consent cannot be transferred from one action to another. Three roles are involved in the evidence lifecycle: -- **Requester**: The service that needs evidence of user consent for a specific action (e.g., to execute a blockchain transaction on the user's behalf). The Requester initiates the evidence request. +- **Requester**: The service that needs evidence of user consent for a specific action (for example, to execute a blockchain transaction on the user's behalf). The Requester initiates the evidence request. - **Holder**: The user whose consent is captured. The Holder reviews the action and approves or rejects the request. - **Verifier**: Any party that checks whether a piece of evidence is valid. @@ -71,50 +76,49 @@ Implementations SHOULD include at minimum: [EIP-4361 (Sign-In with Ethereum)](https://eips.ethereum.org/EIPS/eip-4361) provides inspiration for structured message formats that include these elements. Future EVES MAY define additional evidence types with different signature objects and challenge derivation mechanisms. +For example, a future type could bind the challenge through the OID4VP `transaction_data` mechanism once the necessary sub-specification and wallet support exist. -### 2. VP-Based Evidence +### 2. Evidence Creation Flow (Generic) -This specification defines the first concrete evidence type using Verifiable Presentations: +1. The Requester constructs a **message** describing the action and a **policy** specifying acceptable credentials. +2. A **challenge** is derived from the message. +3. The challenge and policy are presented to the Holder. +4. The Holder reviews the action and decides to approve or reject. +5. If approved, the Holder produces a **signature object** bound to the challenge. +6. The signature object is returned to the Requester, completing the evidence. -- The **challenge** is the cryptographic hash of the canonically serialized message. - Implementations MUST use SHA-256 as the hash function. - The message MUST be serialized using [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785) - or an equivalent deterministic serialization (sorted keys, no whitespace: `json.dumps(sort_keys=True, separators=(",",":"))`). -- The **signature object** is a Verifiable Presentation (VP) where the challenge is bound to the VP. - The binding mechanism depends on the VP format (see below). -- The VP contains zero or more Verifiable Credentials (VCs). When VCs are present, they prove the Holder's identity and attributes. When no VCs are included, the VP serves as a pure consent proof — the Holder's DID binding alone demonstrates authorization. +### 3. Evidence Verification (Generic) -The challenge binding mechanism depends on the VP format: +A Verifier MUST confirm the following for evidence to be considered valid: -- **Simple VP (VC-JOSE-COSE)**: The challenge SHOULD be embedded in the VP's `nonce` field directly (e.g., `nonce = hash(message)` or a composite format like ` `). -- **SD-JWT VP**: The challenge is bound via the KB-JWT `transaction_data_hashes` array - per [OID4VP Appendix B.3.3](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html). - The VP `nonce` field carries a random value for replay prevention. - This dual-binding approach separates replay prevention from message binding and supports multiple evidence items per VP. +1. The **signature object** was produced by the claimed Holder. +2. The **signature object** is bound to the claimed message via the challenge. +3. The **credential requirements** specified in the policy are met (when VCs are present). -The VC format is not prescribed. -SD-JWT VCs (see [SD-JWT-based Verifiable Credentials (RFC 9901)](https://www.rfc-editor.org/rfc/rfc9901)) are RECOMMENDED because selective disclosure allows Holders to redact unnecessary claims, minimizing personal data contained in the evidence. -Other VC formats conforming to the [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) are also valid. +If any of these checks fail, the evidence MUST be considered invalid. -A key advantage of VP-based evidence is that the VP can include VCs carrying authorization-related data. -For example, a VC might prove that the Holder's key is affiliated with a specific organization, or that the Holder holds a particular role. -This means evidence does not just prove consent — it proves _authorized_ consent. -The Requester communicates what VCs are needed as part of the standard OID4VP flow. +### 4. VP-Based Evidence (SD-JWT VC Profile) -A single VP MAY contain evidence for multiple actions. In this case, the binding mechanism MUST support binding to multiple messages (e.g., the KB-JWT `transaction_data_hashes` array contains one hash per action). +This specification defines the first concrete evidence type using Verifiable Presentations. +This profile is defined **only** for Verifiable Credentials in the SD-JWT VC format (`dc+sd-jwt`, see [RFC 9901](https://www.rfc-editor.org/rfc/rfc9901)). +Verifiable Presentations using any other credential format are out of scope for this profile; a future EVES MAY define additional profiles for them. -### 3. Evidence Creation Flow +- The **challenge** is the SHA-256 hash of the serialized message. + When the message is a JSON object, implementations SHOULD canonicalize it before hashing — for example, using [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785) — so that independent implementations derive an identical challenge for the same logical message. +- The **signature object** is a Verifiable Presentation (VP) of one or more `dc+sd-jwt` credentials. The evidence is the VP's Key Binding JWT (KB-JWT), and the challenge is carried in the KB-JWT key-binding `nonce`. +- The VP contains zero or more Verifiable Credentials (VCs). When VCs are present, they prove the Holder's identity and attributes. When no VCs are included, the VP serves as a pure consent proof — the Holder's key binding alone demonstrates authorization. -#### 3.1 Abstract Flow +The challenge is bound to the evidence through the KB-JWT key-binding `nonce`. +This is the binding mechanism that ties the VP to the specific action. -1. The Requester constructs a **message** describing the action and a **policy** specifying acceptable credentials. -2. A **challenge** is derived from the message. -3. The challenge and policy are presented to the Holder. -4. The Holder reviews the action and decides to approve or reject. -5. If approved, the Holder produces a **signature object** bound to the challenge. -6. The signature object is returned to the Requester, completing the evidence. +The SD-JWT VC format is used because selective disclosure allows Holders to redact unnecessary claims, minimizing the personal data contained in the evidence. -#### 3.2 VP-Based Flow Using OID4VP +A key advantage of VP-based evidence is that the VP can include VCs carrying authorization-related data. +For example, a VC might prove that the Holder's key is affiliated with a specific organization, or that the Holder holds a particular role. +This means evidence does not just prove consent — it proves _authorized_ consent. +The Requester communicates what VCs are needed as part of the standard OID4VP flow. + +### 5. VP-Based Creation Flow (OID4VP) The following sequence describes the VP-based evidence creation flow using [OpenID for Verifiable Presentations (OID4VP)](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html): @@ -138,51 +142,44 @@ sequenceDiagram R->>R: Verify & store evidence ``` -### 4. Evidence Verification - -#### 4.1 Abstract Verification - -A Verifier MUST confirm the following for evidence to be considered valid: - -1. The **signature object** was produced by the claimed Holder. -2. The **signature object** is bound to the claimed message via the challenge. -3. The **credential requirements** specified in the policy are met (when VCs are present). - -If any of these checks fail, the evidence MUST be considered invalid. - -#### 4.2 VP-Based Verification +### 6. VP-Based Verification For VP-based evidence, the Verifier MUST perform the following checks: 1. **VP signature verification**: The VP signature is verified against the Holder's DID (see [W3C Decentralized Identifiers](https://www.w3.org/TR/did-core/)). -2. **Credential verification**: Each VC inside the VP is independently verified, including issuer signature validation and format-specific integrity checks. For SD-JWT VCs, this includes disclosure hash validation per [RFC 9901](https://www.rfc-editor.org/rfc/rfc9901). +2. **Credential verification**: Each `dc+sd-jwt` credential inside the VP is independently verified, including issuer signature validation and disclosure hash validation per [RFC 9901](https://www.rfc-editor.org/rfc/rfc9901). 3. **VC requirement check**: When VCs are present, they MUST satisfy the requirements that the Requester specified in the OID4VP request. When no VCs are present (pure consent VP), this check is skipped. -4. **Challenge binding**: The VP MUST be bound to the claimed message. - This binding MAY be achieved by setting the VP's `nonce` equal to `hash(message)`, - or by using the OID4VP `transaction_data` mechanism - ([Appendix B.3.3](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html)) - where the KB-JWT `transaction_data_hashes` array contains `hash(transaction_data_param)`. - For SD-JWT VPs, the KB-JWT `sd_hash` binding (RFC 9901 §4.3.1) MUST also be verified. +4. **Challenge binding**: The KB-JWT key-binding `nonce` MUST equal `hash(message)`, and the KB-JWT `sd_hash` binding ([RFC 9901](https://www.rfc-editor.org/rfc/rfc9901) §4.3.1) MUST be verified. This binds the evidence to the specific action. 5. **Holder verification** (OPTIONAL): If a specific Holder was expected, the VP subject MUST match the expected Holder's identifier. If any check fails, the evidence MUST be considered invalid. -### 5. Security Considerations +### 7. Security Considerations + +The following considerations apply to the generic evidence model: - **Replay prevention**: Each message MUST include a unique nonce, ensuring that the derived challenge is unique per action. This prevents a signature object from being replayed for a different action with an identical message. - **Message integrity**: The deterministic hash binding between message and challenge ensures that any modification to the message invalidates the evidence. -- **Canonical serialization**: Implementations MUST use a deterministic serialization for message hashing. Failure to canonicalize messages means two implementations could produce different challenges for the same logical message, breaking interoperability. +- **Deterministic challenge derivation**: Implementations MUST derive the challenge from the message deterministically. Otherwise two implementations could produce different challenges for the same logical message, breaking interoperability. - **Time-bounding**: Implementations SHOULD set an expiration on evidence requests to prevent stale requests from being fulfilled after an unreasonable delay. -- **Holder binding**: The Requester MAY specify an expected Holder. If specified, the Verifier MUST check that the VP subject matches the expected Holder. +- **Holder binding**: The Requester MAY specify an expected Holder. If specified, the Verifier MUST check that the signature object's subject matches the expected Holder. - **Policy immutability**: The policy associated with an evidence request MUST NOT be modified after the request is created. Changing the policy after the Holder has consented would invalidate the relationship between what was requested and what was approved. + +The following considerations are specific to the VP-based profile: + - **Transport security**: OID4VP requests and responses MUST be transmitted over TLS. Implementations SHOULD use signed authorization requests to prevent tampering. - **Credential freshness**: Verifiers SHOULD check the revocation status of presented VCs. -### 6. Privacy Considerations +### 8. Privacy Considerations + +The following consideration applies to the generic evidence model: - **Minimal disclosure**: Policies SHOULD request only the claims necessary for the specific action. Over-requesting claims exposes unnecessary personal data. -- **Selective disclosure with SD-JWT VCs**: When SD-JWT VCs are used, Holders present only the claims required by the policy. All other claims are redacted from the presentation. This is the RECOMMENDED approach for new implementations. -- **Consent-only evidence**: When the policy does not require identity attributes, implementations SHOULD use zero-VC VPs to minimize data exposure. The Holder's DID binding alone provides proof of consent. + +The following considerations are specific to the VP-based profile: + +- **Selective disclosure**: Because the profile uses SD-JWT VCs, Holders present only the claims required by the policy. All other claims are redacted from the presentation. +- **Consent-only evidence**: When the policy does not require identity attributes, implementations SHOULD use zero-VC VPs to minimize data exposure. The Holder's key binding alone provides proof of consent. - **Storage protection**: Stored evidence contains credential data and MUST be protected with appropriate access controls. Access to stored evidence SHOULD be limited to authorized parties on a need-to-know basis. ## Backwards Compatibility @@ -201,7 +198,6 @@ It is compatible with the existing VC, DID, and wallet infrastructure described 7. **RFC 2119**: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) 8. **RFC 9901 (SD-JWT-based Verifiable Credentials)**: [Specification](https://www.rfc-editor.org/rfc/rfc9901) 9. **RFC 8785 (JSON Canonicalization Scheme)**: [Specification](https://www.rfc-editor.org/rfc/rfc8785) -10. **OID4VP Appendix B.3.3 (Transaction Data)**: [Specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html) ## Implementation From ac77049cf0d4763efdc36a82b503cc02242cfa7b Mon Sep 17 00:00:00 2001 From: felix hoops <9974641+flhps@users.noreply.github.com> Date: Thu, 16 Jul 2026 12:11:17 +0200 Subject: [PATCH 5/8] refactor(EVES-009): slim to generic evidence concept and thin VP core Keep EVES-009 high-level: the generic evidence model plus the minimal VP-based realization (challenge in the KB-JWT key-binding nonce, driven by the constraint that wallets only sign KB-JWTs). Add the hash-as-received principle, a multi-action commitment hook in the generic model, a key rotation security consideration, and a derived-artifact escape hatch in the verification section. Issuance-specific detail moves to EVES-010. Signed-off-by: felix hoops <9974641+flhps@users.noreply.github.com> Co-Authored-By: Claude Fable 5 --- EVES/EVES-009/eves-009.md | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/EVES/EVES-009/eves-009.md b/EVES/EVES-009/eves-009.md index 34c68e1..3d2816c 100644 --- a/EVES/EVES-009/eves-009.md +++ b/EVES/EVES-009/eves-009.md @@ -75,6 +75,10 @@ Implementations SHOULD include at minimum: [EIP-4361 (Sign-In with Ethereum)](https://eips.ethereum.org/EIPS/eip-4361) provides inspiration for structured message formats that include these elements. +A message MAY commit to a set of actions instead of a single one, for example through a cryptographic commitment such as a Merkle root. +A specification building on such messages MUST define how each individual action proves its inclusion in the commitment. +[EVES-010](../EVES-010/eves-010.md) uses this pattern to authorize the issuance of many credentials with a single piece of evidence. + Future EVES MAY define additional evidence types with different signature objects and challenge derivation mechanisms. For example, a future type could bind the challenge through the OID4VP `transaction_data` mechanism once the necessary sub-specification and wallet support exist. @@ -103,9 +107,15 @@ This specification defines the first concrete evidence type using Verifiable Pre This profile is defined **only** for Verifiable Credentials in the SD-JWT VC format (`dc+sd-jwt`, see [RFC 9901](https://www.rfc-editor.org/rfc/rfc9901)). Verifiable Presentations using any other credential format are out of scope for this profile; a future EVES MAY define additional profiles for them. -- The **challenge** is the SHA-256 hash of the serialized message. - When the message is a JSON object, implementations SHOULD canonicalize it before hashing — for example, using [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785) — so that independent implementations derive an identical challenge for the same logical message. -- The **signature object** is a Verifiable Presentation (VP) of one or more `dc+sd-jwt` credentials. The evidence is the VP's Key Binding JWT (KB-JWT), and the challenge is carried in the KB-JWT key-binding `nonce`. +The profile is designed around a practical constraint: identity wallets do not produce arbitrary signatures. +The only signature obtainable from a wallet is the Key Binding JWT (KB-JWT) of an OID4VP presentation. +This profile therefore uses the KB-JWT as the signature object and carries the challenge in a field the wallet signs as part of every presentation: + +- The **challenge** is the SHA-256 hash of the message, computed over the exact bytes presented to the Holder. + The message is carried verbatim alongside the evidence and hashed as received; Verifiers MUST NOT re-render or normalize it. + When a message must be regenerated from structured data rather than carried verbatim (for example, a JSON object), implementations SHOULD use a deterministic serialization + such as [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785) so that independent implementations derive an identical challenge. +- The **signature object** is a Verifiable Presentation (VP) of one or more `dc+sd-jwt` credentials. The evidence is the VP's KB-JWT, and the challenge is carried in the KB-JWT key-binding `nonce`. - The VP contains zero or more Verifiable Credentials (VCs). When VCs are present, they prove the Holder's identity and attributes. When no VCs are included, the VP serves as a pure consent proof — the Holder's key binding alone demonstrates authorization. The challenge is bound to the evidence through the KB-JWT key-binding `nonce`. @@ -126,7 +136,7 @@ The following sequence describes the VP-based evidence creation flow using [Open 2. The Holder ingests the request and the Holder's wallet downloads the request object containing the **challenge** and requested VCs. 3. The Holder selects matching VCs, reviews the challenge, and provides consent. 4. The wallet creates a VP with the challenge as the `nonce` and submits it via `direct_post` to the Requester. -5. The VP is stored as evidence by the Requester and may be used to trigger further actions. +5. The Requester verifies the VP and retains it — or a derived artifact containing at least the KB-JWT and the verbatim message — as evidence, which may be used to trigger further actions. ```mermaid sequenceDiagram @@ -154,6 +164,10 @@ For VP-based evidence, the Verifier MUST perform the following checks: If any check fails, the evidence MUST be considered invalid. +These checks apply to a Verifier in possession of the complete VP — typically the Requester at presentation time. +A specification that persists a derived evidence artifact containing only parts of the VP MUST define which of these checks its Verifiers perform instead and how. +[EVES-010](../EVES-010/eves-010.md) defines such a derived artifact for credential issuance, retaining only the KB-JWT and the message. + ### 7. Security Considerations The following considerations apply to the generic evidence model: @@ -163,6 +177,7 @@ The following considerations apply to the generic evidence model: - **Deterministic challenge derivation**: Implementations MUST derive the challenge from the message deterministically. Otherwise two implementations could produce different challenges for the same logical message, breaking interoperability. - **Time-bounding**: Implementations SHOULD set an expiration on evidence requests to prevent stale requests from being fulfilled after an unreasonable delay. - **Holder binding**: The Requester MAY specify an expected Holder. If specified, the Verifier MUST check that the signature object's subject matches the expected Holder. +- **Key rotation**: When Holder keys are anchored in a DID document that can change over time, Verifiers SHOULD resolve the DID document as of the evidence creation time. Otherwise, legitimate key rotation would retroactively invalidate previously created evidence. - **Policy immutability**: The policy associated with an evidence request MUST NOT be modified after the request is created. Changing the policy after the Holder has consented would invalidate the relationship between what was requested and what was approved. The following considerations are specific to the VP-based profile: @@ -198,12 +213,11 @@ It is compatible with the existing VC, DID, and wallet infrastructure described 7. **RFC 2119**: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) 8. **RFC 9901 (SD-JWT-based Verifiable Credentials)**: [Specification](https://www.rfc-editor.org/rfc/rfc9901) 9. **RFC 8785 (JSON Canonicalization Scheme)**: [Specification](https://www.rfc-editor.org/rfc/rfc8785) +10. **EVES-010**: [ENVITED-X Credential Issuance Authorization via Embedded Evidence](../EVES-010/eves-010.md) ## Implementation -Reference implementations exist in the following repositories: - -- **[harbour-credentials](https://github.com/reachhaven/harbour-credentials)** — Cryptographic library implementing the delegation challenge protocol, SD-JWT VP issuance and verification, and KB-JWT transaction data binding. Provides both Python and TypeScript implementations with feature parity. -- **[simpulse-id-credentials](https://github.com/ASCS-eV/simpulse-id-credentials)** — Domain-specific credential framework for the ENVITED-X Data Space, using harbour-credentials for evidence VP creation with the `credential.issue` action type. +A reference implementation exists in **[harbour-credentials](https://github.com/reachhaven/harbour-credentials)** — a cryptographic library implementing SD-JWT VP issuance and verification, KB-JWT creation and verification, and challenge derivation. +It provides Python and TypeScript implementations with feature parity. -The evidence protocol is deployed in the [ENVITED-X Data Space](https://staging.envited-x.net). +[EVES-010](../EVES-010/eves-010.md) applies this evidence protocol to credential issuance; its implementation is deployed in the [ENVITED-X Data Space](https://staging.envited-x.net). From 3ffac5582bfb0ef8f8465644404d38a76fd9b557 Mon Sep 17 00:00:00 2001 From: felix hoops <9974641+flhps@users.noreply.github.com> Date: Thu, 16 Jul 2026 12:11:17 +0200 Subject: [PATCH 6/8] feat(EVES-010): new draft on credential issuance authorization via embedded evidence Specify how an organization authorizes the issuance of one or more credentials with a single wallet signature (EVES-009 evidence over a message committing to a batch Merkle root) and how each issued credential embeds a self-contained authorization record in its evidence field. Defines the authorization message grammar, the embedded evidence structure, and the two-tier verification model (intake vs. downstream). Matches the mechanism implemented in harbour-credentials. Signed-off-by: felix hoops <9974641+flhps@users.noreply.github.com> Co-Authored-By: Claude Fable 5 --- EVES/EVES-010/eves-010.md | 160 ++++++++++++++++++++++++++++++++++++++ EVES/SUMMARY.md | 1 + README.md | 23 +++--- 3 files changed, 173 insertions(+), 11 deletions(-) create mode 100644 EVES/EVES-010/eves-010.md diff --git a/EVES/EVES-010/eves-010.md b/EVES/EVES-010/eves-010.md new file mode 100644 index 0000000..ed483d6 --- /dev/null +++ b/EVES/EVES-010/eves-010.md @@ -0,0 +1,160 @@ +--- +eves-identifier: "010" +title: ENVITED-X Credential Issuance Authorization via Embedded Evidence +author: Felix Hoops (@flhps) +discussions-to: https://github.com/ASCS-eV/EVES/issues/ +status: Draft +type: Standards +created: 2026-07-16 +requires: ["EVES-001", "EVES-002", "EVES-008", "EVES-009"] +replaces: None +--- + +## Abstract + +This specification applies the evidence protocol defined in [EVES-009](../EVES-009/eves-009.md) to credential issuance. +It defines how an authorizing organization approves the issuance of one or more credentials with a single wallet signature, and how each issued credential embeds a self-contained, independently verifiable record of that authorization in its `evidence` field. +The authorization message commits to the whole batch through a Merkle root; each credential carries the authorization signature together with its own inclusion proof. + +## Motivation + +In the ENVITED-X Data Space, credential proofs are executed by a signing service on behalf of sovereign issuers (see [EVES-008](../EVES-008/eves-008.md)). +The signing service executes the credential lifecycle but must not decide anything: every issuance requires provable authorization by the issuing organization. + +This creates two requirements in tension: + +- **One signature**: A common operation is an organization authorizing credentials for all of its members at once. The authorizing admin should sign once, not once per credential. +- **Self-contained verification**: Every issued credential must independently prove that it was covered by that authorization — without access to the rest of the batch and without contacting the issuing infrastructure. + +This specification resolves the tension with a cryptographic commitment, using the multi-action message pattern from EVES-009: +the admin consents to a message committing to a Merkle root over the whole batch, and each issued credential carries an inclusion proof binding its own payload to that root. +The resulting evidence is embedded in the credential itself and serves as a durable, non-repudiable audit trail of who approved the issuance. +A signing service that issued a credential nobody authorized is detectable by any Verifier, because it cannot forge the admin's wallet signature. + +## Specification + +### 1. Roles + +This specification refines the EVES-009 roles for the issuance setting: + +- **Authorizer**: The issuing organization, identified by its DID. The authorization signature is made by a human admin whose wallet key is a verification method of that DID. The Authorizer is the EVES-009 **Holder**. +- **Signing Service**: The service that assembles the batch, obtains the authorization, embeds the evidence, and executes the credential proofs under a mandate from the issuer. The Signing Service is the EVES-009 **Requester**. +- **Intake Verifier**: The OID4VP verifier endpoint that receives the admin's presentation during the authorization ceremony and performs full EVES-009 verification. +- **Downstream Verifier**: Any relying party that later verifies an issued credential and its embedded evidence in isolation. + +### 2. Authorization Message + +The authorization message is a human-readable text string following the EVES-009 message requirements, styled after [EIP-4361 (Sign-In with Ethereum)](https://eips.ethereum.org/EIPS/eip-4361). +It is composed by the Signing Service, displayed verbatim on the admin's wallet consent screen, and carried byte-exact in the evidence. + +The message MUST contain exactly one statement line matching the following template: + +```text +I authorize the issuance of credential(s) committed to by Merkle root . +``` + +Where `` is the decimal batch size and `` is the base64url-encoded (unpadded, 43 characters) SHA-256 Merkle root over the batch. +Verifiers extract the root only through this template. + +All other message content — domain, Authorizer address, ceremony nonce, and timestamp — is ceremony metadata. +It is part of the hashed message but not interpreted by Verifiers. +The ceremony nonce and timestamp inside the hashed message make every ceremony's challenge unique, satisfying the EVES-009 replay prevention requirement. + +Following EVES-009, the message is hashed exactly as received: the **challenge** is `SHA-256(message)` in lowercase hexadecimal encoding, and Verifiers MUST NOT re-render or normalize the message. + +### 3. Evidence Creation + +1. The Signing Service computes a leaf hash for each credential payload in the batch. The leaf is computed over the payload with its `evidence` and `proof` members removed, so the leaf is independent of the evidence that will later embed the proof of its own inclusion. +2. The Signing Service builds a Merkle tree over the leaves and composes the authorization message committing to its root (see section 2). +3. The admin provides consent through the EVES-009 VP-based flow: the wallet receives an OID4VP presentation request whose `nonce` is the challenge, displays the message, + and responds by presenting the organization's LegalPersonCredential (see EVES-008) with a KB-JWT signed by the admin's wallet key. +4. The Intake Verifier performs full EVES-009 verification of the presentation (see section 5.1). +5. For each credential in the batch, the Signing Service constructs an evidence object (see section 4) and embeds it in the credential's `evidence` array before the credential is signed as `dc+sd-jwt`. + +Only the KB-JWT is retained from the presentation. +The presented credential itself is not carried in the evidence; the Authorizer's authority is verifiable through its DID document instead (see section 5.2). + +### 4. Evidence Structure + +Each issued credential carries one evidence object with the following components: + +- **`authorizedBy`**: The Authorizer organization's DID. +- **`authorization`**: The KB-JWT obtained in the authorization ceremony — the EVES-009 signature object. Its `nonce` carries the challenge, and its `iat` timestamps the authorization. +- **`authorizationMessage`**: The verbatim authorization message — the EVES-009 message. +- **`merkleProof`**: The credential's inclusion proof — the ordered list of sibling digests from the credential's leaf up to the committed root. + +The exact Merkle tree construction, leaf encoding, and JSON-LD vocabulary are specified in the +[Harbour Batched Credential Evidence specification](https://github.com/reachhaven/harbour-credentials/blob/main/docs/specs/batched-credential-evidence.md), +which serves as the normative wire-format reference for this EVES. + +Because the issuer's `dc+sd-jwt` signature covers the credential payload including the `evidence` array, the embedded evidence is tamper-evident: it cannot be stripped or replaced without invalidating the credential. + +### 5. Verification + +Verification happens at two distinct points in time, by two distinct parties, with different material available. + +#### 5.1 Intake Verification + +The Intake Verifier holds the complete presentation and MUST perform the full EVES-009 VP-based verification, including credential verification, `sd_hash` validation, and challenge binding. +Additionally, the Intake Verifier MUST reject an authorization whose KB-JWT `aud` is not its own identifier. + +#### 5.2 Downstream Verification + +A Downstream Verifier verifies one issued credential and its evidence in isolation. +It holds only the derived evidence artifact (see section 4), not the presentation, and MUST perform the following checks: + +1. **Authorization signature**: The KB-JWT signature verifies against a verification method of the `authorizedBy` DID document, resolved as of the KB-JWT `iat` + (see EVES-009 key rotation consideration). The KB-JWT `typ` header MUST be `kb+jwt`. +2. **Challenge binding**: The KB-JWT `nonce` MUST equal `SHA-256(authorizationMessage)` in lowercase hexadecimal encoding, computed over the message exactly as carried. +3. **Commitment extraction**: The message MUST contain exactly one statement line matching the template in section 2; the Merkle root is extracted from it. +4. **Inclusion**: The credential's leaf, recomputed from its payload with `evidence` and `proof` removed, MUST fold to the committed root through the `merkleProof` path. +5. **Issuer binding**: When the issued credential is an EVES-008 identity credential, `authorizedBy` MUST equal the credential's `issuer`. + +If any check fails, the evidence MUST be considered invalid. + +A Downstream Verifier MUST treat the KB-JWT `sd_hash` and `aud` claims as opaque: the presentation they refer to is not available, and no verification decision may be based on them. +This is the derived-artifact check profile required by EVES-009 section 6. + +### 6. Security Considerations + +The EVES-009 security considerations apply. +In addition: + +- **Replay across batches**: The ceremony nonce and timestamp inside the hashed message guarantee a unique challenge per ceremony, so an authorization KB-JWT can never be replayed for a different batch — even one committing to an identical root. +- **Historical key resolution**: Downstream Verifiers MUST resolve the `authorizedBy` DID document as of the KB-JWT `iat`. Later key rotation or admin offboarding does not retroactively invalidate evidence that was validly authorized. +- **Audience binding**: The intake `aud` check prevents an authorization obtained by one verifier from being forwarded to and accepted by another. +- **Unauthorized issuance detection**: Because every Downstream Verifier checks the evidence, a Signing Service that issues credentials without authorization produces detectably invalid credentials — it cannot forge the admin's wallet signature. +- **Evidence integrity**: The issuer signature over the credential covers the embedded evidence, making removal or substitution of evidence tamper-evident. + +### 7. Privacy Considerations + +The EVES-009 privacy considerations apply. +In addition: + +- **Message content**: The authorization message SHOULD contain no personal data beyond the Authorizer's DID. The batch is referenced only through its Merkle root. +- **Batch opacity**: An inclusion proof reveals the batch size and sibling digests, but not the contents of other credentials in the batch — the digests are preimage-resistant hashes. +- **Evidence visibility**: The evidence travels with the credential and is visible to every party the credential is presented to. + It reveals the authorization ceremony metadata (Authorizer DID, batch size, timestamp) and nothing about the credential subject beyond what the credential itself discloses. + +## Backwards Compatibility + +This specification introduces a new mechanism and does not modify any existing EVES. +It instantiates the EVES-009 evidence protocol for credential issuance and is compatible with the credential and identity framework defined in [EVES-008](../EVES-008/eves-008.md). + +## References + +1. **EVES-001**: [ENVITED-X Ecosystem Specification Process](../EVES-001/eves-001.md) +2. **EVES-002**: [ENVITED-X Data Space Architecture Overview](../EVES-002/eves-002.md) +3. **EVES-008**: [ENVITED-X SimpulseID Credential and Identity Framework](../EVES-008/eves-008.md) +4. **EVES-009**: [ENVITED-X Evidence-Based Consent Using Verifiable Presentations](../EVES-009/eves-009.md) +5. **OpenID for Verifiable Presentations (OID4VP)**: [Specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html) +6. **RFC 9901 (SD-JWT-based Verifiable Credentials)**: [Specification](https://www.rfc-editor.org/rfc/rfc9901) +7. **W3C Decentralized Identifiers (DIDs)**: [Specification](https://www.w3.org/TR/did-core/) +8. **EIP-4361 (Sign-In with Ethereum / SIWE)**: [Specification](https://eips.ethereum.org/EIPS/eip-4361) +9. **RFC 2119**: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) +10. **Harbour Batched Credential Evidence Specification**: [Specification](https://github.com/reachhaven/harbour-credentials/blob/main/docs/specs/batched-credential-evidence.md) + +## Implementation + +A reference implementation exists in **[harbour-credentials](https://github.com/reachhaven/harbour-credentials)** (Python and TypeScript with feature parity), covering evidence creation, the authorization message grammar, Merkle tree construction, and both verification tiers. +The mechanism is deployed in the [ENVITED-X Data Space](https://staging.envited-x.net), where the intake ceremony runs through the gatehouse signature API. diff --git a/EVES/SUMMARY.md b/EVES/SUMMARY.md index 71023fc..c6436ad 100644 --- a/EVES/SUMMARY.md +++ b/EVES/SUMMARY.md @@ -15,3 +15,4 @@ - [EVES-007: ENVITED-X Blockchain Identifier URN Schema](./EVES-007/eves-007.md) - [EVES-008: ENVITED-X SimpulseID Credential and Identity Framework](./EVES-008/eves-008.md) - [EVES-009: ENVITED-X Evidence-Based Consent Using Verifiable Presentations](./EVES-009/eves-009.md) +- [EVES-010: ENVITED-X Credential Issuance Authorization via Embedded Evidence](./EVES-010/eves-010.md) diff --git a/README.md b/README.md index de026bf..710c397 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,15 @@ The process on how to write, submit or change specifications in defined in [EVES ## EVES Overview -| Number | Title | Type | Status | -| ---------------------------------- | --------------------------------------------------------------- | --------- | ------ | -| [001](./EVES/EVES-001/eves-001.md) | ENVITED-X Ecosystem Specification Process | Process | Review | -| [002](./EVES/EVES-002/eves-002.md) | ENVITED-X Data Space Architecture Overview | Standards | Draft | -| [003](./EVES/EVES-003/eves-003.md) | ENVITED-X Asset Definition and Upload Process | Standards | Review | -| [004](./EVES/EVES-004/eves-004.md) | ENVITED-X Roles and Responsibilities of EVES Editors | Process | Review | -| [005](./EVES/EVES-005/eves-005.md) | ENVITED-X Contract Negotiation Process | Process | Review | -| [006](./EVES/EVES-006/eves-006.md) | ENVITED-X Scaling Architecture | Process | Draft | -| [007](./EVES/EVES-007/eves-007.md) | ENVITED-X Blockchain Identifier URN Schema | Standards | Draft | -| [008](./EVES/EVES-008/eves-008.md) | ENVITED-X SimpulseID Credential and Identity Framework | Standards | Draft | -| [009](./EVES/EVES-009/eves-009.md) | ENVITED-X Evidence-Based Consent Using Verifiable Presentations | Standards | Draft | +| Number | Title | Type | Status | +| ---------------------------------- | ----------------------------------------------------------------- | --------- | ------ | +| [001](./EVES/EVES-001/eves-001.md) | ENVITED-X Ecosystem Specification Process | Process | Review | +| [002](./EVES/EVES-002/eves-002.md) | ENVITED-X Data Space Architecture Overview | Standards | Draft | +| [003](./EVES/EVES-003/eves-003.md) | ENVITED-X Asset Definition and Upload Process | Standards | Review | +| [004](./EVES/EVES-004/eves-004.md) | ENVITED-X Roles and Responsibilities of EVES Editors | Process | Review | +| [005](./EVES/EVES-005/eves-005.md) | ENVITED-X Contract Negotiation Process | Process | Review | +| [006](./EVES/EVES-006/eves-006.md) | ENVITED-X Scaling Architecture | Process | Draft | +| [007](./EVES/EVES-007/eves-007.md) | ENVITED-X Blockchain Identifier URN Schema | Standards | Draft | +| [008](./EVES/EVES-008/eves-008.md) | ENVITED-X SimpulseID Credential and Identity Framework | Standards | Draft | +| [009](./EVES/EVES-009/eves-009.md) | ENVITED-X Evidence-Based Consent Using Verifiable Presentations | Standards | Draft | +| [010](./EVES/EVES-010/eves-010.md) | ENVITED-X Credential Issuance Authorization via Embedded Evidence | Standards | Draft | From 280f058a61e130572a15a3defc5ab77fcaab009b Mon Sep 17 00:00:00 2001 From: felix hoops <9974641+flhps@users.noreply.github.com> Date: Thu, 16 Jul 2026 15:45:25 +0200 Subject: [PATCH 7/8] chore(EVES-009): promote EVES-009 and EVES-010 to Review status Co-Authored-By: Claude Fable 5 --- EVES/EVES-009/eves-009.md | 2 +- EVES/EVES-010/eves-010.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/EVES/EVES-009/eves-009.md b/EVES/EVES-009/eves-009.md index 3d2816c..2601e6c 100644 --- a/EVES/EVES-009/eves-009.md +++ b/EVES/EVES-009/eves-009.md @@ -3,7 +3,7 @@ eves-identifier: 009 title: ENVITED-X Evidence-Based Consent Using Verifiable Presentations author: Felix Hoops (@flhps) discussions-to: https://github.com/ASCS-eV/EVES/issues/ -status: Draft +status: Review type: Standards created: 2026-03-17 requires: ["EVES-001", "EVES-002"] diff --git a/EVES/EVES-010/eves-010.md b/EVES/EVES-010/eves-010.md index ed483d6..2a824fe 100644 --- a/EVES/EVES-010/eves-010.md +++ b/EVES/EVES-010/eves-010.md @@ -3,7 +3,7 @@ eves-identifier: "010" title: ENVITED-X Credential Issuance Authorization via Embedded Evidence author: Felix Hoops (@flhps) discussions-to: https://github.com/ASCS-eV/EVES/issues/ -status: Draft +status: Review type: Standards created: 2026-07-16 requires: ["EVES-001", "EVES-002", "EVES-008", "EVES-009"] From 8a5eea233b96e98862c07f395780cef258387852 Mon Sep 17 00:00:00 2001 From: felix hoops <9974641+flhps@users.noreply.github.com> Date: Thu, 16 Jul 2026 17:26:52 +0200 Subject: [PATCH 8/8] fix(EVES-009/EVES-010): address review findings - Cite SD-JWT VC (draft-ietf-oauth-sd-jwt-vc) for dc+sd-jwt; correct the RFC 9901 reference title to Selective Disclosure for JSON Web Tokens - Replace the dead Harbour spec file link with the harbour-credentials repository as reference implementation - Pin lowercase hexadecimal challenge encoding in the EVES-009 profile - Add trusted-display security consideration (message shown by Requester, not wallet) and fix the EVES-010 flow step that claimed otherwise - Remove zero-VC VPs; consent-only interactions present a minimal identity credential via a normal OID4VP interaction - Anchor KB-JWT iat at intake (clock skew + key currency checks) and document the residual trust in the Signing Service - Add downstream batch size consistency check bounding merkleProof length by ceil(log2(N)) and document the understatement risk - Align README status with frontmatter (Review) and resolve all Vale errors and warnings in both specs Co-Authored-By: Claude Fable 5 --- EVES/EVES-009/eves-009.md | 33 ++++++++++++++--------- EVES/EVES-010/eves-010.md | 57 ++++++++++++++++++++++++--------------- README.md | 4 +-- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/EVES/EVES-009/eves-009.md b/EVES/EVES-009/eves-009.md index 2601e6c..dcbd0bf 100644 --- a/EVES/EVES-009/eves-009.md +++ b/EVES/EVES-009/eves-009.md @@ -14,7 +14,7 @@ replaces: None This specification defines a protocol for generating and verifying cryptographic evidence of user consent in the ENVITED-X Data Space. It uses Verifiable Presentations (VPs) via OID4VP as the evidence format, binding consent to a specific action through a challenge-response mechanism. -The protocol enables services to act on behalf of users (e.g., submitting blockchain transactions or finalizing contracts) while providing independently verifiable proof that the user authorized the action. +The protocol enables services to act on behalf of users (for example, submitting blockchain transactions or finalizing contracts) while providing independently verifiable proof that the user authorized the action. ## Motivation @@ -104,19 +104,22 @@ If any of these checks fail, the evidence MUST be considered invalid. ### 4. VP-Based Evidence (SD-JWT VC Profile) This specification defines the first concrete evidence type using Verifiable Presentations. -This profile is defined **only** for Verifiable Credentials in the SD-JWT VC format (`dc+sd-jwt`, see [RFC 9901](https://www.rfc-editor.org/rfc/rfc9901)). +This profile is defined **only** for Verifiable Credentials in the SD-JWT VC format (`dc+sd-jwt`, see [SD-JWT VC](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/)). +SD-JWT VC builds on the SD-JWT mechanism defined in [RFC 9901](https://www.rfc-editor.org/rfc/rfc9901). Verifiable Presentations using any other credential format are out of scope for this profile; a future EVES MAY define additional profiles for them. The profile is designed around a practical constraint: identity wallets do not produce arbitrary signatures. The only signature obtainable from a wallet is the Key Binding JWT (KB-JWT) of an OID4VP presentation. This profile therefore uses the KB-JWT as the signature object and carries the challenge in a field the wallet signs as part of every presentation: -- The **challenge** is the SHA-256 hash of the message, computed over the exact bytes presented to the Holder. +- The **challenge** is the SHA-256 hash of the message, computed over the exact bytes presented to the Holder and encoded as lowercase hexadecimal. The message is carried verbatim alongside the evidence and hashed as received; Verifiers MUST NOT re-render or normalize it. When a message must be regenerated from structured data rather than carried verbatim (for example, a JSON object), implementations SHOULD use a deterministic serialization such as [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785) so that independent implementations derive an identical challenge. - The **signature object** is a Verifiable Presentation (VP) of one or more `dc+sd-jwt` credentials. The evidence is the VP's KB-JWT, and the challenge is carried in the KB-JWT key-binding `nonce`. -- The VP contains zero or more Verifiable Credentials (VCs). When VCs are present, they prove the Holder's identity and attributes. When no VCs are included, the VP serves as a pure consent proof — the Holder's key binding alone demonstrates authorization. +- The VP contains one or more Verifiable Credentials (VCs) that prove the Holder's identity and attributes. + Because a KB-JWT is only defined relative to a presented SD-JWT, every presentation includes at least one credential. + A consent-only interaction is a normal OID4VP interaction in which the Requester requests a minimal identity credential, for example a natural person credential. The challenge is bound to the evidence through the KB-JWT key-binding `nonce`. This is the binding mechanism that ties the VP to the specific action. @@ -132,7 +135,7 @@ The Requester communicates what VCs are needed as part of the standard OID4VP fl The following sequence describes the VP-based evidence creation flow using [OpenID for Verifiable Presentations (OID4VP)](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html): -1. The Requester displays a **message**, the **challenge** derived from it, and a way to verify this challenge. The Requester also provides an OID4VP Authorization Request, usually via QR-Code. +1. The Requester displays a **message**, the **challenge** derived from it, and a way to verify this challenge. The Requester also provides an OID4VP Authorization Request, for example via QR code. 2. The Holder ingests the request and the Holder's wallet downloads the request object containing the **challenge** and requested VCs. 3. The Holder selects matching VCs, reviews the challenge, and provides consent. 4. The wallet creates a VP with the challenge as the `nonce` and submits it via `direct_post` to the Requester. @@ -156,10 +159,11 @@ sequenceDiagram For VP-based evidence, the Verifier MUST perform the following checks: -1. **VP signature verification**: The VP signature is verified against the Holder's DID (see [W3C Decentralized Identifiers](https://www.w3.org/TR/did-core/)). +1. **Key binding verification**: The KB-JWT signature is verified against the confirmation (`cnf`) key of the presented SD-JWT per [RFC 9901](https://www.rfc-editor.org/rfc/rfc9901). + When Holder keys are anchored in DID documents (see [W3C Decentralized Identifiers](https://www.w3.org/TR/did-core/)), the `cnf` key MUST correspond to a verification method of the Holder's DID. 2. **Credential verification**: Each `dc+sd-jwt` credential inside the VP is independently verified, including issuer signature validation and disclosure hash validation per [RFC 9901](https://www.rfc-editor.org/rfc/rfc9901). -3. **VC requirement check**: When VCs are present, they MUST satisfy the requirements that the Requester specified in the OID4VP request. When no VCs are present (pure consent VP), this check is skipped. -4. **Challenge binding**: The KB-JWT key-binding `nonce` MUST equal `hash(message)`, and the KB-JWT `sd_hash` binding ([RFC 9901](https://www.rfc-editor.org/rfc/rfc9901) §4.3.1) MUST be verified. This binds the evidence to the specific action. +3. **VC requirement check**: The presented VCs MUST satisfy the requirements that the Requester specified in the OID4VP request. +4. **Challenge binding**: The KB-JWT key-binding `nonce` MUST equal the challenge derived from the message as defined in section 4, and the KB-JWT `sd_hash` binding ([RFC 9901](https://www.rfc-editor.org/rfc/rfc9901) §4.3.1) MUST be verified. This binds the evidence to the specific action. 5. **Holder verification** (OPTIONAL): If a specific Holder was expected, the VP subject MUST match the expected Holder's identifier. If any check fails, the evidence MUST be considered invalid. @@ -184,6 +188,10 @@ The following considerations are specific to the VP-based profile: - **Transport security**: OID4VP requests and responses MUST be transmitted over TLS. Implementations SHOULD use signed authorization requests to prevent tampering. - **Credential freshness**: Verifiers SHOULD check the revocation status of presented VCs. +- **Trusted display**: The wallet displays only the challenge — an opaque hash — while the message itself is displayed by the Requester outside the wallet, for example on a website. + The binding between what the Holder read and what the wallet signed therefore depends on the honesty of the Requester's display. + Requesters MUST display the message together with the challenge and a way for the Holder to independently recompute the challenge from the message. + Moving the message display into the wallet requires the OID4VP `transaction_data` mechanism, which remains future work until wallet support exists (see section 1). ### 8. Privacy Considerations @@ -194,7 +202,7 @@ The following consideration applies to the generic evidence model: The following considerations are specific to the VP-based profile: - **Selective disclosure**: Because the profile uses SD-JWT VCs, Holders present only the claims required by the policy. All other claims are redacted from the presentation. -- **Consent-only evidence**: When the policy does not require identity attributes, implementations SHOULD use zero-VC VPs to minimize data exposure. The Holder's key binding alone provides proof of consent. +- **Consent-only evidence**: When the policy does not require specific attributes, Requesters SHOULD request a minimal identity credential (for example, a natural person credential) and Holders SHOULD redact all claims not required by the policy. - **Storage protection**: Stored evidence contains credential data and MUST be protected with appropriate access controls. Access to stored evidence SHOULD be limited to authorized parties on a need-to-know basis. ## Backwards Compatibility @@ -211,9 +219,10 @@ It is compatible with the existing VC, DID, and wallet infrastructure described 5. **W3C Decentralized Identifiers (DIDs)**: [Specification](https://www.w3.org/TR/did-core/) 6. **EIP-4361 (Sign-In with Ethereum / SIWE)**: [Specification](https://eips.ethereum.org/EIPS/eip-4361) 7. **RFC 2119**: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) -8. **RFC 9901 (SD-JWT-based Verifiable Credentials)**: [Specification](https://www.rfc-editor.org/rfc/rfc9901) -9. **RFC 8785 (JSON Canonicalization Scheme)**: [Specification](https://www.rfc-editor.org/rfc/rfc8785) -10. **EVES-010**: [ENVITED-X Credential Issuance Authorization via Embedded Evidence](../EVES-010/eves-010.md) +8. **RFC 9901 (Selective Disclosure for JSON Web Tokens)**: [Specification](https://www.rfc-editor.org/rfc/rfc9901) +9. **SD-JWT-based Verifiable Credentials (SD-JWT VC)**: [Specification](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/) +10. **RFC 8785 (JSON Canonicalization Scheme)**: [Specification](https://www.rfc-editor.org/rfc/rfc8785) +11. **EVES-010**: [ENVITED-X Credential Issuance Authorization via Embedded Evidence](../EVES-010/eves-010.md) ## Implementation diff --git a/EVES/EVES-010/eves-010.md b/EVES/EVES-010/eves-010.md index 2a824fe..f1aa423 100644 --- a/EVES/EVES-010/eves-010.md +++ b/EVES/EVES-010/eves-010.md @@ -23,13 +23,13 @@ The signing service executes the credential lifecycle but must not decide anythi This creates two requirements in tension: -- **One signature**: A common operation is an organization authorizing credentials for all of its members at once. The authorizing admin should sign once, not once per credential. +- **One signature**: A common operation is an organization authorizing credentials for all of its members at once. The authorizing administrator should sign once, not once per credential. - **Self-contained verification**: Every issued credential must independently prove that it was covered by that authorization — without access to the rest of the batch and without contacting the issuing infrastructure. This specification resolves the tension with a cryptographic commitment, using the multi-action message pattern from EVES-009: -the admin consents to a message committing to a Merkle root over the whole batch, and each issued credential carries an inclusion proof binding its own payload to that root. +the administrator consents to a message committing to a Merkle root over the whole batch, and each issued credential carries an inclusion proof binding its own payload to that root. The resulting evidence is embedded in the credential itself and serves as a durable, non-repudiable audit trail of who approved the issuance. -A signing service that issued a credential nobody authorized is detectable by any Verifier, because it cannot forge the admin's wallet signature. +A signing service that issued a credential nobody authorized is detectable by any Verifier, because it cannot forge the administrator's wallet signature. ## Specification @@ -37,15 +37,15 @@ A signing service that issued a credential nobody authorized is detectable by an This specification refines the EVES-009 roles for the issuance setting: -- **Authorizer**: The issuing organization, identified by its DID. The authorization signature is made by a human admin whose wallet key is a verification method of that DID. The Authorizer is the EVES-009 **Holder**. +- **Authorizer**: The issuing organization, identified by its DID. The authorization signature is made by a human administrator whose wallet key is a verification method of that DID. The Authorizer is the EVES-009 **Holder**. - **Signing Service**: The service that assembles the batch, obtains the authorization, embeds the evidence, and executes the credential proofs under a mandate from the issuer. The Signing Service is the EVES-009 **Requester**. -- **Intake Verifier**: The OID4VP verifier endpoint that receives the admin's presentation during the authorization ceremony and performs full EVES-009 verification. +- **Intake Verifier**: The OID4VP verifier endpoint that receives the administrator's presentation during the authorization ceremony and performs full EVES-009 verification. - **Downstream Verifier**: Any relying party that later verifies an issued credential and its embedded evidence in isolation. ### 2. Authorization Message The authorization message is a human-readable text string following the EVES-009 message requirements, styled after [EIP-4361 (Sign-In with Ethereum)](https://eips.ethereum.org/EIPS/eip-4361). -It is composed by the Signing Service, displayed verbatim on the admin's wallet consent screen, and carried byte-exact in the evidence. +It is composed by the Signing Service, displayed verbatim to the administrator during the authorization ceremony (see the trusted-display consideration in section 6), and carried byte-exact in the evidence. The message MUST contain exactly one statement line matching the following template: @@ -54,20 +54,21 @@ I authorize the issuance of credential(s) committed to by Merkle root ``` Where `` is the decimal batch size and `` is the base64url-encoded (unpadded, 43 characters) SHA-256 Merkle root over the batch. -Verifiers extract the root only through this template. +Only `` and `` are variable; all other characters of the statement line, including the literal `credential(s)`, are fixed. +Verifiers extract the root and the batch size only through this template. All other message content — domain, Authorizer address, ceremony nonce, and timestamp — is ceremony metadata. It is part of the hashed message but not interpreted by Verifiers. The ceremony nonce and timestamp inside the hashed message make every ceremony's challenge unique, satisfying the EVES-009 replay prevention requirement. -Following EVES-009, the message is hashed exactly as received: the **challenge** is `SHA-256(message)` in lowercase hexadecimal encoding, and Verifiers MUST NOT re-render or normalize the message. +Following the EVES-009 profile, the message is hashed exactly as received: the **challenge** is `SHA-256(message)` encoded as lowercase hexadecimal, and Verifiers MUST NOT re-render or normalize the message. ### 3. Evidence Creation -1. The Signing Service computes a leaf hash for each credential payload in the batch. The leaf is computed over the payload with its `evidence` and `proof` members removed, so the leaf is independent of the evidence that will later embed the proof of its own inclusion. +1. The Signing Service computes a leaf hash for each credential payload in the batch. The leaf is computed over the payload with its `evidence` and `proof` members removed, so the leaf is independent of the evidence that later embeds the proof of its own inclusion. 2. The Signing Service builds a Merkle tree over the leaves and composes the authorization message committing to its root (see section 2). -3. The admin provides consent through the EVES-009 VP-based flow: the wallet receives an OID4VP presentation request whose `nonce` is the challenge, displays the message, - and responds by presenting the organization's LegalPersonCredential (see EVES-008) with a KB-JWT signed by the admin's wallet key. +3. The administrator provides consent through the EVES-009 VP-based flow: the Signing Service's interface displays the message and the challenge, and the wallet receives an + OID4VP presentation request whose `nonce` is the challenge and responds by presenting the organization's LegalPersonCredential (see EVES-008) with a KB-JWT signed by the administrator's wallet key. 4. The Intake Verifier performs full EVES-009 verification of the presentation (see section 5.1). 5. For each credential in the batch, the Signing Service constructs an evidence object (see section 4) and embeds it in the credential's `evidence` array before the credential is signed as `dc+sd-jwt`. @@ -83,9 +84,7 @@ Each issued credential carries one evidence object with the following components - **`authorizationMessage`**: The verbatim authorization message — the EVES-009 message. - **`merkleProof`**: The credential's inclusion proof — the ordered list of sibling digests from the credential's leaf up to the committed root. -The exact Merkle tree construction, leaf encoding, and JSON-LD vocabulary are specified in the -[Harbour Batched Credential Evidence specification](https://github.com/reachhaven/harbour-credentials/blob/main/docs/specs/batched-credential-evidence.md), -which serves as the normative wire-format reference for this EVES. +The exact Merkle tree construction, leaf encoding, and JSON-LD vocabulary follow the [harbour-credentials](https://github.com/reachhaven/harbour-credentials) reference implementation (see Implementation). Because the issuer's `dc+sd-jwt` signature covers the credential payload including the `evidence` array, the embedded evidence is tamper-evident: it cannot be stripped or replaced without invalidating the credential. @@ -98,6 +97,10 @@ Verification happens at two distinct points in time, by two distinct parties, wi The Intake Verifier holds the complete presentation and MUST perform the full EVES-009 VP-based verification, including credential verification, `sd_hash` validation, and challenge binding. Additionally, the Intake Verifier MUST reject an authorization whose KB-JWT `aud` is not its own identifier. +The Intake Verifier MUST also reject an authorization whose KB-JWT `iat` deviates from the ceremony time by more than an acceptable clock skew, +and MUST confirm that the signing key is a valid verification method of the Authorizer's DID document at ceremony time. +These intake checks anchor `iat` to real time; Downstream Verifiers depend on them (see section 6). + #### 5.2 Downstream Verification A Downstream Verifier verifies one issued credential and its evidence in isolation. @@ -108,7 +111,9 @@ It holds only the derived evidence artifact (see section 4), not the presentatio 2. **Challenge binding**: The KB-JWT `nonce` MUST equal `SHA-256(authorizationMessage)` in lowercase hexadecimal encoding, computed over the message exactly as carried. 3. **Commitment extraction**: The message MUST contain exactly one statement line matching the template in section 2; the Merkle root is extracted from it. 4. **Inclusion**: The credential's leaf, recomputed from its payload with `evidence` and `proof` removed, MUST fold to the committed root through the `merkleProof` path. -5. **Issuer binding**: When the issued credential is an EVES-008 identity credential, `authorizedBy` MUST equal the credential's `issuer`. +5. **Batch size consistency**: The number of digests in `merkleProof` MUST NOT exceed `ceil(log2())`, where `` is the batch size extracted from the statement line + (zero digests when `` is 1). This bounds the size of the committed tree by the batch size the administrator approved. +6. **Issuer binding**: When the issued credential is an EVES-008 identity credential, `authorizedBy` MUST equal the credential's `issuer`. If any check fails, the evidence MUST be considered invalid. @@ -121,9 +126,16 @@ The EVES-009 security considerations apply. In addition: - **Replay across batches**: The ceremony nonce and timestamp inside the hashed message guarantee a unique challenge per ceremony, so an authorization KB-JWT can never be replayed for a different batch — even one committing to an identical root. -- **Historical key resolution**: Downstream Verifiers MUST resolve the `authorizedBy` DID document as of the KB-JWT `iat`. Later key rotation or admin offboarding does not retroactively invalidate evidence that was validly authorized. +- **Historical key resolution**: Downstream Verifiers MUST resolve the `authorizedBy` DID document as of the KB-JWT `iat`. Later key rotation or administrator offboarding does not retroactively invalidate evidence that was validly authorized. +- **`iat` trust**: The KB-JWT `iat` is asserted by the signer and cannot be independently verified by a Downstream Verifier: a compromised and later rotated key could sign evidence backdated into its validity window. + The intake checks in section 5.1 anchor `iat` to the actual ceremony time, so downstream verification includes residual trust in the Signing Service having performed those checks before issuing. +- **Batch size understatement**: Without the batch size consistency check in section 5.2, `` would be verified by no one, and a malicious Signing Service could display a small batch size to the administrator while committing to a larger tree. + The check bounds the size of the committed tree by the approved ``. +- **Trusted display**: Per the EVES-009 trusted-display consideration, the message and challenge are displayed by the Signing Service's interface rather than by the wallet. + The administrator therefore relies on that interface to faithfully present the batch size and Merkle root being authorized. + Adopting the OID4VP `transaction_data` mechanism, once wallet support exists, moves this display into the wallet and removes that reliance. - **Audience binding**: The intake `aud` check prevents an authorization obtained by one verifier from being forwarded to and accepted by another. -- **Unauthorized issuance detection**: Because every Downstream Verifier checks the evidence, a Signing Service that issues credentials without authorization produces detectably invalid credentials — it cannot forge the admin's wallet signature. +- **Unauthorized issuance detection**: Because every Downstream Verifier checks the evidence, a Signing Service that issues credentials without authorization produces detectably invalid credentials — it cannot forge the administrator's wallet signature. - **Evidence integrity**: The issuer signature over the credential covers the embedded evidence, making removal or substitution of evidence tamper-evident. ### 7. Privacy Considerations @@ -148,11 +160,12 @@ It instantiates the EVES-009 evidence protocol for credential issuance and is co 3. **EVES-008**: [ENVITED-X SimpulseID Credential and Identity Framework](../EVES-008/eves-008.md) 4. **EVES-009**: [ENVITED-X Evidence-Based Consent Using Verifiable Presentations](../EVES-009/eves-009.md) 5. **OpenID for Verifiable Presentations (OID4VP)**: [Specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html) -6. **RFC 9901 (SD-JWT-based Verifiable Credentials)**: [Specification](https://www.rfc-editor.org/rfc/rfc9901) -7. **W3C Decentralized Identifiers (DIDs)**: [Specification](https://www.w3.org/TR/did-core/) -8. **EIP-4361 (Sign-In with Ethereum / SIWE)**: [Specification](https://eips.ethereum.org/EIPS/eip-4361) -9. **RFC 2119**: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) -10. **Harbour Batched Credential Evidence Specification**: [Specification](https://github.com/reachhaven/harbour-credentials/blob/main/docs/specs/batched-credential-evidence.md) +6. **RFC 9901 (Selective Disclosure for JSON Web Tokens)**: [Specification](https://www.rfc-editor.org/rfc/rfc9901) +7. **SD-JWT-based Verifiable Credentials (SD-JWT VC)**: [Specification](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/) +8. **W3C Decentralized Identifiers (DIDs)**: [Specification](https://www.w3.org/TR/did-core/) +9. **EIP-4361 (Sign-In with Ethereum / SIWE)**: [Specification](https://eips.ethereum.org/EIPS/eip-4361) +10. **RFC 2119**: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) +11. **harbour-credentials**: [Reference implementation](https://github.com/reachhaven/harbour-credentials) ## Implementation diff --git a/README.md b/README.md index 710c397..49d96c1 100644 --- a/README.md +++ b/README.md @@ -20,5 +20,5 @@ The process on how to write, submit or change specifications in defined in [EVES | [006](./EVES/EVES-006/eves-006.md) | ENVITED-X Scaling Architecture | Process | Draft | | [007](./EVES/EVES-007/eves-007.md) | ENVITED-X Blockchain Identifier URN Schema | Standards | Draft | | [008](./EVES/EVES-008/eves-008.md) | ENVITED-X SimpulseID Credential and Identity Framework | Standards | Draft | -| [009](./EVES/EVES-009/eves-009.md) | ENVITED-X Evidence-Based Consent Using Verifiable Presentations | Standards | Draft | -| [010](./EVES/EVES-010/eves-010.md) | ENVITED-X Credential Issuance Authorization via Embedded Evidence | Standards | Draft | +| [009](./EVES/EVES-009/eves-009.md) | ENVITED-X Evidence-Based Consent Using Verifiable Presentations | Standards | Review | +| [010](./EVES/EVES-010/eves-010.md) | ENVITED-X Credential Issuance Authorization via Embedded Evidence | Standards | Review |