Skip to content

Commit 8c296cf

Browse files
author
zhdllwyc
committed
honest majority based shamir
1 parent 8ee4e39 commit 8c296cf

File tree

4 files changed

+816
-0
lines changed

4 files changed

+816
-0
lines changed

tss/ecdsa/hstmaj/ecdsaLocalhm.go

+296
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
// Assumptions and Terminology
2+
// 1. There are n parties: p_1...p_n
3+
// 2. Every party has a label and receives a share of the secret key from the core.
4+
// 3. Elliptic curve E(Z_p) of order q is defined as: y^2=x^3 + ax + b (mod p)
5+
// where a, b in Z_p and Z_p is the underlying finite field for E.
6+
// 4. We use Feldman TSS because every party needs to verify the msg from any other party.
7+
8+
package hstmaj
9+
10+
import (
11+
"crypto/rand"
12+
"errors"
13+
14+
"github.com/cloudflare/circl/secretsharing"
15+
16+
"github.com/cloudflare/circl/group"
17+
)
18+
19+
// Local Sign functions
20+
21+
// During online round, the metals will construct their own signature share upon receiving the message
22+
// Input: currParty, the local party
23+
func (currParty *partySign) LocalGenSignatureShare() {
24+
currParty.sharesig.Share.Mul(currParty.r, currParty.sharesk.Share)
25+
currParty.sharesig.Share.Add(currParty.sharesig.Share, currParty.hashMSG)
26+
currParty.sharesig.Share.Mul(currParty.sharesig.Share, currParty.sharekInv.Share)
27+
}
28+
29+
// Initiate local party parameters for final round of signature generation
30+
// Input: i, this party index
31+
// Input: currParty, the local party
32+
// Input: preSign, the same party with preSign informations
33+
// Input: myGroup, the group we operate in
34+
func (currParty *partySign) LocalInit(i uint, myGroup group.Group, preSign partyPreSign) {
35+
currParty.myGroup = preSign.myGroup
36+
currParty.index = i
37+
currParty.sharekInv.ID = i
38+
currParty.sharekInv.Share = preSign.sharekInv.Share.Copy()
39+
currParty.r = myGroup.NewScalar()
40+
currParty.r = preSign.r.Copy()
41+
currParty.sharesk.ID = i
42+
currParty.sharesk.Share = myGroup.NewScalar()
43+
currParty.sharesk.Share.SetUint64(uint64(0))
44+
currParty.sharesig.ID = i
45+
currParty.sharesig.Share = myGroup.NewScalar()
46+
currParty.sharesig.Share.SetUint64(uint64(0))
47+
currParty.hashMSG = myGroup.NewScalar()
48+
}
49+
50+
// Input: currParty, the local party
51+
// Input: sssk, the share of secret key
52+
func (currParty *partySign) Setss(sssk group.Scalar) {
53+
currParty.sharesk.Share = sssk.Copy()
54+
}
55+
56+
func (currParty *partySign) SetMSG(hashMSG group.Scalar) {
57+
currParty.hashMSG = hashMSG.Copy()
58+
}
59+
60+
// Local Pre computation functions
61+
62+
// Initiate local party parameters for preComputation
63+
// Input: i, this party index
64+
// Input: n, the number of parties
65+
// Input: currParty, the local party
66+
// Input: myGroup, the group we operate in
67+
func (currParty *partyPreSign) LocalInit(i, n uint, myGroup group.Group) {
68+
currParty.index = i
69+
currParty.myGroup = myGroup
70+
currParty.sharek.ID = i
71+
currParty.sharek.Share = myGroup.NewScalar()
72+
currParty.sharek.Share.SetUint64(uint64(0))
73+
currParty.shareb.ID = i
74+
currParty.shareb.Share = myGroup.NewScalar()
75+
currParty.shareb.Share.SetUint64(uint64(0))
76+
currParty.sharekb.ID = i
77+
currParty.sharekb.Share = myGroup.NewScalar()
78+
currParty.sharekb.Share.SetUint64(uint64(0))
79+
currParty.sharekInv.ID = i
80+
currParty.sharekInv.Share = myGroup.NewScalar()
81+
currParty.sharekInv.Share.SetUint64(uint64(0))
82+
currParty.sharekG = myGroup.NewElement()
83+
currParty.obfCoefks = make([][]group.Element, n)
84+
currParty.obfCoefbs = make([][]group.Element, n)
85+
}
86+
87+
// Generate the local party information for nonce k and blinding b,
88+
// later will be used in Feldman secret sharing to construct shares of the nonce k and k^{-1}
89+
// Input: t, the threshold parameter
90+
// Input: n, the number of parties
91+
// Input: currParty, the local party
92+
func (currParty *partyPreSign) LocalGenkb(t, n uint) {
93+
94+
// first coefficient of secret polynomial k_i for this party i
95+
currParty.polyki = currParty.myGroup.RandomNonZeroScalar(rand.Reader)
96+
vs, err := secretsharing.NewVerifiable(currParty.myGroup, t, n)
97+
if err != nil {
98+
panic(err)
99+
}
100+
currParty.sski, currParty.obfCoefki = vs.Shard(rand.Reader, currParty.polyki)
101+
102+
// secret polynomial b_i for this party i
103+
currParty.polybi = currParty.myGroup.RandomNonZeroScalar(rand.Reader)
104+
vs, err = secretsharing.NewVerifiable(currParty.myGroup, t, n)
105+
if err != nil {
106+
panic(err)
107+
}
108+
// the shares of polynomial b_i for every single party in the game and the obfuscated coefficient for proving correctness
109+
currParty.ssbi, currParty.obfCoefbi = vs.Shard(rand.Reader, currParty.polybi)
110+
111+
currParty.sharek = currParty.sski[currParty.index-1]
112+
currParty.shareb = currParty.ssbi[currParty.index-1]
113+
}
114+
115+
// Update local shares of k and b
116+
// Input: t, the threshold parameter
117+
// Input: n, the number of parties
118+
// Input: sharekUpdate, update for nonce k share from other party
119+
// Input: sharebUpdate, update for blinding b share from other party
120+
// Input: obfCoefk, the obfuscated coefficient (commitment) as for proving correctness of sharekUpdate
121+
// Input: obfCoefb, the obfuscated coefficient (commitment) as for proving correctness of sharebUpdate
122+
// Input: currParty, the local party
123+
// Input: fromIndex, the index of the party who sends this update
124+
// Output: fromIndex if Feldman check fails, otherwise 0
125+
func (currParty *partyPreSign) LocalUpdatekb(t, n uint, sharekUpdate, sharebUpdate secretsharing.Share, obfCoefk, obfCoefb []group.Element, fromIndex uint) uint {
126+
currParty.sharek.Share.Add(currParty.sharek.Share, sharekUpdate.Share)
127+
vs, err := secretsharing.NewVerifiable(currParty.myGroup, t, n)
128+
if err != nil {
129+
panic(err)
130+
}
131+
check := vs.Verify(sharekUpdate, obfCoefk)
132+
if !check {
133+
return fromIndex
134+
}
135+
136+
currParty.shareb.Share.Add(currParty.shareb.Share, sharebUpdate.Share)
137+
vs, err = secretsharing.NewVerifiable(currParty.myGroup, t, n)
138+
if err != nil {
139+
panic(err)
140+
}
141+
check = vs.Verify(sharebUpdate, obfCoefb)
142+
if !check {
143+
return fromIndex
144+
}
145+
146+
return 0
147+
}
148+
149+
// Compute shares for k*b as sharek*shareb
150+
// Input: currParty, the local party
151+
func (currParty *partyPreSign) LocalSharekb() {
152+
currParty.sharekb.Share.Mul(currParty.sharek.Share, currParty.shareb.Share)
153+
}
154+
155+
// Compute [sharek]G
156+
// Input: currParty, the local party
157+
func (currParty *partyPreSign) LocalkG() {
158+
currParty.sharekG.MulGen(currParty.sharek.Share)
159+
}
160+
161+
// Local party as a combiner collects shares for kb and computes kb^{-1}
162+
// Input: t, the threshold parameter
163+
// Input: n, the number of parties
164+
// Input: currParty, the local party
165+
// Input: shareskb, the shares for kb from other parties
166+
// Output: kb^{-1} and possible error
167+
func (currParty *partyPreSign) CombinerCompkbInv(t, n uint, shareskb []secretsharing.Share) (group.Scalar, error) {
168+
s, err := secretsharing.New(currParty.myGroup, t, n)
169+
if err != nil {
170+
panic(err)
171+
}
172+
kb, err := s.Recover(shareskb)
173+
kbInv := currParty.myGroup.NewScalar()
174+
kbInv.Inv(kb)
175+
return kbInv, err
176+
}
177+
178+
// Local party as a combiner collects shares for [sharek]G and computes [k]G
179+
// Input: t, the threshold parameter
180+
// Input: n, the number of parties
181+
// Input: currParty, the local party
182+
// Input: shareskG, the shares for [k]G from other parties
183+
// Input: indexes, the indexes for all other parties
184+
// Output: x coordinate of [k]G and possible error
185+
func (currParty *partyPreSign) CombinerCompkG(t, n uint, shareskG []group.Element, indexes []group.Scalar) (group.Scalar, error) {
186+
resultkG, errkG := lagrangeInterpolatePoint(t, currParty.myGroup, shareskG, indexes)
187+
if errkG != nil {
188+
return nil, errkG
189+
}
190+
191+
kGBinary, errBinary := resultkG.MarshalBinary()
192+
if errBinary != nil {
193+
panic(errBinary)
194+
}
195+
196+
xCoor := kGBinary[1 : currParty.myGroup.Params().ScalarLength+1]
197+
xScalar := currParty.myGroup.NewScalar()
198+
errBinary = xScalar.UnmarshalBinary(xCoor)
199+
if errBinary != nil {
200+
panic(errBinary)
201+
}
202+
return xScalar, nil
203+
}
204+
205+
// Set the x coordinate of [k]G as r
206+
// Input: currParty, the local party
207+
// Input: xCoor, the x coordinate of [k]G
208+
func (currParty *partyPreSign) Setr(xCoor group.Scalar) {
209+
currParty.r = xCoor.Copy()
210+
}
211+
212+
// Compute share of k^{-1} as (kb)^{-1}*shareb
213+
// Input: currParty, the local party
214+
// Input: kbInv, the (kb)^{-1}
215+
func (currParty *partyPreSign) LocalSharekInv(kbInv group.Scalar) {
216+
currParty.kbInv = kbInv.Copy()
217+
currParty.sharekInv.Share.Mul(currParty.kbInv, currParty.shareb.Share)
218+
}
219+
220+
// Helper functions
221+
222+
// Check everyone receives the same coefficient for Feldman
223+
// Input: t, the threshold parameter
224+
// Input: obfCoefj, the obfuscated coefficient for f_i send to party j
225+
// Input: obfCoefk, the obfuscated coefficient for f_i send to party k
226+
// Ouput: true if obfCoefj == obfCoefk, false otherwise.
227+
func checkObf(t uint, obfCoefj []group.Element, obfCoefk []group.Element) bool {
228+
check := true
229+
for i := uint(0); i < t+1; i++ {
230+
if !(obfCoefj[i].IsEqual(obfCoefk[i])) {
231+
check = false
232+
}
233+
}
234+
return check
235+
}
236+
237+
// Lagrange Interpolation of y as element but not scalar
238+
239+
// Input: myGroup, the group we operate in
240+
// Input: targetIndex, the i
241+
// Input: currShare, the [y_i]G
242+
// Input: indexes, the indexes for each party
243+
// Output: Compute a single [f_i(0)]G
244+
func lagrangeSinglePoint(myGroup group.Group, targetIndex int, currShare group.Element, indexes []group.Scalar) group.Element {
245+
// f_i(0) = y_i[G]
246+
result := currShare.Copy()
247+
248+
// x_i
249+
targetLabel := (indexes)[targetIndex].Copy()
250+
251+
interValue := myGroup.NewScalar()
252+
invValue := myGroup.NewScalar()
253+
254+
for k := 0; k < len(indexes); k++ {
255+
//f_i(0) = f_i(0) * (0-x_k)/(x_i-x_k)
256+
if k != targetIndex {
257+
// x_k
258+
currLabel := (indexes)[k].Copy()
259+
260+
// f_i(0) * (0-x_k)
261+
interValue.SetUint64(uint64(0))
262+
interValue.Sub(interValue, currLabel)
263+
result.Mul(result, interValue)
264+
265+
// (x_i-x_k)
266+
invValue.Sub(targetLabel, currLabel)
267+
invValue.Inv(invValue)
268+
result.Mul(result, invValue)
269+
270+
}
271+
}
272+
return result
273+
}
274+
275+
// Input: t, the threshold, we need at least t+1 points for Lagrange Interpolation
276+
// Input: myGroup, the group we operate in
277+
// Input: ss, the secret shares multiplied by generator G
278+
// Input: indexes, the indexes for each party
279+
// Ouput: the re-constructed secret [f(0)]G
280+
func lagrangeInterpolatePoint(t uint, myGroup group.Group, ss []group.Element, indexes []group.Scalar) (group.Element, error) {
281+
if uint(len(ss)) < t+1 {
282+
return nil, errors.New("need at least t+1 points to do Lagrange Interpolation")
283+
}
284+
285+
secret := myGroup.NewElement()
286+
for i := 0; i < len(ss); i++ {
287+
fi := lagrangeSinglePoint(myGroup, i, ss[i], indexes)
288+
if i == 0 {
289+
secret.Set(fi)
290+
} else {
291+
secret.Add(secret, fi)
292+
}
293+
}
294+
295+
return secret, nil
296+
}

0 commit comments

Comments
 (0)