Skip to content

Commit

Permalink
honest majority based shamir
Browse files Browse the repository at this point in the history
  • Loading branch information
zhdllwyc committed Aug 30, 2022
1 parent 8ee4e39 commit 8c296cf
Show file tree
Hide file tree
Showing 4 changed files with 816 additions and 0 deletions.
296 changes: 296 additions & 0 deletions tss/ecdsa/hstmaj/ecdsaLocalhm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
// Assumptions and Terminology
// 1. There are n parties: p_1...p_n
// 2. Every party has a label and receives a share of the secret key from the core.
// 3. Elliptic curve E(Z_p) of order q is defined as: y^2=x^3 + ax + b (mod p)
// where a, b in Z_p and Z_p is the underlying finite field for E.
// 4. We use Feldman TSS because every party needs to verify the msg from any other party.

package hstmaj

import (
"crypto/rand"
"errors"

"github.com/cloudflare/circl/secretsharing"

"github.com/cloudflare/circl/group"
)

// Local Sign functions

// During online round, the metals will construct their own signature share upon receiving the message
// Input: currParty, the local party
func (currParty *partySign) LocalGenSignatureShare() {
currParty.sharesig.Share.Mul(currParty.r, currParty.sharesk.Share)
currParty.sharesig.Share.Add(currParty.sharesig.Share, currParty.hashMSG)
currParty.sharesig.Share.Mul(currParty.sharesig.Share, currParty.sharekInv.Share)
}

// Initiate local party parameters for final round of signature generation
// Input: i, this party index
// Input: currParty, the local party
// Input: preSign, the same party with preSign informations
// Input: myGroup, the group we operate in
func (currParty *partySign) LocalInit(i uint, myGroup group.Group, preSign partyPreSign) {
currParty.myGroup = preSign.myGroup
currParty.index = i
currParty.sharekInv.ID = i
currParty.sharekInv.Share = preSign.sharekInv.Share.Copy()
currParty.r = myGroup.NewScalar()
currParty.r = preSign.r.Copy()
currParty.sharesk.ID = i
currParty.sharesk.Share = myGroup.NewScalar()
currParty.sharesk.Share.SetUint64(uint64(0))
currParty.sharesig.ID = i
currParty.sharesig.Share = myGroup.NewScalar()
currParty.sharesig.Share.SetUint64(uint64(0))
currParty.hashMSG = myGroup.NewScalar()
}

// Input: currParty, the local party
// Input: sssk, the share of secret key
func (currParty *partySign) Setss(sssk group.Scalar) {
currParty.sharesk.Share = sssk.Copy()
}

func (currParty *partySign) SetMSG(hashMSG group.Scalar) {
currParty.hashMSG = hashMSG.Copy()
}

// Local Pre computation functions

// Initiate local party parameters for preComputation
// Input: i, this party index
// Input: n, the number of parties
// Input: currParty, the local party
// Input: myGroup, the group we operate in
func (currParty *partyPreSign) LocalInit(i, n uint, myGroup group.Group) {
currParty.index = i
currParty.myGroup = myGroup
currParty.sharek.ID = i
currParty.sharek.Share = myGroup.NewScalar()
currParty.sharek.Share.SetUint64(uint64(0))
currParty.shareb.ID = i
currParty.shareb.Share = myGroup.NewScalar()
currParty.shareb.Share.SetUint64(uint64(0))
currParty.sharekb.ID = i
currParty.sharekb.Share = myGroup.NewScalar()
currParty.sharekb.Share.SetUint64(uint64(0))
currParty.sharekInv.ID = i
currParty.sharekInv.Share = myGroup.NewScalar()
currParty.sharekInv.Share.SetUint64(uint64(0))
currParty.sharekG = myGroup.NewElement()
currParty.obfCoefks = make([][]group.Element, n)
currParty.obfCoefbs = make([][]group.Element, n)
}

// Generate the local party information for nonce k and blinding b,
// later will be used in Feldman secret sharing to construct shares of the nonce k and k^{-1}
// Input: t, the threshold parameter
// Input: n, the number of parties
// Input: currParty, the local party
func (currParty *partyPreSign) LocalGenkb(t, n uint) {

// first coefficient of secret polynomial k_i for this party i
currParty.polyki = currParty.myGroup.RandomNonZeroScalar(rand.Reader)
vs, err := secretsharing.NewVerifiable(currParty.myGroup, t, n)
if err != nil {
panic(err)
}
currParty.sski, currParty.obfCoefki = vs.Shard(rand.Reader, currParty.polyki)

// secret polynomial b_i for this party i
currParty.polybi = currParty.myGroup.RandomNonZeroScalar(rand.Reader)
vs, err = secretsharing.NewVerifiable(currParty.myGroup, t, n)
if err != nil {
panic(err)
}
// the shares of polynomial b_i for every single party in the game and the obfuscated coefficient for proving correctness
currParty.ssbi, currParty.obfCoefbi = vs.Shard(rand.Reader, currParty.polybi)

currParty.sharek = currParty.sski[currParty.index-1]
currParty.shareb = currParty.ssbi[currParty.index-1]
}

// Update local shares of k and b
// Input: t, the threshold parameter
// Input: n, the number of parties
// Input: sharekUpdate, update for nonce k share from other party
// Input: sharebUpdate, update for blinding b share from other party
// Input: obfCoefk, the obfuscated coefficient (commitment) as for proving correctness of sharekUpdate
// Input: obfCoefb, the obfuscated coefficient (commitment) as for proving correctness of sharebUpdate
// Input: currParty, the local party
// Input: fromIndex, the index of the party who sends this update
// Output: fromIndex if Feldman check fails, otherwise 0
func (currParty *partyPreSign) LocalUpdatekb(t, n uint, sharekUpdate, sharebUpdate secretsharing.Share, obfCoefk, obfCoefb []group.Element, fromIndex uint) uint {
currParty.sharek.Share.Add(currParty.sharek.Share, sharekUpdate.Share)
vs, err := secretsharing.NewVerifiable(currParty.myGroup, t, n)
if err != nil {
panic(err)
}
check := vs.Verify(sharekUpdate, obfCoefk)
if !check {
return fromIndex
}

currParty.shareb.Share.Add(currParty.shareb.Share, sharebUpdate.Share)
vs, err = secretsharing.NewVerifiable(currParty.myGroup, t, n)
if err != nil {
panic(err)
}
check = vs.Verify(sharebUpdate, obfCoefb)
if !check {
return fromIndex
}

return 0
}

// Compute shares for k*b as sharek*shareb
// Input: currParty, the local party
func (currParty *partyPreSign) LocalSharekb() {
currParty.sharekb.Share.Mul(currParty.sharek.Share, currParty.shareb.Share)
}

// Compute [sharek]G
// Input: currParty, the local party
func (currParty *partyPreSign) LocalkG() {
currParty.sharekG.MulGen(currParty.sharek.Share)
}

// Local party as a combiner collects shares for kb and computes kb^{-1}
// Input: t, the threshold parameter
// Input: n, the number of parties
// Input: currParty, the local party
// Input: shareskb, the shares for kb from other parties
// Output: kb^{-1} and possible error
func (currParty *partyPreSign) CombinerCompkbInv(t, n uint, shareskb []secretsharing.Share) (group.Scalar, error) {
s, err := secretsharing.New(currParty.myGroup, t, n)
if err != nil {
panic(err)
}
kb, err := s.Recover(shareskb)
kbInv := currParty.myGroup.NewScalar()
kbInv.Inv(kb)
return kbInv, err
}

// Local party as a combiner collects shares for [sharek]G and computes [k]G
// Input: t, the threshold parameter
// Input: n, the number of parties
// Input: currParty, the local party
// Input: shareskG, the shares for [k]G from other parties
// Input: indexes, the indexes for all other parties
// Output: x coordinate of [k]G and possible error
func (currParty *partyPreSign) CombinerCompkG(t, n uint, shareskG []group.Element, indexes []group.Scalar) (group.Scalar, error) {
resultkG, errkG := lagrangeInterpolatePoint(t, currParty.myGroup, shareskG, indexes)
if errkG != nil {
return nil, errkG
}

kGBinary, errBinary := resultkG.MarshalBinary()
if errBinary != nil {
panic(errBinary)
}

xCoor := kGBinary[1 : currParty.myGroup.Params().ScalarLength+1]
xScalar := currParty.myGroup.NewScalar()
errBinary = xScalar.UnmarshalBinary(xCoor)
if errBinary != nil {
panic(errBinary)
}
return xScalar, nil
}

// Set the x coordinate of [k]G as r
// Input: currParty, the local party
// Input: xCoor, the x coordinate of [k]G
func (currParty *partyPreSign) Setr(xCoor group.Scalar) {
currParty.r = xCoor.Copy()
}

// Compute share of k^{-1} as (kb)^{-1}*shareb
// Input: currParty, the local party
// Input: kbInv, the (kb)^{-1}
func (currParty *partyPreSign) LocalSharekInv(kbInv group.Scalar) {
currParty.kbInv = kbInv.Copy()
currParty.sharekInv.Share.Mul(currParty.kbInv, currParty.shareb.Share)
}

// Helper functions

// Check everyone receives the same coefficient for Feldman
// Input: t, the threshold parameter
// Input: obfCoefj, the obfuscated coefficient for f_i send to party j
// Input: obfCoefk, the obfuscated coefficient for f_i send to party k
// Ouput: true if obfCoefj == obfCoefk, false otherwise.
func checkObf(t uint, obfCoefj []group.Element, obfCoefk []group.Element) bool {
check := true
for i := uint(0); i < t+1; i++ {
if !(obfCoefj[i].IsEqual(obfCoefk[i])) {
check = false
}
}
return check
}

// Lagrange Interpolation of y as element but not scalar

// Input: myGroup, the group we operate in
// Input: targetIndex, the i
// Input: currShare, the [y_i]G
// Input: indexes, the indexes for each party
// Output: Compute a single [f_i(0)]G
func lagrangeSinglePoint(myGroup group.Group, targetIndex int, currShare group.Element, indexes []group.Scalar) group.Element {
// f_i(0) = y_i[G]
result := currShare.Copy()

// x_i
targetLabel := (indexes)[targetIndex].Copy()

interValue := myGroup.NewScalar()
invValue := myGroup.NewScalar()

for k := 0; k < len(indexes); k++ {
//f_i(0) = f_i(0) * (0-x_k)/(x_i-x_k)
if k != targetIndex {
// x_k
currLabel := (indexes)[k].Copy()

// f_i(0) * (0-x_k)
interValue.SetUint64(uint64(0))
interValue.Sub(interValue, currLabel)
result.Mul(result, interValue)

// (x_i-x_k)
invValue.Sub(targetLabel, currLabel)
invValue.Inv(invValue)
result.Mul(result, invValue)

}
}
return result
}

// Input: t, the threshold, we need at least t+1 points for Lagrange Interpolation
// Input: myGroup, the group we operate in
// Input: ss, the secret shares multiplied by generator G
// Input: indexes, the indexes for each party
// Ouput: the re-constructed secret [f(0)]G
func lagrangeInterpolatePoint(t uint, myGroup group.Group, ss []group.Element, indexes []group.Scalar) (group.Element, error) {
if uint(len(ss)) < t+1 {
return nil, errors.New("need at least t+1 points to do Lagrange Interpolation")
}

secret := myGroup.NewElement()
for i := 0; i < len(ss); i++ {
fi := lagrangeSinglePoint(myGroup, i, ss[i], indexes)
if i == 0 {
secret.Set(fi)
} else {
secret.Add(secret, fi)
}
}

return secret, nil
}
Loading

0 comments on commit 8c296cf

Please sign in to comment.