A framework-agnostic, production-ready implementation of Selective Disclosure for JWTs (SD-JWT) in TypeScript. Works with Node.js, React, React Native, and browser environments. Optimised for compact QR code payloads.
Note: This repository has been restructured to focus exclusively on SD-JWT and SD-JWT-VC. The previous utility packages (
@sd-jwt/types,@sd-jwt/utils,@sd-jwt/decode,@sd-jwt/present,@sd-jwt/hash,@sd-jwt/crypto-nodejs,@sd-jwt/crypto-browser) have been consolidated into@sd-jwt/core. The Token Status List package (@sd-jwt/jwt-status-list) has been moved to the identity-common-ts project as@owf/token-status-list.
Compliant with:
npm install @sd-jwt/core
# or: pnpm install @sd-jwt/coreimport Crypto from 'node:crypto';
import { SDJwtInstance } from '@sd-jwt/core';
// Bring your own crypto – any Signer / Verifier / Hasher that fits the interface
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
const sdjwt = new SDJwtInstance({
signer: async (data) => {
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
return Buffer.from(sig).toString('base64url');
},
verifier: async (data, sig) => {
return Crypto.verify(null, Buffer.from(data), publicKey, Buffer.from(sig, 'base64url'));
},
signAlg: 'EdDSA',
hasher: async (data, alg) => {
return new Uint8Array(Crypto.createHash(alg.replace('-', '')).update(data).digest());
},
hashAlg: 'sha-256',
saltGenerator: async () => Crypto.randomBytes(16).toString('base64url'),
});
// Issue
const credential = await sdjwt.issue(
{ firstname: 'John', lastname: 'Doe', ssn: '123-45-6789' },
{ _sd: ['firstname', 'lastname', 'ssn'] },
);
// Present (disclose only firstname)
const presentation = await sdjwt.present(credential, { firstname: true });
// Verify
const { payload } = await sdjwt.verify(presentation);
console.log(payload); // { firstname: 'John', ... }See the examples/ directory for more detailed usage.
| Package | Description |
|---|---|
| @sd-jwt/core | Core library — encoding, decoding, selective disclosure, presentation, and verification |
| @sd-jwt/sd-jwt-vc | SD-JWT Verifiable Credentials format built on top of @sd-jwt/core |
Both packages are versioned in sync.
Inspect and debug SD-JWTs in the browser: https://sdjwt.co
Prerequisites: Node.js >= 20, pnpm >= 9
pnpm install
pnpm run buildpnpm testWe use Vitest and CodeCov for coverage.
pnpm run lint # check for issues
pnpm run lint:fix # auto-fix issues
pnpm run format # format all filesWe use Biome for linting and formatting.
- Mandatory Signing of the Issuer-signed JWT
- Manipulation of Disclosures
- Entropy of the salt
- Minimum length of the salt
- Choice of a Hash Algorithm
- Key Binding
- Blinding Claim Names
- Selectively-Disclosable Validity Claims
- Issuer Signature Key Distribution and Rotation
- Forwarding Credentials
- Integrity of Presentation
- Explicit Typing
- Duplicate Digest Rejection (Section 7.1 step 4)
- Unreferenced Disclosure Rejection (Section 7.1 step 5)
- Claim Name Collision Detection (Section 7.1 step 3c.ii.3)
Contributions are welcome! Please read our contributing guidelines before making pull requests.
This project is licensed under the Apache 2.0 License.
For support or contributions, find us in OpenWallet Foundation Discord.
Special thanks to all the contributors and the OpenWallet Foundation community for their invaluable input.