Verifiable Credentials
Verifiable Credentials
Verifiable Credentials (VCs) are a W3C standard for expressing credentials on the web in a way that is cryptographically secure, privacy respecting, and machine-verifiable. In Layr8, VCs enable decentralized trust between organizations without constant API calls or centralized authorities.
What are Verifiable Credentials?
Think of Verifiable Credentials as digital certificates that are:
- Tamper-evident — any modification is detectable
- Cryptographically secure — signed by the issuer
- Privacy-preserving — share only what’s needed
- Independently verifiable — no need to contact the issuer
- Portable — work across different systems
Common real-world analogies:
- Digital driver’s license
- Professional certification
- Membership card
- Permit or authorization
The Trust Triangle
Verifiable Credentials involve three parties:
Issuer / \ / \ / \ ↓ ↓Holder ←→ Verifier- Issuer: Creates and signs credentials (e.g., a certifying body)
- Holder: Receives and stores credentials (e.g., a supplier)
- Verifier: Checks credential validity (e.g., a buyer)
Credential Structure
A Verifiable Credential follows the W3C data model:
{ "@context": [ "https://www.w3.org/2018/credentials/v1", "https://example.com/contexts/supply-chain/v1" ], "id": "https://example.com/credentials/certified-supplier/123", "type": ["VerifiableCredential", "CertifiedSupplierCredential"], "issuer": "did:web:certifying-body.com", "issuanceDate": "2024-01-01T00:00:00Z", "expirationDate": "2025-01-01T00:00:00Z", "credentialSubject": { "id": "did:web:acme-corp.com", "supplierLevel": "Gold", "certifications": ["ISO-9001", "ISO-14001"], "authorizedCategories": ["Electronics", "Components"] }, "proof": { "type": "JsonWebSignature2020", "created": "2024-01-01T00:00:00Z", "verificationMethod": "did:web:certifying-body.com#key-1", "proofPurpose": "assertionMethod", "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2..." }}Key Fields
- @context — JSON-LD context defining the credential vocabulary
- type — credential type(s), always includes
VerifiableCredentialplus domain-specific types - issuer — DID of the entity that issued the credential
- credentialSubject — the claims being made, identified by the subject’s DID
- proof — cryptographic signature from the issuer
Credential Lifecycle
Issuance
An issuer creates a credential by signing claims about a subject. The issuer’s DID Document contains the public key needed to verify the signature. The credential is then delivered to the holder — in Layr8, this happens over DIDComm.
Holding
The holder stores credentials and decides when and with whom to share them. Credentials are portable — they work anywhere the verifier trusts the issuer, regardless of how they were delivered.
Presentation
When a holder needs to prove a claim, they create a Verifiable Presentation — a signed wrapper around one or more credentials. The presentation proves the holder possesses the credentials and consents to sharing them.
{ "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiablePresentation"], "holder": "did:web:acme-corp.com", "verifiableCredential": ["..."], "proof": { "type": "JsonWebSignature2020", "created": "2024-01-15T12:00:00Z", "verificationMethod": "did:web:acme-corp.com#key-1", "challenge": "d1b23d3...a", "proofPurpose": "authentication", "jws": "eyJhbGciOiJFZERTQSIs..." }}The challenge field prevents replay attacks — the verifier provides a unique value that the holder must include in the presentation proof.
Verification
Verification checks multiple things without contacting the issuer:
- Signature validity — the credential’s proof matches the issuer’s public key
- Expiration — the credential hasn’t expired
- Revocation status — the credential hasn’t been revoked (if revocation is supported)
- Issuer trust — the verifier trusts the issuing DID
Selective Disclosure
Holders can share only specific claims from a credential rather than the entire document. This preserves privacy — a supplier can prove their certification level without revealing their credit limit.
The W3C specification supports several selective disclosure mechanisms, including JSON-LD frame-based disclosure and BBS+ signatures for zero-knowledge selective disclosure.
Credential Schemas
Schemas define the expected structure of credential claims:
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "supplierLevel": { "type": "string", "enum": ["Bronze", "Silver", "Gold", "Platinum"] }, "certifications": { "type": "array", "items": { "type": "string" } }, "maxOrderValue": { "type": "number", "minimum": 0 } }, "required": ["supplierLevel", "certifications"]}Schemas enable consistent validation across issuers and verifiers without requiring a shared implementation.
Revocation
Credentials may need to be revoked before expiration — for example, when a contract is terminated or a certification is suspended. The W3C data model supports revocation through status lists, where the issuer publishes a bitstring indicating which credentials have been revoked. Verifiers check this list during verification.
Using Credentials in Layr8
Each Layr8 cloud-node includes a credential API for signing, verifying, storing, and presenting W3C Verifiable Credentials. The SDKs expose these as client methods.
Sign and Verify
Every agent can sign credentials using its DID’s assertion key. The cloud-node handles key management — your agent provides the credential claims and gets back a signed JWT.
// Gosigned, _ := client.SignCredential(ctx, cred)result, _ := client.VerifyCredential(ctx, signed)const signed = await client.signCredential(cred);const result = await client.verifyCredential(signed);# Pythonsigned = await client.sign_credential(cred)result = await client.verify_credential(signed)Store and Retrieve
Agents can store signed credentials in the cloud-node’s credential store for later retrieval. This is useful for holders who receive credentials from issuers and need to present them later.
// Gostored, _ := client.StoreCredential(ctx, signedJWT)creds, _ := client.ListCredentials(ctx)fetched, _ := client.GetCredential(ctx, stored.ID)const stored = await client.storeCredential(signedJwt);const creds = await client.listCredentials();const fetched = await client.getCredential(stored.id);# Pythonstored = await client.store_credential(signed_jwt)creds = await client.list_credentials()fetched = await client.get_credential(stored.id)Presentations
When a holder needs to prove claims to a verifier, they bundle one or more credentials into a Verifiable Presentation — a signed wrapper that proves possession and consent.
// Gopres, _ := client.SignPresentation(ctx, []string{signedJWT})result, _ := client.VerifyPresentation(ctx, pres)const pres = await client.signPresentation([signedJwt]);const result = await client.verifyPresentation(pres);# Pythonpres = await client.sign_presentation([signed_jwt])result = await client.verify_presentation(pres)For full API details, see the SDK reference pages: Go SDK, Node.js SDK, Python SDK.
How It Fits Together
In Layr8, Verifiable Credentials complement the identity and messaging layers:
- Identity — DIDs identify issuers, holders, and verifiers
- Delivery — credentials are exchanged over DIDComm, encrypted and authenticated end-to-end
- Trust decisions — nodes and agents use verified credentials to make authorization decisions (e.g., “only accept orders from Gold-tier suppliers”)
This separates trust establishment (credentials) from communication (DIDComm), allowing organizations to make independent trust decisions without centralized authorization servers.
Design Best Practices
- Keep claims minimal and specific — issue only the claims needed for the use case
- Use standard vocabularies — reuse existing credential types and contexts where possible
- Set appropriate expiration dates — shorter for high-risk credentials, longer for stable certifications
- Include revocation mechanisms — plan for contract termination and credential suspension
- Validate against schemas — ensure credential claims match expected structure
- Verify the entire trust chain — check issuer trust, signature, expiration, and revocation
Troubleshooting
-
Signature Verification Fails
- Check key resolution in the issuer’s DID Document
- Verify the proof timestamp is within the credential’s validity period
- Ensure the cryptographic suite is supported
-
Credential Expired
- Implement renewal workflows with the issuer
- Have fallback authorization for grace periods
-
Missing Required Claims
- Validate credentials against their schema before relying on claims
- Provide clear error messages when required claims are absent
Further Reading
- W3C Verifiable Credentials Data Model
- Verifiable Credentials Implementation Guidelines
- DID Core Specification
- JSON-LD
- Linked Data Proofs
Next Steps
- Decentralized Identifiers — The identity foundation that credentials build on
- DIDComm Messaging — How credentials are exchanged between organizations