{"id":23364453,"url":"https://github.com/fission-codes/zerowallet-poc","last_synced_at":"2025-10-24T01:50:15.417Z","repository":{"id":43549255,"uuid":"219594969","full_name":"fission-codes/zerowallet-poc","owner":"fission-codes","description":"Proof of concept for identity derived from zerowallet","archived":false,"fork":false,"pushed_at":"2022-12-11T12:03:48.000Z","size":3541,"stargazers_count":6,"open_issues_count":25,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-07-07T10:26:30.901Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fission-codes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-04T20:55:45.000Z","updated_at":"2024-04-22T02:12:56.000Z","dependencies_parsed_at":"2022-08-19T14:30:55.950Z","dependency_job_id":null,"html_url":"https://github.com/fission-codes/zerowallet-poc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fission-codes/zerowallet-poc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fission-codes%2Fzerowallet-poc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fission-codes%2Fzerowallet-poc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fission-codes%2Fzerowallet-poc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fission-codes%2Fzerowallet-poc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fission-codes","download_url":"https://codeload.github.com/fission-codes/zerowallet-poc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fission-codes%2Fzerowallet-poc/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264900038,"owners_count":23680540,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-21T13:16:11.484Z","updated_at":"2025-10-24T01:50:15.333Z","avatar_url":"https://github.com/fission-codes.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Identity Proof of Concept\n\nHere's a brief rundown of the architecture and setup behind our identity proof of concept that we just launched \n\nCheck out the app here: https://safe.fission.name/\n\n\u003cimg src=\"screenshot.png\" width=\"400\"\u003e\n\n## Overview\nThe goal of this application to to equip a user with a private key while providing UX similar to a traditional web app. \n\nIn the demo application, a user stores a private note in IPFS that is encrypted/decrypted with their private key.\n\nFor the first iteration of our identity system, we decided to use the [ZeroWallet](http://zerowallet.me/) scheme. \n\n## To Run Locally\n- Install dependencies\n  - `yarn`\n- Setup environment\n  - `cp .env.example .env`\n  - change variables\n- Run\n  - `yarn dev`\n  - Given defaults, your server will be on port `8080` and a React app will be on port `3000`\n\n## ZeroWallet\nZeroWallet is a simple scheme where a user generates a private key with two passwords, and unlocks their account on login using just a username and password.\n\nIt makes use of [Shamir's Secret Sharing](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing) and [zero-knowledge proofs](https://en.wikipedia.org/wiki/Zero-knowledge_proof) to allow recovery of private keys.\n\nZeroWallet uses 2 passwords and 3 shards. Any 2 shards can reconstruct the `privateKey`.\n\nAs a brief overview of the components:\n- **account password**: this is the password that a user generally uses to login to their account. Imagine a normal username/password signin\n- **recovery password**: this is the password that a user uses to recover their private key\n- **shard1**: this shard is just a hash of the account password (`shard1 = sha256(accountPassword)`)\n- **shard2**: this is the fancy part of the scheme that makes use of zero-knowledge proofs. You can read more about the nitty gritty details [Here](https://medium.com/@amanladia1/zerowallet-a-zkp-based-wallet-authentication-mechanism-9871dcca0a01). For the purpose here, think of it as `shard2 = serverTransform(sha256(recoveryPassword))`. What actually happens is similar to [Diffie-Hellman key exchange](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange). The important part of this is that the server gets no information about the user's share (`sha256(recoveryPassword)`), and a malicious hacker gets no information about the server's share by sending spoof requests.\n- **shard3**: this shard is derived from the first two using Shamir's Secret Sharing (SSS). SSS can come up with an essentially endless number of shards for a given private key. So `shard3` is actually unique per-device\n\n**Signup** flow (_I'm totally new here_)\n- user enters, `username`, `accountPassword`, and `recoveryPassword`\n- `recoveryPassword` is hashed and \"randomized\" into a value we'll call `alpha`, then sent to the server\n- the server generates an arbitrary 256-bit key `zk_key`. \n- `zk_key` is combined with `alpha` to produce `beta` which is sent back to the user\n- `beta` is \"derandomized\" to produce `shard2`\n- user generates `shard1 = sha256(accountPassword)`\n- user acquires `privateKey = SSS.combine(shard1, shard2)`\n- user generates `shard3 = SSS.newShard(privateKey`)\n- user stores `shard3` in `localStorage` and logs into the safe\n\n**Login** flow (_I've already logged onto this device before_)\n- user enters `username` and `accountPassword`\n- user generates `shard1 = sha256(accountPassword)`\n- user gets `shard3` from `localStorage`\n- user acquires `privateKey = SSS.combine(shard1, shard3)` and loogs into the safe\n\n**Recovery** flow (_I want to login on a new device_)\n- This is the exact same flow as **Signup** except that the server uses the `zk_key` that's already in the database\n\n## Encryption\nIf a user is only encrypting data for themselves, they can just encrypt/decrypt it with their `privateKey`. However, we wanted to build this in such a way that a \"sharing\" or \"social\" component could easily be added.\n\nTo do this, you don't want to have to re-encrypt your note for every friend that you want to share it with. This leads to a lot of data replication, and also puts a big load on the user since everytime they edit the note, it must be re-encrypted for every one of their friends.\n\nInstead, we encrypt the note with a symmetric key (`cipherKey`). Add the cipher text to IPFS. And then encrypt the `cipherKey` with the user's `privateKey`. Now, we have a simple setup that can be easily expanded to shared notes. If I want to share a note with you, I don't have to re-encrypt the entire note for your `publicKey`. I just have to encrypt and send you the `cipherKey`\n\n## Keystore\nI separated all \"key\" functionality into it's own module: `keystore`. Any code that touches private keys is always susceptible to attack (malicious packages, etc). We've discussed writing this module using WASM which essentially gives us a secure \"black box\" that other parts of our code can't acess, keeping these keys safe.\n\n## Database\nFor the time being, we store just 4 things in the database: `username`, `zk_key`, `safe_cid`, and `safe_key`.\n\nThe first two are for ZeroWallet. `username` is self-explanatory, `zk_key` is the server's \"share\" of the second shard of the user's `privateKey`. By itself, it reveals absolutely nothing about the second shard, but it can be used to transform the user's recovery password in such a manner that they can recover the second shard without revealing any information to the server.\n\n`safe_cid` is the current CID of the encrypted safe, and `safe_key` is an encrypted `cipherKey` for the safe. `safe_cid` and `safe_key` are currently stored in our database for convenience sake, but would eventually be moved to some form of decentralized storage (OrbitDB spike coming as we speak!)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffission-codes%2Fzerowallet-poc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffission-codes%2Fzerowallet-poc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffission-codes%2Fzerowallet-poc/lists"}