forked from winderica/kryptology
-
Notifications
You must be signed in to change notification settings - Fork 0
/
round2.go
130 lines (111 loc) · 3.6 KB
/
round2.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//
// Copyright Coinbase, Inc. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
package participant
import (
"encoding/json"
"math/big"
"github.com/coinbase/kryptology/pkg/core"
"github.com/coinbase/kryptology/pkg/paillier"
"github.com/coinbase/kryptology/pkg/tecdsa/gg20/proof"
)
// P2PSend is all the values that need to be sent to each player
type P2PSend struct {
Proof2, Proof3 proof.ResponseFinalizer
}
// UnmarshalJSON explicitly unmarshals into ResponseProofs instead of ResponsFinalizer interface
func (p2ps *P2PSend) UnmarshalJSON(bytes []byte) error {
// Temporary struct used to explicitly unmarshal into ResponseProofs instead of ResponseFinalizer
data := struct {
Proof2, Proof3 proof.ResponseProof
}{}
err := json.Unmarshal(bytes, &data)
if err != nil {
return err
}
p2ps.Proof2 = data.Proof2
p2ps.Proof3 = data.Proof3
return nil
}
// SignRound2 performs round 2 signing operations for a single signer
// Trusted Dealer Mode: see [spec] fig 7: SignRound2
// DKG Mode: see [spec] fig 8: SignRound2
func (signer *Signer) SignRound2(params map[uint32]*Round1Bcast, p2p map[uint32]*Round1P2PSend) (map[uint32]*P2PSend, error) {
if err := signer.verifyStateMap(2, params); err != nil {
return nil, err
}
// In dearlerless version, p2p map must contain one message from each cosigner.
if !signer.state.keyGenType.IsTrustedDealer() {
if err := signer.verifyStateMap(2, p2p); err != nil {
return nil, err
}
}
cnt := signer.threshold - 1
p2PSend := make(map[uint32]*P2PSend, cnt)
signer.state.betaj = make(map[uint32]*big.Int, cnt)
signer.state.vuj = make(map[uint32]*big.Int, cnt)
signer.state.cj = make(map[uint32]paillier.Ciphertext, cnt)
signer.state.Cj = make(map[uint32]core.Commitment, cnt)
// This is outside the loop for efficiency since the only changing value is the
// params ciphertext
pp := &proof.Proof1Params{
Curve: signer.Curve,
DealerParams: signer.state.keyGenType.GetProofParams(signer.id),
}
rpp := proof.ResponseProofParams{
Curve: signer.Curve,
B: signer.publicSharesMap[signer.id].Point,
}
// 1. For j = [1 ... t+1]
for j, param := range params {
// 2. if i == j, continue
if param == nil || j == signer.id {
continue
}
// 3. if MtAVerifyRange(\pi_j^{Range1}, g, q, N~, h1, h2, c_j) == False then Abort
pp.Pk = signer.state.pks[j]
pp.C = param.Ctxt
if signer.state.keyGenType.IsTrustedDealer() {
if err := param.Proof.Verify(pp); err != nil {
return nil, err
}
} else {
// The case using DKG, verify range proof in P2PSend
if err := p2p[j].Verify(pp); err != nil {
return nil, err
}
}
// 4. Compute c^{\gamma}_{ji}, \beta_{ji}, \pi^{Range2}_{ji} = MtaResponse(γ_i,g,q,pk_j,N~,h1,h2,c_j)
rpp.C1 = param.Ctxt
rpp.DealerParams = signer.state.keyGenType.GetProofParams(j)
rpp.SmallB = signer.state.gammai
rpp.Pk = signer.state.pks[j]
proofGamma, err := rpp.Prove()
if err != nil {
return nil, err
}
// 5. Compute c^{w}_{ji}, \vu_{ji}, \pi^{Range3}_{ji} = MtaResponse_wc(w_i,W_i,g,q,pk_j,N~,h1,h2,c_j)
rpp.SmallB = signer.share.Value.BigInt()
proofW, err := rpp.ProveWc()
if err != nil {
return nil, err
}
// Store the values for later rounds
signer.state.cj[j] = param.Ctxt
signer.state.betaj[j] = proofGamma.Beta
signer.state.vuj[j] = proofW.Beta
signer.state.Cj[j] = param.C
// Beta and vu are not sent to other signers
proofGamma.Beta = nil
proofW.Beta = nil
// 6. P2PSend(c^{gamma}_{ji}, c_^{W}_{ji}, \pi^{Range2}_{ji}, \pi^{Range3}_{ji})
p2PSend[j] = &P2PSend{
Proof2: proofGamma,
Proof3: proofW,
}
}
signer.Round = 3
return p2PSend, nil
}