dfinity-side-projects / js-bls-lib

This libary provides primitives for creating and verifying BLS threshold signatures.
Mozilla Public License 2.0
42 stars 22 forks source link

what is a share? #1

Closed dominictarr closed 6 years ago

dominictarr commented 6 years ago

The current documentation gives a low level description of the signatures of the various methods, but I need a high level explaination of how shares are combined and what the properties are, The library this is based on https://github.com/herumi/bls also isn't any better and neither link to material that explains it. Do you know of a good place to learn more?

wanderer commented 6 years ago

Currently I'm stuck on distributed key generation, so I don't think I can give a very satisfying answer yet. But after DKG we should have a 1) a group with a size of group_size and a 2) threshold of size threshold_size 3) master public key for the group and each participant has an ID (just a int) and a corresponding public and private key (that is tied to its ID).

So to recap we have something like

{
  groupPublicKey: <pub_key>
  groupMembers [
    [<id>, <pub_key>, <secret_key>], // pub_key & secret_key generated from DKG
    [<id>, <pub_key>, <secret_key>], 
    ...
   ]
}

Now the group members can create a signature share with the following.

const msg = 'hello mars!'
const sig = bls.signature()
bls.sign(sig, secret_key, msg)
const sigShare = bls.serailizeSignature(sig) // produces an int8Array containing 32-bytes

Its called a "share" because once we have threshold_size signatures from unique group members on the same message we can recombine them and validate the message with groupPublicKey.


const shares = [[<id>, <sig>]] //  an array of the lenght threshold_size with signatures from group members produced by the above code and there corresponding id

const sigs = signatureShares.map(share => {
  const sig = bls.signature() 
  bls.signatureDeserialize(sig, share[1])
  return sig
})
const ids = signatureShares.map(share => share[0])
const sig = bls.signature()
bls.signatureRecover(sig, sigs, ids)

const valid = bls.verify(sig, groupPublicKey, 'hello mars!') // should be 1

DKG

Now I don't have all the pieces for DKG but if you don't mind a trusted party setting up the group use can do the following

     // `ids` are an array of ints. And threshold is an Int that is less then ids.length
      function createGroup (ids, threshold) {
        const secretKey = [] //master sk
        const publicKey = [] // master pk
        const group = {
          ids: {}
        }
        // generate the master sk and pk
        for (let i = 0; i < threshold; i++) {
          const sk = bls.secretKey()
          bls.secretKeySetByCSPRNG(sk)
          secretKey.push(sk)

          const pk = bls.publicKey()
          bls.getPublicKey(pk, sk)

          publicKey.push(pk)
        }
        // generate the pk and sk for the group members
        for (let i = 0; i < ids.length; i++) {
          const index = ids[i].index
          const id = bls.secretKey()
          bls.idSetInt(id, index)

          const sk = bls.secretKey()
          bls.secretKeyShare(sk, secretKey, id)

          const pk = bls.publicKey()
          bls.publicKeyShare(pk, publicKey, id)

          group.ids[index] = {
            secretKey: Buffer.from(bls.secretKeySerialize(sk)).toString('hex'),
            publicKey: Buffer.from(bls.publicKeySerialize(pk)).toString('hex')
          }
        }

        group.publicKey = Buffer.from(bls.publicKeySerialize(publicKey[0])).toString('hex')
        return group
      }
wanderer commented 6 years ago

moving to here https://github.com/wanderer/dkg