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 credentialsauthentication: For authenticating the DID controllerkeyAgreement: For establishing secure channelscapabilityInvocation: For invoking capabilitiescapabilityDelegation: For delegating capabilities
Verification Relationships
Each proof purpose corresponds to a verification relationship in the DID Document:
assertionMethod→assertionMethodrelationshipauthentication→authenticationrelationshipkeyAgreement→keyAgreementrelationshipcapabilityInvocation→capabilityInvocationrelationshipcapabilityDelegation→capabilityDelegationrelationship
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:
- Exact match (full DID URL)
- Relative reference match (resolved relative to issuer DID)
- Fragment-only match (e.g.,
#key-1matchesdid: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
- Always Enable Validation: Enable proof purpose validation in production
- Update DID Documents: Keep DID documents up-to-date with correct verification relationships
- Use Correct Purposes: Use the appropriate proof purpose for each operation
- Verify Before Issuing: Ensure issuer DID document has correct relationships before issuing credentials
- 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/)