Evidence in Harbour Credentials¶
Evidence is a W3C VC Data Model concept that provides cryptographic proof of how an issuer verified claims or why a holder is authorized to perform an action.
What is Evidence?¶
When a credential is issued or a presentation is made, the evidence field can contain supporting proof that:
- For issuance: Shows what the issuer relied upon to verify claims
- For presentations: Shows why the holder is authorized to perform an action
Evidence creates an audit trail — allowing third parties to verify not just that something happened, but how it was validated.
Harbour Evidence Types¶
CredentialEvidence¶
Proves that an authorizing party approved the credential issuance via OID4VP. The embedded VP carries the authorization proof — a Verifiable Presentation containing the authorizer's credential.
The Harbour Signing Service is the sole issuer of all credentials. Evidence VPs establish the chain of authorization:
Use case 1 — Trust Anchor authorizes org (LegalPersonCredential): The Trust Anchor presents a VP containing its self-signed LinkedCredentialService credential (service endpoint proof, root of trust — analogous to a root CA certificate). The Signing Service verifies this VP and issues the org's credential with it as evidence.
Use case 2 — Org authorizes employee (NaturalPersonCredential): The organization presents a VP containing its LegalPersonCredential (SD-JWT with sensitive fields redacted — registration number and addresses hidden, compliance status disclosed). The Signing Service verifies this VP and issues the employee's credential with it as evidence.
{
"type": "harbour:CredentialEvidence",
"verifiablePresentation": {
"@context": ["https://www.w3.org/ns/credentials/v2"],
"type": ["VerifiablePresentation", "harbour:VerifiablePresentation"],
"holder": "did:ethr:0x14a34:0x4d6246a7d1e60caa44b75e3af9b37ac8d6442774",
"verifiableCredential": [
{
"@context": ["https://www.w3.org/ns/credentials/v2", "https://w3id.org/reachhaven/harbour/core/v1/"],
"type": ["VerifiableCredential"],
"issuer": "did:ethr:0x14a34:0x4d6246a7d1e60caa44b75e3af9b37ac8d6442774",
"validFrom": "2024-01-01T00:00:00Z",
"credentialSubject": {
"id": "did:ethr:0x14a34:0x4d6246a7d1e60caa44b75e3af9b37ac8d6442774",
"type": "harbour:LinkedCredentialService",
"didcore:serviceEndpoint": {"id": "https://resolver.harbour.id/credentials/did:ethr:0x14a34:0x4d6246a7d1e60caa44b75e3af9b37ac8d6442774"}
}
}
]
}
}
What it proves: The authorizing party (Trust Anchor or org) approved the Signing Service to issue a credential for the target subject. The chain of trust flows: Trust Anchor (LinkedCredentialService) → org (LegalPersonCredential) → employee (NaturalPersonCredential).
DelegatedSignatureEvidence¶
Evidence on a receipt credential (SD-JWT-VC) that a signing service executed a transaction with the user's explicit consent. The consent VP uses SD-JWT with PII redacted. Transaction data is a disclosable claim enabling three-layer privacy (public / authorized / full audit).
Use case: A signing service issues a receipt credential after executing a blockchain purchase on behalf of a user.
{
"type": "harbour:DelegatedSignatureEvidence",
"verifiablePresentation": "<SD-JWT VP with redacted PII>",
"delegatedTo": "did:ethr:0x14a34:0x31f1ca3dc5da9f83f360d805662d11a418950202",
"transaction_data": {
"type": "harbour.delegate:data.purchase",
"credential_ids": ["harbour_natural_person"],
"transaction_data_hashes_alg": ["sha-256"],
"nonce": "da9b1009",
"iat": 1771934400,
"txn": {
"asset_id": "urn:uuid:550e8400-e29b-41d4-a716-446655440000",
"price": "100",
"currency": "ENVITED",
"marketplace": "did:ethr:0x14a34:0x89fe5e7f506d992f76bcba309773c0ee3ee6039c"
}
},
"challenge": "da9b1009 HARBOUR_DELEGATE c3d4ba771c1103935ab4121874c4b3a78c8471719c80f60d59ca5811e232089b"
}
What it proves: The user explicitly consented to the specific transaction, and the signing service executed it on their behalf.
See Delegated Signing for the complete flow.
Three-Layer Privacy Model¶
The receipt credential is an SD-JWT-VC. Transaction data and identity details are selectively disclosable:
| Layer | Audience | What's Visible |
|---|---|---|
| Layer 1 — Public | Everyone | CRSet entry (credential exists), transaction_data_hash on-chain, DID identifier, KB-JWT signature valid |
| Layer 2 — Authorized | Auditor | Transaction details (asset, price, marketplace), consent VP hash verification |
| Layer 3 — Full Audit | Compliance | User identity (name, email, organization), full credential chain |
When to Use Each Type¶
| Evidence Type | Use When | Example Scenario |
|---|---|---|
CredentialEvidence |
Issuing credential after authorization from a trusted party | Trust Anchor authorizes org issuance; org authorizes employee issuance |
DelegatedSignatureEvidence |
Issuing receipt after delegated action | Blockchain purchase, contract signing, access delegation |
Evidence Structure¶
All evidence types inherit from the abstract Evidence class and share:
Evidence:
abstract: true
class_uri: cred:Evidence
slots:
- type # Required: identifies the evidence type
Most evidence types include a verifiablePresentation slot containing a signed VP as proof.
Privacy Considerations¶
Evidence often contains sensitive information. For privacy-preserving audit:
- Use SD-JWT VPs: Selectively disclose only necessary claims
- Redact PII: Names, emails, etc. can be hidden while keeping DID visible
- Three-layer disclosure:
- Public: CRSet + transaction hash + signature validity
- Authorized: Transaction details (asset, price)
- Full audit: Identity details (name, email, organization)
Verification¶
When verifying credentials or presentations with evidence:
- Verify the outer signature (credential or VP)
- Verify each evidence VP signature
- Check evidence issuer trust (is the evidence issuer trusted?)
- Validate evidence freshness (timestamps, nonces)
- Check revocation status of evidence credentials
from harbour.verifier import verify_vc_jose
# Verify outer credential
result = verify_vc_jose(credential_jwt, issuer_public_key)
# Verify evidence VP
for evidence in result.get("evidence", []):
if "verifiablePresentation" in evidence:
vp = evidence["verifiablePresentation"]
# Verify VP signature...
Adding Evidence to Credentials¶
When issuing a credential with evidence:
credential = {
"@context": [...],
"type": ["VerifiableCredential", "harbour:NaturalPersonCredential"],
"issuer": "did:ethr:0x14a34:0x31f1ca3dc5da9f83f360d805662d11a418950202",
"credentialSubject": {...},
"evidence": [
{
"type": "harbour:CredentialEvidence",
"verifiablePresentation": authorization_vp_jwt
}
]
}
signed_vc = sign_vc_jose(credential, issuer_private_key)
Schema Definition¶
Evidence types are defined in linkml/harbour-core-credential.yaml:
Evidence:
abstract: true
class_uri: cred:Evidence
slots:
- type
CredentialEvidence:
is_a: Evidence
class_uri: harbour:CredentialEvidence
slots:
- verifiablePresentation
slot_usage:
verifiablePresentation:
required: true
DelegatedSignatureEvidence:
is_a: Evidence
class_uri: harbour:DelegatedSignatureEvidence
slots:
- verifiablePresentation
- delegatedTo
- transaction_data
slot_usage:
verifiablePresentation:
required: true
delegatedTo:
required: true
transaction_data:
required: true
Related Documentation¶
- Delegated Signing — Full delegated signing flow
- SD-JWT-VC — Selective disclosure credentials
- W3C VC Data Model — Evidence