Proof Purpose Validation

Overview

Proof Purpose Validation ensures that proofs in verifiable credentials are used only for their intended purposes as defined in the DID Document’s verification relationships. This is a critical security feature that prevents misuse of verification methods.

Key Concepts

Proof Purpose

A proof purpose indicates why a proof was created. Common proof purposes include:

  • assertionMethod: For signing verifiable credentials
  • authentication: For authenticating the DID controller
  • keyAgreement: For establishing secure channels
  • capabilityInvocation: For invoking capabilities
  • capabilityDelegation: For delegating capabilities

Verification Relationships

Each proof purpose corresponds to a verification relationship in the DID Document:

  • assertionMethodassertionMethod relationship
  • authenticationauthentication relationship
  • keyAgreementkeyAgreement relationship
  • capabilityInvocationcapabilityInvocation relationship
  • capabilityDelegationcapabilityDelegation relationship

Verification Method Matching

The proof’s verificationMethod must be listed in the corresponding verification relationship of the issuer’s DID Document.

Usage

Basic Validation

1
2
3
4
5
6
7
8
9
10
import org.trustweave.credential.results.VerificationResult

when (val result = trustWeave.verify {
    credential(credential)
    validateProofPurpose()
}) {
    is VerificationResult.Valid -> println("Proof purpose and other checks passed")
    is VerificationResult.Invalid.InvalidProof -> println("Proof issue: ${result.reason}")
    else -> println(result.allErrors.joinToString())
}

Complete Verification Example

1
2
3
4
5
6
7
8
9
10
11
12
import org.trustweave.credential.results.VerificationResult

val registry = trustWeave.configuration.trustRegistry
when (val result = trustWeave.verify {
    credential(credential)
    validateProofPurpose()
    checkExpiration()
    registry?.let { requireTrust(it) }
}) {
    is VerificationResult.Valid -> println("Verification succeeded")
    is VerificationResult.Invalid -> println(result.allErrors.joinToString())
}

Proof Purposes

assertionMethod

Used for signing verifiable credentials. The verification method must be in the issuer’s assertionMethod list.

1
2
3
4
5
6
7
8
9
10
// DID Document must have:
{
  "assertionMethod": ["did:key:issuer#key-1"]
}

// Proof must have:
{
  "proofPurpose": "assertionMethod",
  "verificationMethod": "did:key:issuer#key-1"
}

authentication

Used for authenticating the DID controller. The verification method must be in the DID’s authentication list.

1
2
3
4
5
6
7
8
9
10
// DID Document must have:
{
  "authentication": ["did:key:user#key-1"]
}

// Proof must have:
{
  "proofPurpose": "authentication",
  "verificationMethod": "did:key:user#key-1"
}

keyAgreement

Used for establishing secure channels. The verification method must be in the DID’s keyAgreement list.

1
2
3
4
5
6
7
8
9
10
// DID Document must have:
{
  "keyAgreement": ["did:key:user#key-1"]
}

// Proof must have:
{
  "proofPurpose": "keyAgreement",
  "verificationMethod": "did:key:user#key-1"
}

capabilityInvocation

Used for invoking capabilities on behalf of the DID. The verification method must be in the DID’s capabilityInvocation list.

1
2
3
4
5
6
7
8
9
10
// DID Document must have:
{
  "capabilityInvocation": ["did:key:user#key-1"]
}

// Proof must have:
{
  "proofPurpose": "capabilityInvocation",
  "verificationMethod": "did:key:user#key-1"
}

capabilityDelegation

Used for delegating capabilities to other DIDs. The verification method must be in the DID’s capabilityDelegation list.

1
2
3
4
5
6
7
8
9
10
// DID Document must have:
{
  "capabilityDelegation": ["did:key:delegator#key-1"]
}

// Proof must have:
{
  "proofPurpose": "capabilityDelegation",
  "verificationMethod": "did:key:delegator#key-1"
}

Verification Method References

Full DID URLs

1
2
// Full DID URL
"did:key:issuer#key-1"

Relative References

1
2
// Relative reference (resolved relative to issuer DID)
"#key-1" // Resolves to "did:key:issuer#key-1"

Matching Logic

The validator matches verification methods using:

  1. Exact match (full DID URL)
  2. Relative reference match (resolved relative to issuer DID)
  3. Fragment-only match (e.g., #key-1 matches did:key:issuer#key-1)

Examples

Valid Proof Purpose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// DID Document
val issuerDoc = DidDocument(
    id = "did:key:issuer",
    assertionMethod = listOf("did:key:issuer#key-1")
)

// Credential with proof
val credential = VerifiableCredential(
    issuer = "did:key:issuer",
    proof = Proof(
        proofPurpose = "assertionMethod",
        verificationMethod = "did:key:issuer#key-1"
    )
)

// Validation succeeds
val result = validator.validateProofPurpose(
    proofPurpose = "assertionMethod",
    verificationMethod = "did:key:issuer#key-1",
    issuerDid = "did:key:issuer"
)
// Validation succeeded

Invalid Proof Purpose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// DID Document
val issuerDoc = DidDocument(
    id = "did:key:issuer",
    assertionMethod = listOf("did:key:issuer#key-1")
    // Note: capabilityInvocation is empty
)

// Credential with proof using wrong purpose
val credential = VerifiableCredential(
    issuer = "did:key:issuer",
    proof = Proof(
        proofPurpose = "capabilityInvocation", // Wrong purpose!
        verificationMethod = "did:key:issuer#key-1"
    )
)

// Validation fails
val result = validator.validateProofPurpose(
    proofPurpose = "capabilityInvocation",
    verificationMethod = "did:key:issuer#key-1",
    issuerDid = "did:key:issuer"
)
// Validation failed
// Error output explains that proof purpose 'capabilityInvocation' does not match verification relationships

Best Practices

  1. Always Enable Validation: Enable proof purpose validation in production
  2. Update DID Documents: Keep DID documents up-to-date with correct verification relationships
  3. Use Correct Purposes: Use the appropriate proof purpose for each operation
  4. Verify Before Issuing: Ensure issuer DID document has correct relationships before issuing credentials
  5. Monitor Validation Failures: Track proof purpose validation failures to identify issues

Error Messages

Common validation errors:

  • Unknown proof purpose: Proof purpose is not recognized
  • Verification method not found: Verification method doesn’t exist in DID Document
  • Proof purpose mismatch: Proof purpose doesn’t match verification relationship
  • DID resolution failed: Cannot resolve issuer DID

Integration with Credential Verification

Proof purpose validation is automatically performed when enabled in credential verification:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.trustweave.credential.results.VerificationResult

when (val result = trustWeave.verify {
    credential(credential)
    validateProofPurpose()
    checkExpiration()
    trustWeave.configuration.trustRegistry?.let { requireTrust(it) }
}) {
    is VerificationResult.Valid -> { }
    is VerificationResult.Invalid.InvalidProof -> {
        println("Proof purpose or signature issue: ${result.reason}")
    }
    else -> result.allErrors.forEach { println("  - $it") }
}

See Also

  • DID Documentation](dids.md)
  • Delegation Documentation](delegation.md)
  • Web of Trust Scenario](../scenarios/web-of-trust-scenario.md)
  • W3C DID Core Specification](https://www.w3.org/TR/did-core/)

This site uses Just the Docs, a documentation theme for Jekyll.