Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

How to Implement Selective Disclosure for Health Records

A step-by-step developer guide for implementing selective disclosure protocols like BBS+ signatures and zero-knowledge proofs to verify health claims without revealing the full record.
Chainscore © 2026
introduction
PRIVACY ENGINEERING

How to Implement Selective Disclosure for Health Records

Selective disclosure allows patients to share specific health data points without revealing their entire medical history, a fundamental shift from traditional all-or-nothing data sharing models.

Selective disclosure is a cryptographic privacy pattern that enables granular, attribute-based sharing. Instead of handing over a complete medical record, a patient can prove a specific claim—like being over 18 or having a recent negative test result—without exposing their birthdate or full test report. This is achieved using zero-knowledge proofs (ZKPs) and verifiable credentials. Core standards like the W3C Verifiable Credentials Data Model and Decentralized Identifiers (DIDs) provide the framework for creating, holding, and presenting these cryptographically signed, tamper-evident claims.

Implementing this system requires a defined architecture with distinct roles: the issuer (hospital, lab), the holder (patient with a digital wallet), and the verifier (pharmacy, employer). The issuer signs credentials (e.g., "vaccinationStatus": "complete") and sends them to the holder's wallet. When proof is needed, the verifier sends a presentation request specifying the required claims and any predicates (e.g., "vaccinationDate > 2021-06-01"). The holder's wallet uses a ZKP protocol to generate a verifiable presentation that satisfies the request, which the verifier can cryptographically validate against the issuer's public DID.

For developers, libraries like Hyperledger Aries and Veramo provide essential tooling. Here's a conceptual flow using a TypeScript snippet with Veramo to create a selective disclosure presentation:

typescript
// Verifier requests proof of age > 16 and a specific vaccination
const presentationRequest = {
  id: 'request-1',
  query: [{
    type: 'QueryByExample',
    credentialQuery: [{
      reason: 'Age verification for clinical trial',
      example: {
        '@context': ['https://www.w3.org/2018/credentials/v1'],
        type: ['VerifiableCredential', 'HealthCredential'],
        credentialSubject: {
          'ageOver': { '$gt': 16 },
          'vaccinationCode': { '$eq': '207' }
        }
      }
    }]
  }]
};
// Holder's wallet creates a ZKP satisfying the request
const presentation = await agent.createVerifiablePresentation({
  presentation: {
    holder: holderDid,
    verifiableCredential: [selectedCredential],
  },
  proofFormat: 'jwt',
  challenge: presentationRequest.id
});

Key design decisions involve choosing proof systems. BBS+ Signatures allow for multi-claim disclosure from a single signature, while zk-SNARKs (e.g., via Circom) enable complex logical operations. The choice impacts wallet computational load and proof size. Privacy must be balanced with regulatory auditability; using revocation registries (like Indy's accumulator) or status lists allows issuers to invalidate credentials without tracking individual presentations. Always anchor issuer DIDs on a verifiable data registry, such as the Ethereum or Sovrin ledger, to ensure trust in the credential's origin.

Real-world applications are emerging. The EU Digital COVID Certificate system demonstrated selective disclosure principles at scale. In ongoing trials, mental health apps allow users to share generalized wellness scores ("PHQ-9 score < 10") instead of raw questionnaire answers. The SMART Health Cards framework uses JWT-based verifiable credentials for immunization data. When implementing, prioritize patient-held data models over centralized databases, ensure interoperability via W3C standards, and conduct thorough security audits on ZKP circuits and key management to prevent data linkage or forgery attacks.

prerequisites
HEALTHCARE DATA PRIVACY

Prerequisites and Setup

This guide outlines the technical foundation required to build a system for selective disclosure of health records using verifiable credentials and zero-knowledge proofs.

Selective disclosure in healthcare allows a patient to share specific, verified claims from their medical history without revealing the entire record. This is achieved using Verifiable Credentials (VCs) and Zero-Knowledge Proofs (ZKPs). A VC, issued by a trusted entity like a hospital, is a cryptographically signed attestation (e.g., "Alice is over 18"). ZKPs, such as those enabled by zk-SNARKs or Circom circuits, allow Alice to prove she possesses a valid VC meeting certain criteria (e.g., age > 18) without exposing her birth date or the credential's full contents.

To implement this, you will need a foundational understanding of public-key cryptography, decentralized identifiers (DIDs), and the W3C Verifiable Credentials data model. Familiarity with a programming language like JavaScript/TypeScript (for web integration) or Rust (for performance-critical proof generation) is essential. Key libraries include did-jwt-vc for credential handling, snarkjs for ZKP workflows, and @veramo/core for a unified agent framework to manage identities and credentials.

The core setup involves three roles: the Issuer (healthcare provider), the Holder (patient), and the Verifier (pharmacy, insurer). You must establish a trust framework where Issuers publish their public DID and credential schema to a verifiable data registry, like the Ethereum blockchain or ION (a Bitcoin-based DID network). The Holder uses a digital wallet (e.g., Veramo Agent or SpruceID's Kepler) to receive, store, and selectively present credentials.

For the selective disclosure logic, you will define claim predicates. Using a tool like Circom, you write a circuit that takes private inputs (the VC data) and public inputs (the disclosure requirement). For example, a circuit could prove a vaccinationStatus claim equals "Completed" and a date claim is within the last year. This circuit is compiled and a trusted setup generates proving and verification keys, which are used by the Holder's wallet and Verifier's service respectively.

Finally, integrate the components into an application flow. The Issuer's backend signs VCs using their private key. The Holder's wallet requests a credential, then uses the ZKP circuit to generate a Verifiable Presentation for a specific request. The Verifier's API receives this presentation, checks the proof against the public verification key and the Issuer's DID on the registry, and grants access if valid. This architecture ensures minimal data exposure and cryptographically enforced patient consent.

key-concepts-text
CORE CRYPTOGRAPHIC CONCEPTS

How to Implement Selective Disclosure for Health Records

A technical guide to using zero-knowledge proofs and verifiable credentials to share specific health data without revealing the entire record.

Selective disclosure is a cryptographic technique that allows a user to prove a specific claim derived from a credential—like a health record—without revealing the credential itself or any unrelated data. This is crucial for privacy in healthcare, where a patient might need to prove they are over 18 for a vaccination, or that their latest test result is negative, without exposing their full medical history. Core technologies enabling this include Verifiable Credentials (VCs), which are tamper-evident digital claims, and Zero-Knowledge Proofs (ZKPs), which allow the validation of a statement's truth without revealing the underlying data. Standards like the W3C Verifiable Credentials Data Model provide the foundational framework for interoperability.

Implementing selective disclosure typically involves a three-role architecture: the issuer (e.g., a hospital cryptographically signs a VC containing the full health record), the holder (the patient who stores the VC in a digital wallet), and the verifier (e.g., a pharmacy requesting proof). When a verifier requests proof of a specific attribute, the holder's wallet uses a cryptographic protocol to generate a Verifiable Presentation. This presentation can be a simple, signed subset of the original VC or, for more advanced privacy, a ZK-SNARK proving a predicate (e.g., age > 18) is satisfied by the signed data. Libraries like jsonld-signatures or anoncreds provide the tools to create and verify these structures.

For a practical implementation, consider using the BBS+ (Boneh-Boyen-Shacham) signature scheme, which supports deriving unlinkable, selective disclosure proofs from a single master signature. Here's a conceptual flow using pseudocode:

code
// 1. Issuer signs a credential with BBS+
credential = {"id": "patient123", "age": 25, "diagnosis": "A", "lastVisit": "2024-01-15"};
signature = bbs.sign(issuerPrivateKey, credential);
// 2. Holder receives signed credential (VC).
// 3. Verifier asks: "Prove age >= 21 without revealing exact age or other fields."
// 4. Holder generates a zero-knowledge proof.
proof = bbs.createProof(credential, signature, disclosureFrame = { "age": true });
// The 'disclosureFrame' specifies only 'age' is revealed. The proof cryptographically verifies the hidden signature and that age >= 21.
// 5. Verifier checks the proof against the issuer's public key.
isValid = bbs.verifyProof(issuerPublicKey, proof, revealedData = { "age": 25 });

Key design considerations include schema definition—using a standardized format like JSON Schema or Hyperledger AnonCreds to define the structure of health data—and revocation. Issuers must be able to revoke credentials if data becomes invalid (e.g., a test expires). Common patterns are revocation lists or status registries. Furthermore, holder binding mechanisms ensure that the presentation is generated by the legitimate credential owner, often via a Decentralized Identifier (DID) and proof of control of a cryptographic key. These components ensure the system is not only private but also secure and trustworthy.

Real-world implementations are emerging in projects like the European Digital Identity Wallet and IBM's Digital Health Pass. When building, evaluate existing SSI (Self-Sovereign Identity) frameworks such as Hyperledger Aries, Serto, or Trinsic to avoid implementing complex cryptography from scratch. The primary challenges remain user experience—managing keys and consent flows—and scalability of ZKP generation on mobile devices. However, selective disclosure represents the future of privacy-preserving data sharing, moving beyond the all-or-nothing paradigm of traditional data dumps to a model of minimal, auditable, and user-controlled disclosure.

TECHNICAL OVERVIEW

Comparison of Selective Disclosure Protocols

A feature and performance comparison of leading protocols for implementing selective disclosure in health record systems.

Feature / MetricW3C Verifiable Credentials (JSON-LD)BBS+ Signatures (AnonCreds)Coconut (ZKP Scheme)Iden3 (zk-SNARKs)

Cryptographic Foundation

Linked Data Proofs (Ed25519, RSA)

Pairing-Based (BLS12-381)

Attribute-Based Credentials (Pairings)

zk-SNARKs (Groth16, PLONK)

Predicate Proofs (e.g., Age > 18)

Multi-Credential Proof Aggregation

Proof Size (Typical)

1-5 KB

~200 bytes

~300 bytes

~1 KB

Verification Time

< 100 ms

< 50 ms

< 80 ms

< 2 sec

Revocation Mechanism

Status List 2021

Accumulators

Cryptographic Blacklists

State-Based (SMT)

Schema Flexibility

High (JSON-LD)

Moderate (JSON)

High

High (JSON, Protobuf)

Primary Use Case

Interoperable identity

Anonymous credentials

Privacy-preserving DApps

Decentralized identity (DID)

implementation-bbs
CRYPTOGRAPHIC FOUNDATION

Step 1: Implementing BBS+ Signatures

BBS+ signatures enable selective disclosure, allowing a user to prove specific claims from a credential without revealing the entire document. This is the core privacy mechanism for our health record system.

BBS+ (Boneh-Boyen-Shacham with a pairing) is a digital signature scheme that supports zero-knowledge proofs. Unlike standard signatures like ECDSA, which verify an entire signed message, BBS+ allows a prover to cryptographically demonstrate they possess a valid signature on a set of messages, while only disclosing a chosen subset of those messages to the verifier. For health records, this means a patient can prove they are over 18 from a driver's license credential without revealing their name, address, or exact birth date.

The protocol operates on elliptic curve groups with a bilinear pairing, typically the BLS12-381 curve. A signature is generated by a trusted issuer (e.g., a hospital) over a commitment to several message attributes. The critical property is signature proof of knowledge: a user can create a proof that convinces a verifier of the signature's validity and the truth of the revealed messages, without leaking information about the hidden messages or the original signature itself. This is achieved through complex but well-defined operations involving group elements and zero-knowledge proof techniques.

To implement this, you'll need a cryptographic library that supports BBS+. The Hyperledger AnonCreds specification provides a standardized data model and algorithms. For development, consider the bbs Rust crate or the @mattrglobal/bbs-signatures JavaScript/TypeScript library. The core steps are: 1) Key Generation for the issuer, 2) Signing a multi-message credential, 3) Creating a Presentation (proof) that reveals only selected messages, and 4) Verifying that presentation.

Here is a simplified conceptual flow in pseudocode:

code
// Issuer signs a health record with attributes
signature = bbs_sign(issuer_sk, ["Alice", "01/01/1980", "BloodType: O+"])
// User creates a proof revealing only the birth year (proving age)
proof = bbs_create_presentation(signature, revealed_indices=[1], revealed_messages=["1980"])
// Verifier checks the proof without learning "Alice" or "BloodType: O+"
is_valid = bbs_verify_presentation(issuer_pk, proof, revealed_messages=["1980"])

The security relies on the q-SDH assumption and the Random Oracle Model, making it computationally infeasible to forge signatures or proofs.

When integrating, you must manage the cryptographic binding between the signature and the credential's identifier (e.g., a schema_id). The BBS+ signature does not sign the raw attribute values directly but signs their integer representations after a hash-to-scalar operation. This ensures the attributes are properly committed to before signing. Libraries handle this, but developers must ensure attribute encoding is consistent between issuance and presentation. Failure to do so will cause verification to fail.

The primary advantage over simpler schemes is unlinkability. Multiple presentations from the same credential cannot be linked together by the verifier, providing strong privacy for repeated attestations. This makes BBS+ ideal for sensitive applications like health data, where a patient might need to prove insurance eligibility to a clinic and vaccination status to an employer without allowing those parties to collude and build a complete profile.

implementation-zkp
PRACTICAL IMPLEMENTATION

Step 2: Implementing a Zero-Knowledge Proof

This guide walks through building a selective disclosure proof for a health record, allowing a patient to prove specific attributes (like being over 18) without revealing the underlying data.

Selective disclosure is a core privacy feature enabled by zero-knowledge proofs (ZKPs). In our health record scenario, a user holds a credential containing multiple attributes: dateOfBirth, bloodType, and vaccinationStatus. Using a ZKP, they can generate a proof for a verifier (like a pharmacy) that cryptographically demonstrates a statement such as currentYear - dateOfBirth > 18 is true, without exposing the actual birth year or any other credential data. This moves beyond all-or-nothing credential sharing to granular, privacy-preserving verification.

We will implement this using Circom, a popular domain-specific language for writing arithmetic circuits, and the snarkjs toolkit. The first step is to define the circuit logic. We create a Circom template that takes the private witness inputs (the full credential data and a secret) and public inputs (the current year and the disclosed minimum age). The circuit's constraints will compute the age from the birth year and enforce that it is greater than the threshold.

Here is a simplified Circom circuit template for the age verification logic:

circom
pragma circom 2.0.0;
template AgeCheck() {
    // Private inputs (known only to prover)
    signal input birthYear;
    signal input secret;
    // Public inputs (known to prover & verifier)
    signal input currentYear;
    signal input minAge;
    // Public output (the proof's claim)
    signal output verified;
    // Compute age
    signal age <== currentYear - birthYear;
    // Constraint: age must be greater than or equal to minAge
    age - minAge >= 0;
    // Additional constraint: the prover knows a valid 'secret' tied to the credential
    // This links the proof to a specific signed credential.
    // For simplicity, we show a check against a public hash.
    component hash = Poseidon(2);
    hash.in[0] <== birthYear;
    hash.in[1] <== secret;
    // The verified output is set to 1 if all constraints are satisfied
    verified <== 1;
}

This circuit ensures the prover knows a birthYear that, when subtracted from the currentYear, yields an age meeting the minimum requirement, and that this birthYear is cryptographically committed to with a valid secret.

After compiling the circuit with circom, we perform a trusted setup using snarkjs to generate proving and verification keys. The prover (the patient's wallet) then uses the proving key, their private witness data (birthYear, secret), and the public parameters (currentYear: 2024, minAge: 18) to generate a zk-SNARK proof. This proof is a small, easily-verifiable piece of data. The verifier (the pharmacy's server) only needs the verification key, the public inputs, and the proof to check its validity, requiring no trusted connection or exposure of the patient's personal data.

Integrating this into an application requires a verifier smart contract. The verification key is embedded into a Solidity contract. The pharmacy's backend submits the public inputs and the proof to this contract's verifyProof function. A return value of true confirms the proof is valid, allowing the service to proceed. This creates a trustless, automated check. For production, systems like Semaphore or zkKit offer higher-level libraries to manage identity, credentials, and these proof generations, abstracting away much of the cryptographic complexity.

Key considerations for implementation include choosing the right proving system (Groth16 requires a trusted setup, while PLONK-family protocols can have universal setups), managing the trusted setup ceremony securely, and ensuring the underlying credential (like a Verifiable Credential signed by an issuer) is properly bound to the circuit's secret to prevent proof forgery. The end result is a user flow where sharing proof of age is as simple as clicking a button, with no sensitive data ever leaving the user's device.

verification-flow
IMPLEMENTING SELECTIVE DISCLOSURE

Step 3: Building the Verification System

This section details how to construct the core logic that allows patients to prove specific claims from their health records without revealing the entire document.

Selective disclosure is the cryptographic mechanism that enables a verifier (like an insurance provider) to confirm a specific patient attribute—such as being over 18 or having a certain vaccination—without learning any other information from the Verifiable Credential (VC). This is achieved using Zero-Knowledge Proofs (ZKPs), specifically BBS+ signatures or CL signatures, which are supported by the W3C Verifiable Credentials Data Model. Instead of sending the full credential, the holder (patient) generates a Verifiable Presentation containing only the required, cryptographically proven claims.

To implement this, you first need a credential format that supports selective disclosure. JSON-LD with BBS+ signatures is a common choice. The issuer signs the credential, creating a digital signature over the entire JSON-LD document. When a holder needs to disclose only that "age" > 18 and "vaccinationStatus": "fully-vaccinated", they use a ZKP library like @mattrglobal/bbs-signatures to create a derived proof. This proof cryptographically demonstrates that the disclosed claims are part of a valid, unaltered credential signed by a trusted issuer, without revealing the signature on the undisclosed data.

Here is a simplified code example using a hypothetical ZKP SDK for creating a selective disclosure presentation:

javascript
// Patient holds a full HealthCredential VC
const fullCredential = healthWallet.getCredential('covidVaxCredential');

// Define which claims to disclose selectively
const disclosureFrame = {
  '@context': 'https://schema.org',
  'vaccinationStatus': true, // Disclose this value
  'issuanceDate': true,      // Disclose this value
  'patientBirthDate': false  // Keep this hidden, only prove >18
};

// Generate a Verifiable Presentation with a ZK proof
const verifiablePresentation = await zkpSDK.createPresentation(
  fullCredential,
  disclosureFrame,
  { nonce: verifierProvidedNonce } // Prevents replay attacks
);

// Send only the VP to the verifier
sendToVerifier(verifiablePresentation);

The verifier then uses the issuer's public key and the provided nonce to verify the proof's validity.

The verifier's system must be built to request specific claims using a Presentation Definition, as formalized by the Presentation Exchange (PX) specification. This definition is a machine-readable format that specifies exactly which claims are required, any predicates (e.g., "age" >= 18), and the accepted credential schemas. The verifier sends this definition to the patient's wallet. Upon receiving the resulting Verifiable Presentation, the verifier's backend calls a verification library to check the ZKP signature and ensure all requested disclosures are satisfied. This process ensures data minimization by design.

Key security considerations for this system include nonce management to prevent proof replay attacks, schema validation to ensure the credential structure is correct, and issuer DID resolution to fetch the current public key for signature verification. The entire flow—from presentation request to proof verification—can be implemented using open-source frameworks like Veramo or Trinsic, which abstract much of the complex cryptography while maintaining interoperability with W3C standards.

IMPLEMENTATION PATTERNS

Code Examples by Use Case

Verifying a Single Credential

This pattern demonstrates how to verify a single signed credential, such as a vaccination record, without revealing the patient's full identity.

Core Components:

  • Verifiable Credential (VC): A JSON-LD document containing the health claim.
  • Selective Disclosure: Using BBS+ signatures to reveal only specific predicates (e.g., vaccinationStatus is true).
  • Verifier Policy: Rules defining which claims must be proven.
javascript
// Example using @mattrglobal/node-bbs-signatures
const { BbsSigner, BbsVerifier } = require('@mattrglobal/node-bbs-signatures');

// Patient discloses only that they are vaccinated, not the date or vaccine type.
const disclosedIndices = [1]; // Index of the 'vaccinationStatus' claim in the VC
const proof = await BbsSigner.createProof({
  messages: originalMessages, // Full credential messages
  disclosedIndices,
  nonce: verifierNonce,
});

// Verifier checks the proof against the public key and the disclosed claim.
const isVerified = await BbsVerifier.verifyProof({
  proof,
  publicKey: issuerPublicKey,
  messages: disclosedMessages, // Only the 'true' value for vaccinationStatus
  nonce: verifierNonce,
});

This allows a patient to prove eligibility for an event while maintaining privacy over other health details.

DEVELOPER GUIDE

Frequently Asked Questions

Common technical questions and solutions for implementing selective disclosure in on-chain health record systems.

Selective disclosure is a cryptographic principle that allows a user to prove specific claims from a larger set of data without revealing the entire dataset. For health records, this means a patient can prove they are over 18, have a specific vaccination, or meet a lab result threshold without exposing their full medical history.

This is critical for privacy-preserving compliance with regulations like HIPAA or GDPR on-chain. Without it, storing verifiable credentials or zero-knowledge proofs would require revealing all attested data, creating significant privacy risks. Protocols like zk-SNARKs (e.g., Circom, Halo2) and BBS+ signatures are commonly used to implement these proofs, allowing verification of predicates (age > 18) instead of raw data.

conclusion
IMPLEMENTATION ROADMAP

Conclusion and Next Steps

This guide has outlined the core principles of using zero-knowledge proofs for selective disclosure in health records. The next step is to translate these concepts into a functional system.

To implement a production-ready system, you must choose a ZK-SNARK framework suited for your data model. For complex health schemas with many optional fields, Circom offers fine-grained circuit design. For simpler claims or integration with existing identity systems, zk-SNARKs in Noir or zk-STARKs with StarkWare may be more efficient. The choice impacts proving time, trust setup requirements, and developer experience. Always benchmark with your specific data payloads.

The architecture requires three core components: a circuit that validates data integrity and generates proofs, an off-chain prover (often a backend service), and an on-chain verifier (a smart contract). For example, an Ethereum verifier contract using the Groth16 verifier from snarkjs would contain the verification key and a function like verifyHealthCredential(bytes calldata proof, uint256[] calldata publicSignals). The public signals would include the hash of the disclosed data and a nullifier to prevent double-spending of the credential.

Consider these practical next steps for your project. First, define a standardized schema for your health credentials, such as aligning with W3C Verifiable Credentials or HL7 FHIR data models. Second, implement a secure wallet for users to store their credentials and generate proofs client-side, using libraries like iden3's js-snarkjs or zkp.js. Third, plan for key management and revocation, potentially using semaphore-style nullifiers or time-based credential expiry.

For further learning, explore these resources: the Circom documentation provides circuit-writing tutorials; the ETHResearch forum hosts advanced discussions on ZKP privacy; and projects like zkEmail demonstrate real-world data parsing in circuits. Start with a minimal proof-of-concept, such as proving age over 18 from a birth date without revealing the date itself, before scaling to full health records. The goal is to give patients cryptographic control over their personal data.