VC ZK Health Records (VC-ZK HR) project was built during a Digital Identity Hackathon sponsored by Onyx by J.P. Morgan and hosted by Encode Club. This project showcases a real practical use of DIDs (Decentralized IDs), VCs (Verifiable Credentials), and ZKP (Zero-Knowlegde Proofs) in the Healthcare Industry. An objective is to prove how Web3 can act as the forefront technology for a interoperable privacy preserving layer between multiple Healthcare providers software applications.
- Interoperability - Electronic Health/Medical Records (EHR/EMR) are complex due to a high number of standards implemented in various areas within healthcare. Technology leaders like Epic Systems, SMART, CommonWell Health Alliance, and Apple's Health App are supporting the free and open standards of FHIR specifications by HL7. This project demonstrates building with FHIR, USDCI test sample data, and an open source healthcare developer platform called Medplum.
- Privacy/Sharing - Lack of interoperability increases possibilities for data breaches and mishandling patient records. Reverting to paper records or keeping data private is not the answer in healthcare. Even the rise of AI has caused data to become a modern day gold rush causing companies to put up paywalls for data. Zero-Knowledge protocols can provide an opportunity to share data like never before and move the needle towards precision medicine. This project demonstrates the use of zk-STARK and RISC Zero's zkVM.
- Ease-of-use - Account abstraction and EIP-4337 provided the opportunity for an overall improved user experience into Web3. This project demonstrates the use of Biconomy's Smart Accounts Platform based on ERC-4337 and Magic's developer SDK for Web3 onboarding.
-
Sends FHIR based electronic health record (EHR) to the zkVM to generate a Receipt. The full receipt is written to a file, zkp_receipt.json, in the zk app to be used during the proof verification. Details of the verification will be found in the Verifier section.
- A receipt contains a journal containing the public outputs of the zkVM application. In this project, the committed outputs include a SHA256 hash of the privately loaded health record into the Guest code from the Host. The Guest code also searches the desired fields from the health record to prove that these fields exist in the complete health record. If not found, the proof is not generated. Additionally, the values of each searched field are committed to the public output. These values will represent the meaningful data for a verifier to know while keeping all other information from the health record private.
- A seal, or the zk-STARK, that attests the correct execution of the proven statement (aka guest program) is also found in the receipt. In this project, the seal is not passed to the verifier and is mentioned in the Verifier section.
- An ImageID is included with the public outputs for use during the zk proof validation.
-
Onyx SDK API executes
create-and-sign-vc_with_schema_params.ts
to produce the verifiable credential (VC) issued by the Healthcare Provider. In details, the following occurs:- An arbitrary expiration date (1 year) is added to the VC.
- Schema validation performed on the FHIR EHR using the
fhir.schema.json
file. Accuracy of the file is not verified and was obtained from this Asymmetrik FHIR API Server project. - Signed VC is written to file,
medicationRequest_vc.json
, simply simulating DB store at the issuer.
- Explanation of how DID keys are being managed: DID:Keys are read from an .env file as a focus for this project is to not have a patient tracking multiple private keys. It's expected that the private keys are managed by the health provider for both itself (issuer) and the patient (holder). A trusted health provider will securely store electronic health records with the patient's private keys and ensure correct use of the DID:key upon issuing a VC. The soulbound NFT receipt will contain a DID:key that references to a signed VC and is sent to the patient's Smart Account during the creation of the VP. Any NFT receipt sent to the patient's smart account without being processed through the Biconomy paymaster can be viewed as untrusted. Since the patient needs to authorize the creation of a VP via the Magic link step in the flow of the program, an untrusted issuer will not be able to issue a malicious VC on the patient. A verifier will be able to verify the patient's NFT Receipt, the VP token, and zk proof for correctness in the trust triangle.
-
Sequence Ends, Patient has access to view the VC.
- Fulfils Identity Authorization to request for a verifiable presentation (VP). The Identity Authorization requires signing into a Magic link.
- Onyx SDK API executes
create-and-sign-vp.ts
to produce the verifiable presentation (VP) issued by the patient. - Signed VP is written to file,
medicationRequest_vp.json
, simply simulating DB store at the issuer. - SoulBound NFT Receipt token is minted and sent to the Patient's Smart Account address:
0xae2Dd7f355bE651A71E72B780cdEf3D38a7EDAf6
on Polygon's Mumbai Testnet. In detail, the following occurs:- The
DID:Key
representing the Issuers signed VC is added to a metadata object and uploaded to IPFS via Pinata to obtain a CID for use during the minting of the NFT Receipt token. - Biconomy's Sponsored Paymaster Service creates a gasless experience for the patient. Signing onto Magic link is a requirement for the process to run.
- The VC SoulBound Receipt Contract address:
0x50F49A3B09BD7597ff588686843d9b03070EdCbe
was previously setup and deployed on the testnet. The patient's smart account address was also granted a MINTER_ROLE for the project demo. Remix was utilized to setup the NFT contract for the project's demo. No UI has been created for granting/revoking of roles or NFT token burn at the completion of this hackathon project.
- The
- Sequence Ends, Patient has access to the signed VP and able to share with a verifier.
- The application displays a Verifier section to simulate the verification procedures. Running the
Verify Signed JWT
is needed before running theVerify Zero Knowledge Proof
in the application to reveal the payload of a decoded VP, resulting with the signed VC. - Onyx SDK API executes
verify.ts
confirming a valid signed VP/VC JWT token. - During the zk proof verification, the payload of the signed VC token is decoded to retain the ImageID. The ImageID is sent to the zkVM API to execute the
receipt.verify(ImageID)
method for proof verification. The receipt itself is read from the file, zkp_receipt.json, simulating a possible zk receipt registry. In this project, the file will only contain the last generated zk proof. - In this project, I applied a reversed approach on the zk proof verification process compared to the method described by RISC zero. The method described in the link has the prover sending the full receipt to the verifier.
- This zkVM app instead returns only the ImageID and the journal portion of the receipt.
- RISC zero has a zk proof as a service type of feature in development called Bonsai potentially to serve as a more viable use in the healthcare industry versus running separate zkVMs. This project is simulating this type of user experience.
- Additionally, a verifier can manually verify the patient's smart account for the NFT Receipt to match the
DID:Key
related to a verifiable credential. - Sequence Ends, zk proof verified.
- A free and open-source sample healthcare webapp by the Medplum Team was used for this project to bootstrap the secure and compliant backend as well as learning and applying the FHIR standards to create a more realistic Healthcare project.
- The following UI components are the focus of this project:
medication.tsx
- Process from FHIR resource data > zkVM > signed VCVcItem.tsx
- Patient signing of Verifiable CredentialsVpItem.tsx
- Patient issuing of Verifiable PresentationsVerifyItem.tsx
- Verifier validations
- The following components were added or modified from Onyx's original SDK to meet the needs to the project
create-and-sign-vc_with_schema_params.ts
- Health Providercreate-and-sign-vp.ts
- Patientverify.ts
- Verifierapp.ts
- API server to access SDK from FrontenduploadMetadata.ts
- NFT metadata processing
- Created smart contract code using Foundry
VCSoulBoundReceipt.sol
VCSoulBoundReceipt_flatten.sol
- For verifying contract on testnet
- Created with Rust
main.rs
- API server with Actixlib.rs
- Host code using RISC zero zkVMmain.rs
- Guest code using RISC zero zkVM
[Patient]
- Click
Log in
button on the top-right of screen: - Login with the sample profile to ensure sample data are loaded: username:
[email protected]
and password:encode_onyx
- Click on
Health Record
- Click
Medications
on left sidebar - Click on one of the 2 sample Medication Request records
- Click the
Request VC
link to generate a signed verifiable credential with zk proof - A modal will appear, click
Submit VC Request
- After issued VC is created, a link will appear. Click on link to navigate to the VC section and view the available VCs
- Click on an available VC to view the details page
- A chevron icon is available to display the VC token string. Copy and paste into the
Encoded
section of this JWT site to decode and view the payload - Click button to sign the issued VC and create a VP
- Click
View/Share Proof of Credentials
in the sidebar section - Clink on an available VP
- A chevron icon is available to display the VP token string. Copy and paste into the
Encoded
section of this JWT site to decode and view the payload - Click button to login via Magic link
- Login with an email.
- Click on submit button to generate a NFT Receipt and send to your smart account.
In order to get beyond this point, you need to Sign-up for your own account on Medplum and load in the sample data from the Medplum tutorials. In the Medplum.app, locate a medication request record and view the raw JSON. Copy and create a new medication request record and apply the Patient ID that is assigned to your Medplum account. Then deploy your own NFT SoulBound contract, verify it on Polygon's testnet, setup a Biconomy Paymaster and create a policy allowing a safe mint user op on the NFT contract, and grant the necessary MINTER_ROLE to the Smart Account that gets generated during the Biconomy/Magic login. Feel free to reach out to me if you have questions. - After NFT mint is complete, a link will display.
- Clink link to see on OpenSea Testnets
- Clink on the TokenID in the Details section to view the metadata from IPFS.
[Verifier]
- Click on
**Demo Only** - Verifiers
in the sidebar of theVerifiable Credentials
section - Click on each
Verify
button to perform describe verification. Chevron icons are available to view the JWT strings
The NFT Receipt portion of the app can be ignored if you don't want to setup the Web3 related items in the env file. Otherwise the following will be needed:
- Deploy SoulBound NFT contract, grant MINTER_ROLES to Biconomy Smart Account address, and Verify contract on Polygon Mumbai Testnet
- Setup Biconomy Paymaster, Deposit Mumbai testnet Matic tokens in Gas-Tank, add NFT contract to the policy allowing the
safeMint
method. - Setup a Magic account
- For Frontend: env
- For Onyx SDK: env
- Run script to create keys for env file:
cd ./med_app/packages/onyx-ssi-sdk
npm run create:keypair
- Run script to create keys for env file:
- Frontend - runs on port:3000
- Onyx API - runs on port:3001
- zkVM API - runs on port:8080
cd med-app
npm install
npm run dev
cd packages/onyx-ssi-sdk
npm run dev
// Return to project root directory
cd zk_app
cargo run --release
Open in browser, localhost:3000, enjoy!
- Revise or replace zk proof system as needed pending revisions from zk protocols.
- Add in all available FHIR resource types for increased compatibility and testing.
- Build out messaging using a Web3 protocol.
- Build or integrate medical billing feature targeting ICD-10-CM and/or Current Procedural Terminology (CPT).
- Add/Revise DID methods.
- Encountered random userOp issues during the Biconomy Paymaster setup preventing the NFT Mint to fail. RPC was updated to Alchemy to try and remedy. If issue occurs, just try again after a few minutes and it seemed to work for me.