|
| 1 | +--- |
| 2 | +eves-identifier: "010" |
| 3 | +title: ENVITED-X Credential Issuance Authorization via Embedded Evidence |
| 4 | +author: Felix Hoops (@flhps) |
| 5 | +discussions-to: https://github.com/ASCS-eV/EVES/issues/ |
| 6 | +status: Draft |
| 7 | +type: Standards |
| 8 | +created: 2026-07-16 |
| 9 | +requires: ["EVES-001", "EVES-002", "EVES-008", "EVES-009"] |
| 10 | +replaces: None |
| 11 | +--- |
| 12 | + |
| 13 | +## Abstract |
| 14 | + |
| 15 | +This specification applies the evidence protocol defined in [EVES-009](../EVES-009/eves-009.md) to credential issuance. |
| 16 | +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. |
| 17 | +The authorization message commits to the whole batch through a Merkle root; each credential carries the authorization signature together with its own inclusion proof. |
| 18 | + |
| 19 | +## Motivation |
| 20 | + |
| 21 | +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)). |
| 22 | +The signing service executes the credential lifecycle but must not decide anything: every issuance requires provable authorization by the issuing organization. |
| 23 | + |
| 24 | +This creates two requirements in tension: |
| 25 | + |
| 26 | +- **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. |
| 27 | +- **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. |
| 28 | + |
| 29 | +This specification resolves the tension with a cryptographic commitment, using the multi-action message pattern from EVES-009: |
| 30 | +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. |
| 31 | +The resulting evidence is embedded in the credential itself and serves as a durable, non-repudiable audit trail of who approved the issuance. |
| 32 | +A signing service that issued a credential nobody authorized is detectable by any Verifier, because it cannot forge the admin's wallet signature. |
| 33 | + |
| 34 | +## Specification |
| 35 | + |
| 36 | +### 1. Roles |
| 37 | + |
| 38 | +This specification refines the EVES-009 roles for the issuance setting: |
| 39 | + |
| 40 | +- **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**. |
| 41 | +- **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**. |
| 42 | +- **Intake Verifier**: The OID4VP verifier endpoint that receives the admin's presentation during the authorization ceremony and performs full EVES-009 verification. |
| 43 | +- **Downstream Verifier**: Any relying party that later verifies an issued credential and its embedded evidence in isolation. |
| 44 | + |
| 45 | +### 2. Authorization Message |
| 46 | + |
| 47 | +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). |
| 48 | +It is composed by the Signing Service, displayed verbatim on the admin's wallet consent screen, and carried byte-exact in the evidence. |
| 49 | + |
| 50 | +The message MUST contain exactly one statement line matching the following template: |
| 51 | + |
| 52 | +```text |
| 53 | +I authorize the issuance of <N> credential(s) committed to by Merkle root <root>. |
| 54 | +``` |
| 55 | + |
| 56 | +Where `<N>` is the decimal batch size and `<root>` is the base64url-encoded (unpadded, 43 characters) SHA-256 Merkle root over the batch. |
| 57 | +Verifiers extract the root only through this template. |
| 58 | + |
| 59 | +All other message content — domain, Authorizer address, ceremony nonce, and timestamp — is ceremony metadata. |
| 60 | +It is part of the hashed message but not interpreted by Verifiers. |
| 61 | +The ceremony nonce and timestamp inside the hashed message make every ceremony's challenge unique, satisfying the EVES-009 replay prevention requirement. |
| 62 | + |
| 63 | +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. |
| 64 | + |
| 65 | +### 3. Evidence Creation |
| 66 | + |
| 67 | +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. |
| 68 | +2. The Signing Service builds a Merkle tree over the leaves and composes the authorization message committing to its root (see section 2). |
| 69 | +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, |
| 70 | + and responds by presenting the organization's LegalPersonCredential (see EVES-008) with a KB-JWT signed by the admin's wallet key. |
| 71 | +4. The Intake Verifier performs full EVES-009 verification of the presentation (see section 5.1). |
| 72 | +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`. |
| 73 | + |
| 74 | +Only the KB-JWT is retained from the presentation. |
| 75 | +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). |
| 76 | + |
| 77 | +### 4. Evidence Structure |
| 78 | + |
| 79 | +Each issued credential carries one evidence object with the following components: |
| 80 | + |
| 81 | +- **`authorizedBy`**: The Authorizer organization's DID. |
| 82 | +- **`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. |
| 83 | +- **`authorizationMessage`**: The verbatim authorization message — the EVES-009 message. |
| 84 | +- **`merkleProof`**: The credential's inclusion proof — the ordered list of sibling digests from the credential's leaf up to the committed root. |
| 85 | + |
| 86 | +The exact Merkle tree construction, leaf encoding, and JSON-LD vocabulary are specified in the |
| 87 | +[Harbour Batched Credential Evidence specification](https://github.com/reachhaven/harbour-credentials/blob/main/docs/specs/batched-credential-evidence.md), |
| 88 | +which serves as the normative wire-format reference for this EVES. |
| 89 | + |
| 90 | +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. |
| 91 | + |
| 92 | +### 5. Verification |
| 93 | + |
| 94 | +Verification happens at two distinct points in time, by two distinct parties, with different material available. |
| 95 | + |
| 96 | +#### 5.1 Intake Verification |
| 97 | + |
| 98 | +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. |
| 99 | +Additionally, the Intake Verifier MUST reject an authorization whose KB-JWT `aud` is not its own identifier. |
| 100 | + |
| 101 | +#### 5.2 Downstream Verification |
| 102 | + |
| 103 | +A Downstream Verifier verifies one issued credential and its evidence in isolation. |
| 104 | +It holds only the derived evidence artifact (see section 4), not the presentation, and MUST perform the following checks: |
| 105 | + |
| 106 | +1. **Authorization signature**: The KB-JWT signature verifies against a verification method of the `authorizedBy` DID document, resolved as of the KB-JWT `iat` |
| 107 | + (see EVES-009 key rotation consideration). The KB-JWT `typ` header MUST be `kb+jwt`. |
| 108 | +2. **Challenge binding**: The KB-JWT `nonce` MUST equal `SHA-256(authorizationMessage)` in lowercase hexadecimal encoding, computed over the message exactly as carried. |
| 109 | +3. **Commitment extraction**: The message MUST contain exactly one statement line matching the template in section 2; the Merkle root is extracted from it. |
| 110 | +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. |
| 111 | +5. **Issuer binding**: When the issued credential is an EVES-008 identity credential, `authorizedBy` MUST equal the credential's `issuer`. |
| 112 | + |
| 113 | +If any check fails, the evidence MUST be considered invalid. |
| 114 | + |
| 115 | +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. |
| 116 | +This is the derived-artifact check profile required by EVES-009 section 6. |
| 117 | + |
| 118 | +### 6. Security Considerations |
| 119 | + |
| 120 | +The EVES-009 security considerations apply. |
| 121 | +In addition: |
| 122 | + |
| 123 | +- **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. |
| 124 | +- **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. |
| 125 | +- **Audience binding**: The intake `aud` check prevents an authorization obtained by one verifier from being forwarded to and accepted by another. |
| 126 | +- **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. |
| 127 | +- **Evidence integrity**: The issuer signature over the credential covers the embedded evidence, making removal or substitution of evidence tamper-evident. |
| 128 | + |
| 129 | +### 7. Privacy Considerations |
| 130 | + |
| 131 | +The EVES-009 privacy considerations apply. |
| 132 | +In addition: |
| 133 | + |
| 134 | +- **Message content**: The authorization message SHOULD contain no personal data beyond the Authorizer's DID. The batch is referenced only through its Merkle root. |
| 135 | +- **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. |
| 136 | +- **Evidence visibility**: The evidence travels with the credential and is visible to every party the credential is presented to. |
| 137 | + It reveals the authorization ceremony metadata (Authorizer DID, batch size, timestamp) and nothing about the credential subject beyond what the credential itself discloses. |
| 138 | + |
| 139 | +## Backwards Compatibility |
| 140 | + |
| 141 | +This specification introduces a new mechanism and does not modify any existing EVES. |
| 142 | +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). |
| 143 | + |
| 144 | +## References |
| 145 | + |
| 146 | +1. **EVES-001**: [ENVITED-X Ecosystem Specification Process](../EVES-001/eves-001.md) |
| 147 | +2. **EVES-002**: [ENVITED-X Data Space Architecture Overview](../EVES-002/eves-002.md) |
| 148 | +3. **EVES-008**: [ENVITED-X SimpulseID Credential and Identity Framework](../EVES-008/eves-008.md) |
| 149 | +4. **EVES-009**: [ENVITED-X Evidence-Based Consent Using Verifiable Presentations](../EVES-009/eves-009.md) |
| 150 | +5. **OpenID for Verifiable Presentations (OID4VP)**: [Specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html) |
| 151 | +6. **RFC 9901 (SD-JWT-based Verifiable Credentials)**: [Specification](https://www.rfc-editor.org/rfc/rfc9901) |
| 152 | +7. **W3C Decentralized Identifiers (DIDs)**: [Specification](https://www.w3.org/TR/did-core/) |
| 153 | +8. **EIP-4361 (Sign-In with Ethereum / SIWE)**: [Specification](https://eips.ethereum.org/EIPS/eip-4361) |
| 154 | +9. **RFC 2119**: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) |
| 155 | +10. **Harbour Batched Credential Evidence Specification**: [Specification](https://github.com/reachhaven/harbour-credentials/blob/main/docs/specs/batched-credential-evidence.md) |
| 156 | + |
| 157 | +## Implementation |
| 158 | + |
| 159 | +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. |
| 160 | +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. |
0 commit comments