Elliptic SSS scheme implementation in Node.js.
algorithm features
- use secp256k1 to restore secret
- each share can be signed with the corresponding private key
The ESSS scheme is an extended version of SSS (Shamir Shared Secret) scheme, which use elliptic curve properties for making sure, that only certain private key owners are able to restore the secret.
The original algorithm is based on polynomial interpolation, where we have to find (x0, y0). The x0 = 0
, and y0 = secret
.
In ESSS scheme, each peer should have its own private and public keys. The workflow looks like so:
- during split phase, the peer should provide all involved public keys with restoration factor (m, in m-of-n)
- the result of the split is an [xCoef, y] for each peer (each will have its own pair).
- each peer should receive its own [xCoef, y]
- To restore the secret, m of n peers should sign the xCoef with their private key
- the next step is to exchange with [signature, y].
- the last step is to restore the secret from m shares
During the split phase, algorithm generates a random xCoef for each provided public key. The xCoef should belong to prime: xCoef <= prime
.
Then the algorithm calculates the x
coordinate: xCoef * publicKey[i]
, where publicKey[i]
- is an i
public key of provided public keys array.
M-of-n peers should sign the xCoef
: signature = xCoef * privateKey
.
During the restoration phase, the algorithm calculates the initial x
coordinate as: x = signature * G
.
By knowing m-of-n shares, the algorithm restores initial secret through interpolation.
The proof: xCoef * publicKey = xCoef * privateKey * G = signature * G
$ npm install esss --save
$ npm run build
Arguments:
secret
- the source secret, which should be split. Make sure, that secret doesn't start from0
- otherwise it will be wiped during restoration.needed
- how many keys required for restoration (m, m-of-n)publicKeys
- all involved public keys
Return: Array<[string, string]>
, where each element of array is [xCoef, y], which should be distributed to the certain peer.
The publicKey index is the same as index of [xCoef, y] (so it returns in the same order as publicKeys were provided).
Arguments:
share
- the y coordinate (which is also known as share)privateKey
- peer's private key
Return: signature, which is string
.
An optional step to validate the signature of the certain peer
Arguments:
xCoef
- the peer'sxCoef
publicKey
- peer's public keysignature
- peer's signature for providedxCoef
Return: boolean
. If signature valid returns true
otherwise - false
Arguments:
Array<[string, string]>
- array of [signature, share]
Return: string
. Should return the secret
Should generate the safe keypair. The safe means that private key doesn't start with 0
.
It's important since algorithm works with bigNumbers and this 0 can be wiped during convertation process.
Return: { privateKey: string, publicKey: string }
- should return the keyPair.
import esss from 'esss'
const keyPair1 = esss.utils.generateSafeKeyPair();
const keyPair2 = esss.utils.generateSafeKeyPair();
const keyPair3 = esss.utils.generateSafeKeyPair();
const secret = '2e2ce090ee475752b19e79501897d3f3cb92d687f8c028df092a18e7838edac3';
const m = 2;
const [share1, share2, share3] = esss.split(secret, m, [keyPair1.publicKey, keyPair2.publicKey, keyPair3.publicKey]);
const signature1 = esss.sign(share1[0], keyPair1.privateKey);
const reply1: [string, string] = [signature1, share1[1]];
const signature3 = esss.sign(share3[0], keyPair3.privateKey);
const reply3: [string, string] = [signature3, share3[1]];
const joined = esss.join([reply1, reply3]);
console.log(`are equal: ${secret === joined}`); //are equal: true
Please check out test files for an advanced example.
$ npm run test
Copyright (c) 2020-2021 Egor Zuev