BBS+ alongside SD-JWT: libraries, independent keys, and honest predicates
Library choice
Use @mattrglobal/bbs-signatures (BLS12-381, Node + WASM paths). W3C Data Integrity wrappers add LD-graph weight you may not need for server-issued credentials—pick the layer that matches your threat model and bundle budget.
Keys: separate hierarchy
BBS+ issuer keys are independent of Ed25519 passport keys. Do not “derive BLS from Ed25519” — generate a fresh BLS12-381 keypair, store in KMS, publish GET /v1/.well-known/bbs-public-key for verifiers.
Mixing hierarchies confuses rotation, incident response, and auditors.
API shape (disclosure requests)
proof_type: 'sd-jwt' | 'bbs'on disclosure requests (defaultsd-jwtfor compatibility).range_proofsJSONB whenproof_type = 'bbs'— schema per migration; validate server-side.- Verifier challenge embedded as nonce in presentation construction — replay resistance.
Phase 6.1 honesty
Native BBS+ gives selective disclosure and unlinkable presentations. It does not universally ship numeric range proofs as a one-call API the way Bulletproofs-style systems do.
Phase 6.1 may use issuer-issued predicates (e.g. score_ge_80: true computed at issuance) with clear trust boundaries. Phase 6.2 targets fuller range-proof constructions—market that split in docs and blog, not only in tickets.
Test matrix (minimum)
- Partial disclosure — undisclosed claims absent from presentation.
- Verifier challenge mismatch → structured failure.
- Wrong issuer public key → verification fails.
- Expired credential →
EXPIREDclass result. - Tampered proof bytes →
INVALID_PROOF.
Narrative: Prove you qualify. Passport: selective disclosure + anchoring.
— Part of