A Veramo plugin to issue, present and verify SD-JWT-VCs and is using SD-JWT-JS library.
npm install @bcrl/veramo-sd-jwt
Detailed examples can be found in the test file.
const agent = createAgent<ISDJwtPlugin>({
plugins: [
new SDJwtPlugin({
// calculate the digest of the JWT
hasher: digest,
// generate a random salt
saltGenerator: generateSalt,
// verify the JWT
verifySignature,
}),
});
Instead of implementing the hasher and saltGenerator on your own, you can use the default implementations for each environment:
// Node.js
import { digest, generateSalt } from '@sd-jwt/crypto-nodejs';
// Browser
import { digest, generateSalt } from '@sd-jwt/crypto-browser';
const claims = {
given_name: 'John',
family_name: 'Deo',
email: 'johndeo@example.com',
phone: '+1-202-555-0101',
address: {
street_address: '123 Main St',
locality: 'Anytown',
region: 'Anystate',
country: 'US',
},
birthdate: '1940-01-01',
};
const disclosureFrame: DisclosureFrame<typeof claims> = {
_sd: [
'given_name',
'family_name',
'email',
'phone',
'address',
'birthdate',
],
};
const credentialPayload: SdJwtVcPayload = {
...claims,
// a did url that is used for the issuance. You need to pass the reference to the key that is used to sign the JWT
iss: 'did:example:123#key-1',
iat: new Date().getTime() / 1000,
// type of the credential
vct: 'ID-Card',
// required to perform holder binding.
cnf: {
// the public key of the holder encoded as Json Web Key
jwk,
},
};
const credential = await agent.createSdJwtVc({
credentialPayload,
disclosureFrame,
});
The verify function will validate the signature of the SD-JWT-VC, it will not validate a referenced status list.
const verified = await agent.verifySdJwtVc({
credential: credential.credential,
});
Creates a presentation of a credential. The presentation will only contain the claims that are specified in the presentationKeys. If you want to present all claims, you can pass an empty object.
To perform a holder binding, The included key in the cnf
claim must be used. Right now it only supports the cnf.jwk
approach so you need to pass a JWK during the issuance and not a did url.
const presentationKeys: PresentationFrame<typeof claims> = {
given_name: true,
};
const presentation = await agent.createSdJwtVcPresentation({
presentation: credential.credential,
presentationKeys,
kb: {
payload: {
aud: '1',
iat: 1,
nonce: '342',
},
},
});
Verifies a given presentation. It will validate the signature of the issuer, if all claims are present and optional if the key binding is correct.
const result = await agent.verifySdJwtVcPresentation({
// encoded presentation
presentation: presentation.presentation,
// list of required claims
requiredClaimKeys: ['given_name'],
// if set to true, the kb will be verified
kb: true,
});
Packages are managed via pnpm
.
pnpm run build
Test are written with vitest
;
pnpm run test
To get the coverage report, run:
pnpm run format
The code is formatted with biome
, passing the format and lint check is required to pass the CI. To format the code locally, run
pnpm run format