1 package rsa
2
3 import (
4 "crypto/rand"
5 "crypto/rsa"
6 "encoding/binary"
7 "errors"
8 "fmt"
9 "io"
10 "math"
11 "math/big"
12 "sync"
13 )
14
15
16 type KeyShare struct {
17 si *big.Int
18
19 twoDeltaSi *big.Int
20 Index uint
21
22 Players uint
23 Threshold uint
24 }
25
26 func (kshare KeyShare) String() string {
27 return fmt.Sprintf("(t,n): (%v,%v) index: %v si: 0x%v",
28 kshare.Threshold, kshare.Players, kshare.Index, kshare.si.Text(16))
29 }
30
31
32
33 func (kshare *KeyShare) MarshalBinary() ([]byte, error) {
34
35
36
37
38 if kshare.Players > math.MaxUint16 {
39 return nil, fmt.Errorf("rsa_threshold: keyshare marshall: Players is too big to fit in a uint16")
40 }
41
42 if kshare.Threshold > math.MaxUint16 {
43 return nil, fmt.Errorf("rsa_threshold: keyshare marshall: Threshold is too big to fit in a uint16")
44 }
45
46 if kshare.Index > math.MaxUint16 {
47 return nil, fmt.Errorf("rsa_threshold: keyshare marshall: Index is too big to fit in a uint16")
48 }
49
50 players := uint16(kshare.Players)
51 threshold := uint16(kshare.Threshold)
52 index := uint16(kshare.Index)
53
54 twoDeltaSiBytes := []byte(nil)
55 if kshare.twoDeltaSi != nil {
56 twoDeltaSiBytes = kshare.twoDeltaSi.Bytes()
57 }
58
59 twoDeltaSiLen := len(twoDeltaSiBytes)
60
61 if twoDeltaSiLen > math.MaxInt16 {
62 return nil, fmt.Errorf("rsa_threshold: keyshare marshall: twoDeltaSiBytes is too big to fit it's length in a uint16")
63 }
64
65 siBytes := kshare.si.Bytes()
66
67 siLength := len(siBytes)
68
69 if siLength == 0 {
70 siLength = 1
71 siBytes = []byte{0}
72 }
73
74 if siLength > math.MaxInt16 {
75 return nil, fmt.Errorf("rsa_threshold: keyshare marshall: siBytes is too big to fit it's length in a uint16")
76 }
77
78 blen := 2 + 2 + 2 + 2 + 2 + 1 + siLength + twoDeltaSiLen
79 out := make([]byte, blen)
80
81 binary.BigEndian.PutUint16(out[0:2], players)
82 binary.BigEndian.PutUint16(out[2:4], threshold)
83 binary.BigEndian.PutUint16(out[4:6], index)
84
85 binary.BigEndian.PutUint16(out[6:8], uint16(siLength))
86
87 copy(out[8:8+siLength], siBytes)
88
89 if twoDeltaSiBytes != nil {
90 out[8+siLength] = 1
91 }
92
93 binary.BigEndian.PutUint16(out[8+siLength+1:8+siLength+3], uint16(twoDeltaSiLen))
94
95 if twoDeltaSiBytes != nil {
96 copy(out[8+siLength+3:8+siLength+3+twoDeltaSiLen], twoDeltaSiBytes)
97 }
98
99 return out, nil
100 }
101
102
103 func (kshare *KeyShare) UnmarshalBinary(data []byte) error {
104
105
106
107 if len(data) < 6 {
108 return fmt.Errorf("rsa_threshold: keyshare unmarshalKeyShareTest failed: data length was too short for reading Players, Threshold, Index")
109 }
110
111 players := binary.BigEndian.Uint16(data[0:2])
112 threshold := binary.BigEndian.Uint16(data[2:4])
113 index := binary.BigEndian.Uint16(data[4:6])
114
115 if len(data[6:]) < 2 {
116 return fmt.Errorf("rsa_threshold: keyshare unmarshalKeyShareTest failed: data length was too short for reading siLen length")
117 }
118
119 siLen := binary.BigEndian.Uint16(data[6:8])
120
121 if siLen == 0 {
122 return fmt.Errorf("rsa_threshold: keyshare unmarshalKeyShareTest failed: si is a required field but siLen was 0")
123 }
124
125 if uint16(len(data[8:])) < siLen {
126 return fmt.Errorf("rsa_threshold: keyshare unmarshalKeyShareTest failed: data length was too short for reading si, needed: %d found: %d", siLen, len(data[8:]))
127 }
128
129 si := new(big.Int).SetBytes(data[8 : 8+siLen])
130
131 if len(data[8+siLen:]) < 1 {
132 return fmt.Errorf("rsa_threshold: keyshare unmarshalKeyShareTest failed: data length was too short for reading twoDeltaSiNil")
133 }
134
135 isNil := data[8+siLen]
136
137 var twoDeltaSi *big.Int
138
139 if isNil != 0 {
140 if len(data[8+siLen+1:]) < 2 {
141 return fmt.Errorf("rsa_threshold: keyshare unmarshalKeyShareTest failed: data length was too short for reading twoDeltaSiLen length")
142 }
143
144 twoDeltaSiLen := binary.BigEndian.Uint16(data[8+siLen+1 : 8+siLen+3])
145
146 if uint16(len(data[8+siLen+3:])) < twoDeltaSiLen {
147 return fmt.Errorf("rsa_threshold: keyshare unmarshalKeyShareTest failed: data length was too short for reading twoDeltaSi, needed: %d found: %d", twoDeltaSiLen, len(data[8+siLen+2:]))
148 }
149
150 twoDeltaSi = new(big.Int).SetBytes(data[8+siLen+3 : 8+siLen+3+twoDeltaSiLen])
151 }
152
153 kshare.Players = uint(players)
154 kshare.Threshold = uint(threshold)
155 kshare.Index = uint(index)
156 kshare.si = si
157 kshare.twoDeltaSi = twoDeltaSi
158
159 return nil
160 }
161
162
163 func (kshare *KeyShare) get2DeltaSi(players int64) *big.Int {
164
165 if kshare.twoDeltaSi != nil {
166 return kshare.twoDeltaSi
167 }
168 delta := calculateDelta(players)
169
170
171 delta.Lsh(delta, 1).Mul(delta, kshare.si)
172 kshare.twoDeltaSi = delta
173 return delta
174 }
175
176
177
178
179
180
181
182
183
184 func (kshare *KeyShare) Sign(randSource io.Reader, pub *rsa.PublicKey, digest []byte, parallel bool) (SignShare, error) {
185 x := &big.Int{}
186 x.SetBytes(digest)
187
188 exp := kshare.get2DeltaSi(int64(kshare.Players))
189
190 var signShare SignShare
191 signShare.Players = kshare.Players
192 signShare.Threshold = kshare.Threshold
193 signShare.Index = kshare.Index
194
195 signShare.xi = &big.Int{}
196
197 if randSource != nil {
198
199
200
201
202
203
204
205 r, err := rand.Int(randSource, pub.N)
206 if err != nil {
207 return SignShare{}, errors.New("rsa_threshold: unable to get random value for blinding")
208 }
209 expPlusr := big.Int{}
210
211 expPlusr.Add(exp, r)
212
213 var wg *sync.WaitGroup
214
215
216 if parallel {
217 wg = &sync.WaitGroup{}
218 wg.Add(1)
219 go func() {
220 signShare.xi.Exp(x, &expPlusr, pub.N)
221 wg.Done()
222 }()
223 } else {
224 signShare.xi.Exp(x, &expPlusr, pub.N)
225 }
226
227 xExpr := big.Int{}
228
229 xExpr.Exp(x, r, pub.N)
230
231 res := xExpr.ModInverse(&xExpr, pub.N)
232
233 if res == nil {
234
235 return SignShare{}, errors.New("rsa_threshold: no mod inverse")
236 }
237
238 if wg != nil {
239 wg.Wait()
240 }
241
242
243 signShare.xi.Mul(signShare.xi, &xExpr)
244 signShare.xi.Mod(signShare.xi, pub.N)
245 } else {
246
247 signShare.xi = &big.Int{}
248 signShare.xi.Exp(x, exp, pub.N)
249 }
250
251 return signShare, nil
252 }
253
View as plain text