{"id":18357327,"url":"https://github.com/nethermindeth/research-mnemonic","last_synced_at":"2025-04-06T13:31:18.558Z","repository":{"id":39863129,"uuid":"460085564","full_name":"NethermindEth/research-mnemonic","owner":"NethermindEth","description":"Shamir secret sharing for mnemonic lists","archived":false,"fork":false,"pushed_at":"2022-09-26T10:32:53.000Z","size":835,"stargazers_count":17,"open_issues_count":1,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-22T00:34:03.247Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NethermindEth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-02-16T16:28:13.000Z","updated_at":"2024-10-22T16:04:35.000Z","dependencies_parsed_at":"2023-01-17T18:31:12.449Z","dependency_job_id":null,"html_url":"https://github.com/NethermindEth/research-mnemonic","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NethermindEth%2Fresearch-mnemonic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NethermindEth%2Fresearch-mnemonic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NethermindEth%2Fresearch-mnemonic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NethermindEth%2Fresearch-mnemonic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NethermindEth","download_url":"https://codeload.github.com/NethermindEth/research-mnemonic/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247488441,"owners_count":20946946,"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-11-05T22:13:25.596Z","updated_at":"2025-04-06T13:31:17.978Z","avatar_url":"https://github.com/NethermindEth.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Readme\n\n## Table of contents\n  * [Description](#description)\n  * [Notation](#notation)\n  * [Shamir's secret sharing scheme (SSS)](#shamir-secret-sharing-scheme)\n  * [Generating shares and reconstruction of the secret](#generating-shares-and-reconstruction-of-the-secret)\n  * [Working with the project](#working-with-the-project)\n  * [Basic usage](#basic-usage)\n  * [Using with Docker build](#using-with-docker-build)\n  * [Format of a share](#format-of-a-share)\n  * [Design rationale](#design-rationale)\n  * [References](#references)\n\n## Description\nIn this project we implement a modified version of Shamir’s secret sharing scheme (SSS) in order to share a secret phrase, called mnemonics, in a secure way. In the following we give the notation that we use, then we give the definition of Shamir's secret sharing scheme and our modified scheme. We  describe how we generate shares and reconstruct the secret. Then we give a basic usage information and the format of a share file. Finally, we give a few comments on design rationale.\n\n## Notation\n\n| Symbol | Descripton |\n| --- | --- |\n| *n*\t| Number of shares |\n| *t*\t| Threshold |\n| *s*\t| Secret |\n| *D*\t| Digest of the secret |\n| *nb*\t| Number of bits, e.i. *nb = log\u003csub\u003e2\u003c/sub\u003e len(dictionary)*|\n| *nw*\t| Number of words in the mnemonic, e.i. *nw = len(secret)* |\n| *m*\t| Size of *q* in bits, e.i. *m = nb * nw* |\n| *q*\t| Order of the Galois field, e.i. *q = 2\u003csup\u003em\u003c/sup\u003e* |\n|  F\t| Galois field, e.i. F = GF(*q*)|\n| *d*\t| Number of bits taken from the hash of the secret, the first part of the digest *D*. |\n| *R*\t| Number of bits of the randomness which is the remaining part of the digest *D*. |\n\n## Shamir secret sharing scheme\n\nLet F be a finite field with q elements. A *(t, n)-threshold secret sharing scheme* shares a non-zero secret *s* among *n* users such that any *t* or more shares can reconstruct the secret but *t-1* or less cannot. Shamir's secret sharing scheme is an ideal and perfect *(t, n)-thresholds scheme* and can be defined in two phases as follows:\n\n### 1. Share Generation Phase:\n\n+ A dealer chooses a secret polynomial *f(x)* with degree *t-1*, such that its constant term is the secret to be shared *s*.\n\n+ The dealer sends the tuple *(x\u003csub\u003ei\u003c/sub\u003e, f(x\u003csub\u003ei\u003c/sub\u003e))* as the share to *i*-th user, where *x\u003csub\u003ei\u003c/sub\u003e*'s are all non-zero and distinct for *i = 1, … , n*.\n\n### 2. Reconstruction Phase: \n\n+ If any *t* or more users jointly perform a Lagrange interpolation with their shares, they obtain the secret polynomial *f(x)*, and *f(0)* yields the secret *s*.\n\n## Generating shares and reconstruction of the secret\n\nIn addition to the above definition, we also encode the digest of the secret as *f(q-1)* as stated in SLIP-0039: Shamir's Secret-Sharing for Mnemonic Codes. Let *s* be the secret to be shared and *D* be it's digest such that, *D =* HMAC-SHA256(*R || s*)[*:d*] || *R*, where *R* is the randomness with length *m-d* in bits, for *m = log\u003csub\u003e2\u003c/sub\u003e q* and some integer *d*. \n\n![shamir](images/shamir.jpg)\n\nIn other words the digest share *D* is composed of two parts; first *d*-bit part is the first *d* bits of the output of the hash function and the remaining part is a randomness with *m-d* bit length.\n\n![digest](images/digest.jpg)\n \nOur scheme takes a secret mnemonic as string, converts it to binary string and performs padding if needed. Then it is converted to integer. After generating the integer shares, all the shares are converted into string and parsed as distinct n mnemonics. Below we describe Lagrange polynomial interpolation, share generation and secret reconstruction. \n\n### Polynomial interpolation\nLagrange interpolation formula tells us that constructing a degree *t-1* polynomial requires at least *t* points. Assume that we have *t* distinct points *(x\u003csub\u003e1\u003c/sub\u003e,y\u003csub\u003e1\u003c/sub\u003e), (x\u003csub\u003e2\u003c/sub\u003e, y\u003csub\u003e2\u003c/sub\u003e), … , (x\u003csub\u003et\u003c/sub\u003e, y\u003csub\u003et\u003c/sub\u003e)*. Then we can construct the unique degree *t-1* polynomial as follows: \n\n![lagrange](images/lagrange.jpg)\n \nwhere *l\u003csub\u003ej\u003c/sub\u003e(x)* is the Lagrange basis polynomial with respect to the *j*-th point, i.e.\n\n![lagrange_basis](images/lagrange_basis.jpg)\n\n### Share Generation\n\n#### INPUT: secret *s*, total number of shares *n*, threshold *t*, order of Galois field *q*, irreducible polynomial of GF(*q*) \n\n#### OUTPUT: list of *n* shares\n\n+ Encode *s = f(0)* and the digest *D = f(q-1)*.\n+ Pick random *t-2* more points, i.e. *(x\u003csub\u003e1\u003c/sub\u003e, y\u003csub\u003e1\u003c/sub\u003e), (x\u003csub\u003e2\u003c/sub\u003e, y\u003csub\u003e2\u003c/sub\u003e), … , (x\u003csub\u003et-2\u003c/sub\u003e, y\u003csub\u003et-2\u003c/sub\u003e)*.\n+ Using the shares *(0, s), (q-1, D), (x\u003csub\u003e1\u003c/sub\u003e, y\u003csub\u003e1\u003c/sub\u003e), (x\u003csub\u003e2\u003c/sub\u003e, y\u003csub\u003e2\u003c/sub\u003e), … , (x\u003csub\u003et-2\u003c/sub\u003e, y\u003csub\u003et-2\u003c/sub\u003e)*, perform Lagrange interpolation and construct the unique degree *t-1* polynomial *f(x)*.\n+ Generate *n-t+2* more shares by evaluating *f(x)* at the points *x\u003csub\u003et-1\u003c/sub\u003e, … , x\u003csub\u003en\u003c/sub\u003e*. \n+ Output *n* shares *(x\u003csub\u003ei\u003c/sub\u003e, y\u003csub\u003ei\u003c/sub\u003e)* for *i = 1, … , n*.\n\n### Secret Reconstruction\n#### INPUT: list of share id *x*, list of access shares *y*, order of Galois field *q*, irreducible polynomial of GF(*q*), digest length *d*.\n#### OUTPUT: secret *s'* or abort.\n+ Apply Lagrange interpolation for the shares *(x\u003csub\u003ej\u003c/sub\u003e , y\u003csub\u003ej\u003c/sub\u003e) for j = i\u003csub\u003e1\u003c/sub\u003e, … , i\u003csub\u003et\u003c/sub\u003e*, and recover the secret polynomial *f(x)*.\n+ Compute the secret *s' = f(0)*\n+ Compute the digest *D' = f(-1)*\n+ If HMAC-SHA256(*D'*[*d:*] || *s'*)[*:d*] = *D'*[*:d*], then return *s'*. Otherwise abort.\n\n## Working with the project\n\n+ Project uses Pipenv as a tool to manage packages and their versions properly.\n\n+ Make sure you have pipenv installed on your local machine or install it using\n\n```shell\npython -m pip install pipenv\n```\n\n+ Install the required packages using \n\n```shell\npipenv install\n```\n\n+ Run the project using (Read [Basic usage](#basic-usage) for detailed Information)\n\n```shell\npipenv run python main.py\n```\n\n\n## Basic usage\n+ One can share his secret by running below command in the terminal.\n\n\t```Python\n\t  Python main.py create_shares -n [number of shares] -t [threshold value] -s [path/secret.txt] -v [optional]\n\t ```\n+ If the secret file is not defined then the secret is requested to be typed on the terminal. \n\n+ The **reconstruct.py** takes *json* files automatically from the same location and outputs the secret *s* if the number of the shares is enough.\n\n## Using with Docker build\n\n+ You can directly use this app using Docker cli without installing anything.\n Make sure you have docker cli available on your machine.\n\n+ Create a `shares` directory wherever you want to store the files this \napp will generate. This is necessary for the app to function correctly.\n\n```\nmkdir shares\n```\n\n+ Run this command to generate shares (Make sure to replace CURRENT_VERSION \nwith appropriate version numbers)\n\n```\ndocker run -v shares:/usr/src/app/shares nethermindeth/research-mnemonic:CURRENT_VERSION main.py create_shares -n 4 -t 4\n```\n\n+ Run this to reconstruct words from data in shares directory.\n\n```\ndocker run -v shares:/usr/src/app/shares nethermindeth/research-mnemonic:CURRENT_VERSION main.py reconstruct\n```\n## Format of a share\n\n+ Our shares are stored in *json* files which are created in the same location with **create_shares.py**.  The shares include the following information:\n\n\t```Python\n\t{\n\t\"id\": i,\n\t\"share\": [\n\t\t\"word_1\",\n\t\t\"word_2\",\n\t\t\"word_3\",\n\t\t.\n\t\t.\n\t\t.\n\t\t\"word_nw\"\n\t]\n\t}\n\t```\n \n + If -v flag is used with **create_shares.py** then the share (*json*) files include additional public reconstruction data, e.i. irreducible polynomial and the dictionary. \n \n\t```Python\n\t{\n\t\"id\": i,\n\t\"share\": [\n\t\t\"word_1\",\n\t\t\"word_2\",\n\t\t\"word_3\"\n\t\t.\n\t\t.\n\t\t.\n\t\t\"word_nw\"\n\t],\n\t\"total_shares\": n,\n\t\"threshold\": t,\n\t\"primitive_poly\": \u003cpolynomial in string form\u003e,\n\t\"dictionary\": \u003cword list\u003e\n\t} \n\t```\n\t \n## Design rationale\n\n### Role of the digest\n+ The digest is encoded as a point in our scheme. It is the evaluation of the polynomial *f(x)* at *q-1*, e.i. *f(q-1)*. Using digest provides us an additional check before returning the reconstructed secret with probability *1/d*. \n+ On the other hand it decreases the entropy from *2\u003csup\u003em\u003c/sup\u003e* to *2\u003csup\u003em-d\u003c/sup\u003e* (for further information please see security analysis). \n\n### Number of words and Galois field\n+ Number of words *nw* and the number of bits *nb* determine the size of our Galois field. \n+ We have the primitive polynomials of degree up to 660. Therefore, for a dictionary of size 2048, e.i. *nb = 11*, our scheme supports up to 60 word secrets. \n\n### Security\n  + Although Shamir’s secret sharing scheme (SSS) is information theoretically secure, there is a known active adversary attack against it. Assume an adversary who interacts with *t-1* shareholders and perform share reconstruction with a faulty share. If she can do this again with another *t-1* shareholders (1 different shareholder suffices), she can construct the secret without knowing anything about the secret. In order to avoid such an attack we plan to take some security measures which force the active adversaries to behave passively. We are going to use a composition of authentication schemes and a ZK proofs for the reconstruction process.\n  + Another security issue for our modified scheme is the decreasing entropy because of the digest check that is used in the reconstruction phase. But ensuring *m-d \u003e 128* can defeat this low entropy weakness. \n  + Finally we have another issue for the security. Assume that an attacker has *k* shares such that *t \u003c k \u003c n*, and assume that *e* shares among *k* are faulty shares. In this case Lagrange interpolation does not work because of the faulty shares. But if *e \u003c t \u003c k/3* then the [*Berlekamp-Welch*](https://en.wikipedia.org/wiki/Berlekamp%E2%80%93Welch_algorithm) algorithm works and the adversary can reconstruct the secret without knowing the true shares.\n\n### References\n  1. [Shamir, A.: How to share a secret. Communications of the Association for Computing Machinery 22(11), 612_613 (Nov 1979)](https://web.mit.edu/6.857/OldStuff/Fall03/ref/Shamir-HowToShareASecret.pdf)\n\t\n  2. [BIP-39: Mnemonic code for generating deterministic keys](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)\n\t\n  3. [SLIP-0039: Shamir's Secret-Sharing for Mnemonic Codes](https://github.com/satoshilabs/slips/blob/master/slip-0039.md)\n\n### License\n[MIT License](https://github.com/NethermindEth/research-mnemonic/blob/main/LICENSE)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnethermindeth%2Fresearch-mnemonic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnethermindeth%2Fresearch-mnemonic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnethermindeth%2Fresearch-mnemonic/lists"}