Zero-knowledge proofs (ZKPs) let one party prove a statement is true without revealing anything beyond the statement's validity. In the context of verification infrastructure, ZKPs enable selective disclosure — a holder can prove they are over 21, hold a valid professional license, or are a member of an organization, all without revealing their date of birth, license number, or membership ID.
This post describes how we integrated ZKP-based selective disclosure into the Truthlocks attestation framework, the cryptographic primitives we use, and the practical trade-offs we encountered.
The Problem: Over-Sharing in Verification
Traditional verification is binary: present the full credential or don't. If a bar needs to confirm you are over 21, you hand over a driver's license that also reveals your full name, address, date of birth, license number, and organ donor status. This over-sharing is a privacy problem and, in regulated industries, a compliance liability.
Selective disclosure addresses this by letting the holder derive a presentation from their credential that proves exactly the required attributes and nothing more.
Cryptographic Foundation
Our ZKP implementation uses BBS+ signatures (as specified in the W3C BBS Signature draft) combined with a Groth16-based proving system for range proofs and set membership proofs. The architecture has three components:
BBS+ Multi-Message Signatures
Unlike Ed25519, which signs a single message, BBS+ can sign a vector of messages — where each message corresponds to a credential attribute. The holder can then selectively disclose individual attributes while proving that the undisclosed attributes were part of the original signed credential. The signature remains valid even when attributes are hidden.
The issuer signs the credential using their BBS+ secret key. The holder stores the credential and the BBS+ signature. At presentation time, the holder creates a zero-knowledge proof of knowledge of the signature that reveals only the chosen attributes.
Range Proofs
Some verifications require proving that a numeric value falls within a range — for example, "date of birth is before 2005-03-07" to prove the holder is over 21. We use a Bulletproofs-inspired range proof that operates on the committed attribute value without revealing it. The verifier learns only that the value satisfies the range predicate.
Set Membership Proofs
Other verifications require proving that an attribute belongs to a defined set — for example, "country of licensure is one of {US, CA, UK, AU}." We use a cryptographic accumulator to represent the set and a witness that proves membership without revealing which specific element the holder possesses.
The Presentation Flow
Here is how a selective-disclosure verification works end-to-end:
- Credential issuance: The issuer mints an attestation with attributes signed using BBS+. The credential is stored by the holder (in a wallet or secure enclave).
- Presentation request: The verifier defines a presentation definition specifying which attributes to disclose and which predicates to prove (e.g., age ≥ 21).
- Proof generation: The holder's wallet generates a ZKP that satisfies the presentation definition. This proof includes the disclosed attributes and cryptographic evidence for the predicates — but nothing else.
- Verification: The verifier submits the proof to the Truthlocks verification API, which checks the BBS+ signature proof, validates the range and set membership proofs, confirms the issuer's trust level, and checks revocation status.
Implementation Details
The ZKP engine runs as a dedicated service within our infrastructure. Proof verification is computationally more expensive than Ed25519 signature verification — roughly 15 ms per proof compared to 0.01 ms for Ed25519. To maintain our latency SLAs, we made several optimizations:
- Precomputed pairing values: We cache bilinear pairing computations for frequently used issuer public keys, reducing verification time by approximately 40%.
- Batch verification: When multiple proofs arrive in a short window, we batch the pairing checks using the small-exponents optimization, amortizing the cost across proofs.
- Proof format: We use a compact binary encoding for proofs rather than JSON, reducing payload size by 60% and parse time accordingly.
A Practical Example: Age Verification
Consider an age verification scenario. The issuer (a government identity authority) issues a credential with attributes: name, date_of_birth, address, document_number. The verifier (an e-commerce platform) only needs to confirm the buyer is over 18.
// Presentation definition from the verifier
{
"requested_attributes": [],
"requested_predicates": [
{
"attribute": "date_of_birth",
"predicate": "less_than",
"value": "2008-03-07"
}
],
"trusted_issuers": ["did:truthlock:gov-identity-authority"]
}
The holder's wallet generates a proof that date_of_birth < 2008-03-07 without revealing the actual date of birth. The verifier receives a binary yes/no answer plus the cryptographic proof, which they submit to our API for independent verification.
Trade-Offs and Limitations
ZKP-based verification introduces several trade-offs that teams should consider:
- Proof generation cost: Generating a ZKP on a mobile device takes 200–500 ms depending on the number of attributes and predicates. This is acceptable for most user-facing flows but may not suit high-frequency machine-to-machine verification.
- Credential format: ZKP-compatible credentials use BBS+ signatures, which require a different issuance path than standard Ed25519-signed attestations. Issuers must explicitly opt into BBS+ at credential type creation time.
- Revocation complexity: Revoking a ZKP-compatible credential requires updating a cryptographic accumulator, which is more involved than adding an entry to a revocation list. We handle this transparently in the platform, but issuers should be aware of the underlying mechanism.
Getting Started
ZKP-based selective disclosure is on our roadmap for enterprise customers. As we develop this capability, the developer documentation will include guides for issuing BBS+ credentials, defining presentation requests, and verifying proofs. If you are interested in selective disclosure for your verification workflows, reach out through the enterprise contact page to discuss your use case.
Selective disclosure is a significant step toward privacy-preserving verification. We believe that as the ecosystem matures, ZKP-based presentations will become the default for sensitive credential types — letting people and organizations prove what they need to prove, and nothing more.
