Verifiable Credentials (W3C VCDM 2.0)
Issue and verify W3C Verifiable Credentials (VC Data Model 2.0, a W3C Recommendation) secured per "Securing Verifiable Credentials using JOSE and COSE" (VC-JOSE-COSE, also a W3C Recommendation). A verifiable credential is a tamper-evident, cryptographically-signed set of claims an issuer makes about a subject — a diploma, a membership, a license, an age assertion.
Two securing mechanisms are supported, both putting the credential itself (not a JWT/CWT claims wrapper) as the signed payload: JOSE produces a compact JWS with the vc+jwt media type (typ header "vc+jwt"), signed with the classical ES256 / 384 / 512 or EdDSA JOSE algorithms; COSE produces a COSE_Sign1 (application/vc+cose) over b.cose, adding ML-DSA-87 (PQC-forward) to that set. b.vc.verify auto-detects the form from the input (a compact-JWS string vs. COSE_Sign1 bytes).
b.vc.issue(credential, opts) validates the credential against the VCDM 2.0 structural rules (the credentials/v2 context first, a VerifiableCredential type, an issuer, a credential subject) and signs it. b.vc.verify(secured, opts) verifies the signature (the algorithm allowlist is mandatory; the JOSE none algorithm is always refused), re-checks the structural rules, and enforces the validFrom / validUntil validity window. This is the W3C model and is distinct from the IETF SD-JWT VC at b.auth.sdJwtVc.
b.vc.issue(credential, opts) #
{
{
securing: string, // "jose" (compact JWS) | "cose" (COSE_Sign1)
alg: string, // JOSE: ES256/384/512 | EdDSA. COSE: + ML-DSA-87
privateKey: object, // matching KeyObject or PEM
kid: string, // optional key id (header)
cty: string, // optional JOSE cty (e.g. "vc")
}
}
Validate a credential against the VCDM 2.0 structural rules and secure it. securing: "jose" returns a compact JWS string (media type vc+jwt) signed with an ES256/384/512 or EdDSA key; securing: "cose" returns COSE_Sign1 bytes (media type application/vc+cose) over b.cose, which also accepts "ML-DSA-87". The credential itself is the signed payload — no JWT/CWT claims wrapper is added.
var jws = await b.vc.issue(credential, { securing: "jose", alg: "ES256", privateKey: key });
// → a compact JWS string with typ "vc+jwt"
b.vc.verify(secured, opts) #
{
{
algorithms: string[], // required — accepted alg names (allowlist)
publicKey: object, // verification key (KeyObject / PEM)
keyResolver: function, // (header) → key (alternative to publicKey)
expectedIssuer: string, // require the credential issuer (id) to match
at: Date, // validity instant (default: now); must be a valid Date
}
}
Verify a secured verifiable credential and return the credential. The securing form is auto-detected (a compact-JWS string vs. COSE_Sign1 bytes); the algorithm allowlist is mandatory and the JOSE none algorithm is always refused. After the signature, the VCDM 2.0 structural rules are re-checked and the validFrom / validUntil window is enforced against opts.at (default: now).
var out = await b.vc.verify(jws, { algorithms: ["ES256"], publicKey: issuerPub, expectedIssuer: "did:example:123" });
// → { credential, securing: "jose", alg: "ES256", issuer: "did:example:123" }
b.vc.present(opts) #
{
{
credentials: array, // secured VCs (compact-JWS strings or COSE_Sign1 bytes)
holder: string, // the presenter (a DID or other id)
securing: string, // "jose" | "cose"
alg: string, // JOSE: ES256/384/512 | EdDSA. COSE: + ML-DSA-87
privateKey: object, // the holder's key
kid: string, // optional key id
nonce: string, // optional verifier challenge (embedded + checked)
audience: string, // optional intended verifier (embedded + checked)
}
}
Build and sign a W3C Verifiable Presentation: a holder-signed envelope wrapping one or more secured credentials (each enveloped per VC-JOSE-COSE). securing and the algorithms match b.vc.issue (compact JWS vp+jwt, or COSE_Sign1 application/vp+cose). Supply nonce / audience for holder-binding / replay protection — they are embedded in the signed presentation and checked at verification.
var vp = await b.vc.present({ credentials: [jws], holder: holderDid, securing: "jose", alg: "ES256", privateKey: holderKey, nonce: challenge });
b.vc.verifyPresentation(secured, opts) #
{
{
algorithms: string[], // required — holder-signature alg allowlist
publicKey: object, // the holder verification key
keyResolver: function, // (header) → holder key
expectedHolder: string, // require presentation holder to match
nonce: string, // require embedded nonce to match
audience: string, // require embedded audience to match
verifyCredentials: boolean, // verify each enveloped VC via b.vc.verify
credentialOpts: object, // opts passed to b.vc.verify for each VC
}
}
Verify a Verifiable Presentation: the holder signature (auto-detected jose / cose, mandatory algorithm allowlist, JOSE none refused), the VCDM structure, and the embedded nonce / audience / expectedHolder when given. With verifyCredentials: true each enveloped credential is verified through b.vc.verify (using opts.credentialOpts) and returned.
var out = await b.vc.verifyPresentation(vp, {
algorithms: ["ES256"], publicKey: holderKey, nonce: challenge,
verifyCredentials: true, credentialOpts: { algorithms: ["ES256"], publicKey: issuerKey },
});
// → { presentation, holder, credentials: [verified VCs], securing, alg }
Last updated 2026-08-08T16:39:49.652Z by seeder.