Proofs and Proof Engines
Overview
TrustWeave’s proof system provides cryptographic proof generation and verification for Verifiable Credentials. The architecture is built around Proof Engines that handle proof suite-specific operations, and Proof Options that configure cross-suite proof parameters.
Key Concepts
Proof Suites
A proof suite identifies the cryptographic proof format used in a Verifiable Credential. TrustWeave supports multiple proof suites:
- VC-LD (
ProofSuiteId.VC_LD) - W3C Verifiable Credentials with Linked Data Proofs - VC-JWT (
ProofSuiteId.VC_JWT) - W3C Verifiable Credentials as JWT - SD-JWT-VC (
ProofSuiteId.SD_JWT_VC) - IETF Selective Disclosure JWT Verifiable Credentials - AnonCreds (
ProofSuiteId.ANONCREDS) - Hyperledger AnonCreds with zero-knowledge proofs
All proof suites are built-in and always available - no plugins or registration required.
1
2
3
4
5
6
import org.trustweave.credential.format.ProofSuiteId
// Use enum values directly
val vcLdSuite = ProofSuiteId.VC_LD
val sdJwtVcSuite = ProofSuiteId.SD_JWT_VC
val anonCredsSuite = ProofSuiteId.ANONCREDS
Proof Options
ProofOptions configure proof generation parameters that apply across all proof suites:
- Purpose - Why the proof exists (assertionMethod, authentication, etc.)
- Challenge - Nonce for non-repudiation (prevents replay attacks)
- Domain - Domain binding string (prevents cross-domain attacks)
- Verification Method - Explicit key/verification method to use
- Additional Options - Proof suite-specific parameters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.trustweave.credential.proof.*
// Simple - defaults to assertionMethod
val options = proofOptions()
// With DSL builder
val options = proofOptions {
purpose = ProofPurpose.Authentication
challenge = generateChallenge()
domain = "example.com"
verificationMethod = "did:key:example#key-1"
}
// Using convenience functions
val authOptions = proofOptionsForAuthentication(
challenge = "nonce-123",
domain = "example.com"
)
val presentationOptions = proofOptionsForPresentation(
challenge = verifierChallenge,
domain = "example.com"
)
Proof Engines
A Proof Engine is an implementation that handles proof operations for a specific proof suite. Each engine:
- Generates cryptographic proofs during credential issuance
- Verifies proofs during credential verification
- Creates presentations (if supported)
- Exposes capabilities (selective disclosure, zero-knowledge, etc.)
Proof engines are internal - normal users interact with them through CredentialService, not directly.
Proof Purposes
Proof purposes indicate why a proof exists, following W3C Verifiable Credentials standards:
AssertionMethod
Default for credential issuance. Proves that the issuer is asserting the credential claims.
1
2
3
4
5
val options = proofOptionsForIssuance()
// or
val options = proofOptions {
purpose = ProofPurpose.AssertionMethod
}
Authentication
Used when the credential holder authenticates, typically in presentation flows.
1
2
3
4
val options = proofOptionsForAuthentication(
challenge = generateChallenge(),
domain = "example.com"
)
KeyAgreement
For establishing secure channels or key exchange.
1
2
3
val options = proofOptionsForKeyAgreement(
verificationMethod = "did:key:example#key-agreement-1"
)
CapabilityInvocation
For invoking capabilities or permissions.
1
2
3
val options = proofOptionsForCapabilityInvocation(
challenge = generateChallenge()
)
CapabilityDelegation
For delegating capabilities or permissions.
1
2
3
val options = proofOptionsForCapabilityDelegation(
verificationMethod = "did:key:example#delegation-key"
)
Using Proof Options
In Issuance Requests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import org.trustweave.credential.requests.*
import org.trustweave.credential.proof.*
val request = IssuanceRequest(
format = ProofSuiteId.VC_LD,
issuer = issuer,
credentialSubject = subject,
type = listOf(CredentialType("VerifiableCredential")),
proofOptions = proofOptions {
purpose = ProofPurpose.AssertionMethod
verificationMethod = "did:key:issuer#key-1"
}
)
// Or using extension function
val request = IssuanceRequest(...)
.withProofOptions {
purpose = ProofPurpose.AssertionMethod
challenge = "nonce-123"
}
In Presentation Requests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
val presentationRequest = PresentationRequest(
disclosedClaims = setOf("name", "email"),
proofOptions = proofOptionsForPresentation(
challenge = verifierChallenge,
domain = "example.com"
)
)
// Or using extension function
val request = PresentationRequest(...)
.withProofOptions {
challenge = verifierChallenge
domain = "example.com"
}
Proof Suite-Specific Options
Use additionalOptions for proof suite-specific parameters:
1
2
3
4
5
6
7
8
9
10
11
12
13
val options = proofOptions {
purpose = ProofPurpose.AssertionMethod
option("proofType", "Ed25519Signature2020")
option("canonicalizationAlgorithm", "urdna2015")
}
// For AnonCreds
val anonCredsOptions = proofOptions {
purpose = ProofPurpose.AssertionMethod
option("schema_id", "schema:123")
option("cred_def_id", "cred_def:456")
option("rev_reg_id", "rev_reg:789")
}
Proof Engine Architecture
Built-in Engines
TrustWeave includes built-in proof engines for all supported proof suites:
- VcLdProofEngine - Handles VC-LD proofs with JSON-LD canonicalization
- SdJwtProofEngine - Handles SD-JWT-VC proofs with selective disclosure
- AnonCredsProofEngine - Handles AnonCreds proofs with zero-knowledge capabilities
These engines are automatically available when you create a CredentialService:
1
2
3
4
import org.trustweave.credential.*
val service = credentialService(didResolver)
// All proof engines are automatically configured
Engine Capabilities
Each proof engine exposes capabilities:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
val capabilities = engine.capabilities
if (capabilities.selectiveDisclosure) {
// Engine supports selective disclosure
}
if (capabilities.zeroKnowledge) {
// Engine supports zero-knowledge proofs
}
if (capabilities.presentation) {
// Engine supports presentations
}
if (capabilities.predicates) {
// Engine supports predicate proofs
}
Checking Support
Check if a proof suite is supported:
1
2
3
4
5
6
7
8
if (service.supports(ProofSuiteId.VC_LD)) {
// VC-LD is supported
}
// Check capabilities
val supportsSelectiveDisclosure = service.supportsCapability(ProofSuiteId.SD_JWT_VC) {
selectiveDisclosure
}
Common Patterns
Issuing with Default Proof Options
1
2
3
4
5
6
7
8
9
val request = IssuanceRequest(
format = ProofSuiteId.VC_LD,
issuer = issuer,
credentialSubject = subject,
type = listOf(CredentialType("VerifiableCredential"))
// proofOptions defaults to assertionMethod
)
val result = service.issue(request)
Issuing with Custom Proof Options
1
2
3
4
5
6
7
8
9
10
11
12
13
val request = IssuanceRequest(
format = ProofSuiteId.VC_LD,
issuer = issuer,
credentialSubject = subject,
type = listOf(CredentialType("VerifiableCredential")),
proofOptions = proofOptions {
purpose = ProofPurpose.AssertionMethod
verificationMethod = "did:key:issuer#key-1"
option("proofType", "Ed25519Signature2020")
}
)
val result = service.issue(request)
Creating Presentations with Challenge
1
2
3
4
5
6
7
8
9
10
11
12
13
14
val challenge = generateChallenge()
val presentationRequest = PresentationRequest(
disclosedClaims = setOf("name", "email"),
proofOptions = proofOptionsForPresentation(
challenge = challenge,
domain = "example.com"
)
)
val presentation = service.createPresentation(
credentials = listOf(credential),
request = presentationRequest
)
Modifying Proof Options
1
2
3
4
5
6
7
8
9
10
val baseOptions = proofOptionsForIssuance()
// Add challenge
val withChallenge = baseOptions.withChallenge("nonce-123")
// Change purpose
val forAuth = baseOptions.withPurpose(ProofPurpose.Authentication)
// Add domain
val withDomain = baseOptions.withDomain("example.com")
Best Practices
- Use appropriate proof purposes
AssertionMethodfor credential issuanceAuthenticationfor presentations
- Always include challenges in presentations
- Prevents replay attacks
- Use
generateChallenge()for random nonces
- Use domain binding for web flows
- Prevents cross-domain attacks
- Common in OID4VP flows
- Specify verification method when needed
- Helps when issuer has multiple keys
- Improves performance by avoiding key resolution
- Use proof suite-specific options sparingly
- Prefer standard
ProofOptionswhen possible - Use
additionalOptionsonly for suite-specific needs
- Prefer standard
Related Documentation
- Proof Purpose Validation - Detailed explanation of proof purposes
- Verifiable Credentials - W3C VC data model
- Key Management - Key management for signing
- Credential Service API - Complete API reference