Skip to content

AnonCreds Support

The DID WebVH Server supports publishing and resolving AnonCreds objects as Attested Resources. This enables issuers to publish AnonCreds schemas, credential definitions, revocation registry definitions, and revocation registry states using the DID WebVH method.

Overview

AnonCreds is a privacy-preserving credential system that provides: - Selective Disclosure: Reveal only specific attributes from a credential - Unlinkability: Multiple presentations cannot be correlated to the same credential - Predicate Proofs: Prove relationships (e.g., age ≥ 18) without revealing exact values - Privacy-Preserving Revocation: Check revocation status without correlation - Multi-Credential Presentations: Combine proofs from multiple credentials

The DID WebVH Server stores AnonCreds objects as AttestedResource objects, which are cryptographically signed and linked to the issuer's DID.

AnonCreds Object Types

Four types of AnonCreds objects can be published on the server:

  1. Schema: Defines the structure and attributes of a credential type
  2. Credential Definition: Contains the issuer's public keys for a specific schema
  3. Revocation Registry Definition: Defines a revocation registry for revocable credentials
  4. Revocation Registry State: Contains the current state of a revocation registry

Each object is namespaced to the issuer's DID and can be resolved using the DID WebVH resolution protocol.

Prerequisites

Before publishing AnonCreds objects, you need:

  1. An Issuer DID: A DID created on the server with a valid verificationMethod of type Multikey
  2. Witness Connection (if WEBVH_ENDORSEMENT=true): Connection to a witness service for endorsement
  3. Signing Capability: Ability to create DataIntegrityProof signatures using the eddsa-jcs-2022 cryptosuite

Creating an AttestedResource

An AnonCreds object is published as an AttestedResource with the following structure:

{
  "@context": ["https://w3id.org/security/data-integrity/v2"],
  "id": "did:webvh:{SCID}:example.com:issuer:my-did/resources/{digestMultibase}",
  "content": {
    // AnonCreds object (Schema, Credential Definition, etc.)
  },
  "metadata": {
    "resourceId": "{digestMultibase}",
    "resourceType": "AnonCredsSchema",
    "resourceName": "Example Schema"
  },
  "links": [],
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "eddsa-jcs-2022",
    "proofPurpose": "assertionMethod",
    "verificationMethod": "did:webvh:{SCID}:example.com:issuer:my-did#key-1",
    "proofValue": "..."
  }
}

Step-by-Step Process

  1. Initialize the AttestedResource
  2. Create an empty object
  3. Set @context to ["https://w3id.org/security/data-integrity/v2"]

  4. Set the Content

  5. Set the content property to your AnonCreds object (Schema, Credential Definition, etc.)

  6. Generate the Resource ID

  7. Calculate the digestMultibase of the content property
  8. Construct the resource ID: {issuer_did}/resources/{digestMultibase}
  9. Example: did:webvh:abc123:example.com:issuer:my-did/resources/zM6mH...

  10. Add Metadata (Optional but Recommended)

    {
      "resourceId": "{digestMultibase}",
      "resourceType": "AnonCredsSchema",  // or "AnonCredsCredentialDefinition", etc.
      "resourceName": "Example Schema Name"
    }
    

  11. Add Links (Optional)

  12. Add related resource links if the AnonCreds object references other resources
  13. Each link should have an id, type, and optionally digestMultibase or timestamp

  14. Sign the Resource

  15. Create a DataIntegrityProof using eddsa-jcs-2022 cryptosuite
  16. Use a verificationMethod from your issuer DID document
  17. Set proofPurpose to "assertionMethod"

  18. Obtain Witness Endorsement (if WEBVH_ENDORSEMENT=true)

  19. Request witness signature for the resource
  20. Include witness proof alongside your proof in the proof array

  21. Upload to Server

  22. POST /{namespace}/{alias}/resources
  23. Include both controller proof and witness proof (if required)

Uploading AnonCreds Objects

Example: Uploading a Schema

# 1. Create the AttestedResource
{
  "@context": ["https://w3id.org/security/data-integrity/v2"],
  "id": "did:webvh:abc123:example.com:issuer:my-did/resources/zM6mH...",
  "content": {
    "name": "Example Schema",
    "version": "1.0",
    "attrNames": ["name", "age", "email"]
  },
  "metadata": {
    "resourceId": "zM6mH...",
    "resourceType": "AnonCredsSchema",
    "resourceName": "Example Schema"
  },
  "proof": [
    {
      "type": "DataIntegrityProof",
      "cryptosuite": "eddsa-jcs-2022",
      "proofPurpose": "assertionMethod",
      "verificationMethod": "did:webvh:abc123:example.com:issuer:my-did#key-1",
      "proofValue": "..."
    },
    {
      "type": "DataIntegrityProof",
      "cryptosuite": "eddsa-jcs-2022",
      "proofPurpose": "assertionMethod",
      "verificationMethod": "did:key:z6Mk...#witness",
      "proofValue": "..."
    }
  ]
}

# 2. Upload to server
curl -X POST "https://did.example.org/issuer/my-did/resources" \
  -H "Content-Type: application/json" \
  -d '{
    "attestedResource": { ... }
  }'

Example: Uploading a Credential Definition

{
  "@context": ["https://w3id.org/security/data-integrity/v2"],
  "id": "did:webvh:abc123:example.com:issuer:my-did/resources/zM6mH...",
  "content": {
    "schemaId": "did:webvh:abc123:example.com:issuer:my-did/resources/zM6mH...",
    "tag": "default",
    "type": "CL",
    "value": {
      "primary": { ... },
      "revocation": { ... }
    }
  },
  "metadata": {
    "resourceId": "zM6mH...",
    "resourceType": "AnonCredsCredentialDefinition",
    "resourceName": "Example Credential Definition"
  },
  "proof": [ ... ]
}

Resolving AnonCreds Objects

AnonCreds objects can be resolved using the DID WebVH resolution protocol:

  1. Get the Resource ID
  2. Example: did:webvh:abc123:example.com:issuer:my-did/resources/zM6mH...

  3. Transform DID to HTTPS URL

  4. Extract the DID components: did:webvh:{SCID}:{domain}:{namespace}:{alias}
  5. Transform to: https://{domain}/{namespace}/{alias}
  6. Example: https://example.com/issuer/my-did

  7. Append Resource Path

  8. Add /resources/{digestMultibase} to the URL
  9. Example: https://example.com/issuer/my-did/resources/zM6mH...

  10. Make GET Request

    curl https://example.com/issuer/my-did/resources/zM6mH...
    

  11. Verify the Resource

  12. Verify the DataIntegrityProof signature
  13. Calculate digestMultibase of content and compare with resource ID
  14. Verify the metadata.resourceId matches (if present)
  15. Check that metadata.resourceType matches expected type

Updating AttestedResources

You can update the metadata or links of an existing resource:

  1. Retrieve the Original Resource
  2. GET the resource from the server

  3. Modify Metadata or Links

  4. Update metadata properties (e.g., resourceName)
  5. Add or remove items from links array
  6. Note: The content property is immutable

  7. Create New Proof

  8. Generate a new DataIntegrityProof with updated timestamp
  9. Obtain witness endorsement if required

  10. Update on Server

  11. PUT /{namespace}/{alias}/resources/{resource_id}
  12. Include the updated resource with new proof
curl -X PUT "https://did.example.org/issuer/my-did/resources/zM6mH..." \
  -H "Content-Type: application/json" \
  -d '{
    "attestedResource": {
      ... // Updated metadata/links with new proof
    }
  }'

Endorsement Requirements

If WEBVH_ENDORSEMENT=true (default), resources must be endorsed by a witness:

  1. Controller Signs Resource
  2. Create DataIntegrityProof with controller's verification method

  3. Request Witness Endorsement

  4. Send resource to witness service via DIDComm
  5. Witness verifies and signs the resource

  6. Include Both Proofs

  7. Controller proof: verificationMethod starts with did:webvh:
  8. Witness proof: verificationMethod starts with did:key:
  9. Both proofs must be in the proof array

  10. Server Validation

  11. Server verifies both proofs
  12. Server checks witness is in known witness registry
  13. Server validates witness key matches registered DID

Best Practices

  1. Use Descriptive Metadata
  2. Set resourceType to clearly identify the AnonCreds object type
  3. Use resourceName for human-readable identification

  4. Link Related Resources

  5. Use links to connect schemas, credential definitions, and revocation registries
  6. This enables discovery of related AnonCreds objects

  7. Maintain Resource Immutability

  8. Never modify the content property after initial publication
  9. Use updates only for metadata and links

  10. Verify Before Use

  11. Always verify DataIntegrityProof signatures
  12. Check digestMultibase matches resource ID
  13. Validate witness endorsement if required

  14. Monitor Revocation Registry States

  15. Regularly update revocation registry states
  16. Use links to connect states to registry definitions

API Endpoints

Upload Resource

  • POST /{namespace}/{alias}/resources
  • Uploads a new AnonCreds object as an AttestedResource

Update Resource

  • PUT /{namespace}/{alias}/resources/{resource_id}
  • Updates metadata or links of an existing resource

Get Resource

  • GET /{namespace}/{alias}/resources/{resource_id}
  • Retrieves a specific resource

List Resources

  • GET /{namespace}/{alias}/resources
  • Lists all resources for a DID