# Efficient and Secure EMR Storage and Sharing Scheme Based on Hyperledger Fabric and IPFS
## 3 Framework Components
### zk-SNARKs  
A zero-knowledge proof (ZKP) requires the participation of both a prover and verifier. In employing the ZKP techniques, the prover can convince the verifier of the truthfulness of a statement without revealing any useful information related to the statement beyond its truth. ZKP has been widely utilized in identity authentication [22].  
ZKPs can be categorized into interactive and non-interactive types. A non-interactive proof requires at most one authentication interaction during the verification process, thereby reducing the communication overhead caused by multiple interactions in the proof process, especially in blockchain systems. The Zero-Knowledge Succinct Non-Interactive Argument of Knowledge (zk-SNARKs) [23], Zero-Knowledge Scalable Transparent Argument of Knowledge (zk-STARKs) [24], and Bulletproofs [25] are three typical non-interactive ZKP schemes. Table 2 presents a comparison of three typical non-interactive ZKP technologies. zk-SNARKs have the smallest proof size. Verifiers of zk-SNARKs only need to check a fixed-size structure, such as the verification key and proof. This eliminates the need to reproduce or understand the original computation. Consequently, verifiers can complete the verification in a very short time, which is crucial for enhancing the scalability and efficiency of blockchain systems.  
Zokrates [26] is a ZKP toolkit that includes a Domain-Specific Language (DSL) processor, compiler, and zk-SNARKs generator. The zk-SNARKs process is facilitated in Zokrates by initializing a zokratesProvider object, with the option to choose Groth16 [27] as the verification scheme during initialization. This process encompasses the generation of proof key \(PK\) and verification key \(VK\), the generation of proof \(pf\), and the verification of \(pf\).  
Figure 1 illustrates the process of generating proof and verifying it using zk-SNARKs through Zokrates. The steps are as follows:  
1. \(Setup(f)\rightarrow(PK,VK)\): Use DSL to describe the constraint verification program intended for ZKP implementation, denoted as \(sourceCode\). Next, compile it to generate the internal arithmetic circuit representation, denoted as \(f=compile(sourceCode)\). Finally, generate the key pair \((PK,VK)\) by constructing \(Setup\).  
\begin{table}
\begin{tabular}{c c c c} \hline \hline  & **zk-SNARKs** & **zk-STARKs** & **Bulletproofs** \\ \hline \hline Algorithmic complexity of the prover & O(N-log(N)) & O(N-polylog(N)) & O(N-log(N)) \\ Algorithmic complexity of the verifier & O(1) & O(polylog(N)) & O(N) \\ Communication complexity & O(1) & O(polylog(N)) & O(log(N)) \\
1 TX proof size & 200 B & 45 KB & 1.5 KB \\ \hline \hline \end{tabular}
\end{table}
Table 2: Comparison of zk-SNARKs, zk-STARKs, and Bulletproofs.  
2. \(GenProof(f,witness,PK)\to proof\): Given the public input \(input_{pub}\) and the private input \(input_{pri}\), compute \(witness=compute(f,[input_{pub},input_{pri}])\). Finally, generate the proof using Equation (1): \[pf=GenProof(f,witness,PK).\] (1)
3. \(Verify(VK,proof)\to result\): When there is a verification requirement, the correctness of \(pf\) can be verified by constructing \(Verify\) and providing \(pf\) and its corresponding \(VK\) as inputs.