The steps involved in uploading a file are: 1) The user uploads the file to the web application and enters the public keys of the Ethereum addresses of the recipients. The recipients must share their public keys with the user who wants to share the file (5 different public keys is a must for the demo. The reason is, if we are building a ‘private’ file sharing platform also the user who uploads shouldn’t know the real address of the receiver so there is 20% possibility) 2 ) The file is then encrypted with each of the public keys and uploaded to IPFS. (different IPFS files encrypted with different public keys) 3) The IPFS URLs are encrypted with each of the public keys and hashes of the public keys are uploaded to the smart contract. (different IPFS URLs) To access the file, the recipients must follow these steps: 1) The recipient opens the web app and navigates to the specific page URI (e.g., localhost:8080/file?=0x1C66D49FB1e9782Aa838A2Ec9fa6F346C85096E0) with the address of the person who shared the file. (Here we should get the URL parameter (address) and get the mapping which contains all of the encrypted IPFS urls and public keys. This will be struct most probably.) 2) The recipient generates a proof off-chain which contains his/her public key. (In the circuit the public key is hashed with mimcsponge, also public keys stored in the contract are also hashed with mimcsponge) 3) The recipient then sends a proof and the hashed public key, which is verified by the ZKP contract. If the proof is valid, an event will be emitted which contains the hashed IPFS URI, also the file senders address (key in the map) will be emitted to distinguish different file senders / files. The file sender address in the event will be compared with the address in the web app URI (.com/file?=0x....). The structure might be: ```mapping(address => mapping(hashedPublicKey => encryptedIPFS))``` 4) The event listener on the frontend receives an event and returns it to the user that sends the proof. (The data here is the encrypted IPFS URL) The use of ZKP ensures that only the intended recipient can access the file, as they are the only ones who possess the private key required to decrypt the IPFS URL. The encrypted IPFS URLs stored on the contract provide an additional layer of security, as only the intended recipient with the correct public key can access them. ```mermaid sequenceDiagram actor R as Recipients actor A as Alice participant W as WebUI participant S as SmartContract R->>A: Send public keys Note right of A: X different public keys is a must for the demo. The reason is, if we are building a ‘private’ file sharing platform also the user who uploads shouldn’t know the real address of the receiver so there is 20% possibility A->>W: Upload file A->>W: Enter recipients addresses A->A: Encrypt files with public keys A->IPFS: Send encrypted files A->A: Hash each recipients public hash A->S: Send encrypted IPFS URLs with public keys hashes ``` ```mermaid sequenceDiagram actor R as Recipients participant W as WebUI participant S as SmartContract R->>W: Enter the address of Alice R->>R: Generate proof of public key R->>S: Use SmartContract proof validator S->>W: Return the encrypted IPFS URL W->>R: Display encrypted IPFS URL R->>R: Decrypt IPFS URL using private key IPFS->>R: Obtain the file using the deciphered URL Note right of R: Theses last steps can be done on the WebUI R->>R: Decrypt file content using private key ```