keygen: adding a Schnorr proof in round 1. Adding missing ridi and rid. Adding Xi and Ai to the hashes and messages. Adding Schnorr zkp in round 3. Adding proof verifications in round 4.

This commit is contained in:
Gustavo Frederico
2021-10-18 18:39:19 -04:00
parent 2abb1033ec
commit 4397af0043
9 changed files with 271 additions and 66 deletions

View File

@@ -54,20 +54,59 @@ func NewProof(X *crypto.ECPoint, x *big.Int) (*ProofSch, error) {
return &ProofSch{A: A, Z: z}, nil
}
// NewProof implements proofsch
func NewProofWithAlpha(X *crypto.ECPoint, x *big.Int, alpha *big.Int, aux *big.Int) (*ProofSch, error) {
if x == nil || X == nil || !X.ValidateBasic() {
return nil, errors.New("zkpsch constructor received nil or invalid value(s)")
}
ec := X.Curve()
q := ec.Params().N
g := crypto.NewECPointNoCurveCheck(ec, ec.Params().Gx, ec.Params().Gy) // already on the curve.
// Fig 22.1
A := crypto.ScalarBaseMult(ec, alpha)
// Fig 22.2 e
var e *big.Int
{
eHash := common.SHA512_256i(X.X(), X.Y(), g.X(), g.Y(), A.X(), A.Y(), aux)
e = common.RejectionSample(q, eHash)
}
// Fig 22.3
z := new(big.Int).Mul(e, x)
z = common.ModInt(q).Add(alpha, z)
return &ProofSch{A: A, Z: z}, nil
}
func NewProofCommitment(X *crypto.ECPoint, x *big.Int) (*crypto.ECPoint, *big.Int, error) {
if x == nil || X == nil || !X.ValidateBasic() {
return nil, nil, errors.New("zkpsch constructor received nil or invalid value(s)")
}
ec := X.Curve()
q := ec.Params().N
// Fig 22.1
alpha := common.GetRandomPositiveInt(q)
A := crypto.ScalarBaseMult(ec, alpha)
return A, alpha, nil
}
func NewProofFromBytes(ec elliptic.Curve, bzs [][]byte) (*ProofSch, error) {
if !common.NonEmptyMultiBytes(bzs, ProofSchBytesParts) {
return nil, fmt.Errorf("expected %d byte parts to construct ProofSch", ProofSchBytesParts)
}
if !common.NonEmptyMultiBytes(bzs, ProofSchBytesParts) {
return nil, fmt.Errorf("expected %d byte parts to construct ProofSch", ProofSchBytesParts)
}
point, err := crypto.NewECPoint(ec,
new(big.Int).SetBytes(bzs[0]),
new(big.Int).SetBytes(bzs[1]))
if err != nil {
return nil, err
}
return &ProofSch{
A: point,
Z: new(big.Int).SetBytes(bzs[2]),
}, nil
new(big.Int).SetBytes(bzs[0]),
new(big.Int).SetBytes(bzs[1]))
if err != nil {
return nil, err
}
return &ProofSch{
A: point,
Z: new(big.Int).SetBytes(bzs[2]),
}, nil
}
func (pf *ProofSch) Verify(X *crypto.ECPoint) bool {
@@ -97,14 +136,41 @@ func (pf *ProofSch) Verify(X *crypto.ECPoint) bool {
return true
}
func (pf *ProofSch) VerifyWithAux(X *crypto.ECPoint, aux *big.Int) bool {
if pf == nil || !pf.ValidateBasic() || X == nil {
return false
}
ec := X.Curve()
q := ec.Params().N
g := crypto.NewECPointNoCurveCheck(ec, ec.Params().Gx, ec.Params().Gy)
var e *big.Int
{
eHash := common.SHA512_256i(X.X(), X.Y(), g.X(), g.Y(), pf.A.X(), pf.A.Y(), aux)
e = common.RejectionSample(q, eHash)
}
// Fig 22. Verification
left := crypto.ScalarBaseMult(ec, pf.Z)
XEXPe := X.ScalarMult(e)
right, err := pf.A.Add(XEXPe)
if err != nil {
return false
}
if right.X().Cmp(left.X()) != 0 || right.Y().Cmp(left.Y()) != 0 {
return false
}
return true
}
func (pf *ProofSch) ValidateBasic() bool {
return pf.Z != nil && pf.A != nil
}
func (pf *ProofSch) Bytes() [ProofSchBytesParts][]byte {
return [...][]byte{
pf.A.X().Bytes(),
pf.A.Y().Bytes(),
pf.Z.Bytes(),
}
return [...][]byte{
pf.A.X().Bytes(),
pf.A.Y().Bytes(),
pf.Z.Bytes(),
}
}

View File

@@ -7,7 +7,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.17.3
// protoc v3.18.1
// source: protob/ecdsa-keygen.proto
package keygen
@@ -87,6 +87,9 @@ type KGRound2Message struct {
NTilde []byte `protobuf:"bytes,3,opt,name=n_tilde,json=nTilde,proto3" json:"n_tilde,omitempty"`
H1 []byte `protobuf:"bytes,4,opt,name=h1,proto3" json:"h1,omitempty"`
H2 []byte `protobuf:"bytes,5,opt,name=h2,proto3" json:"h2,omitempty"`
Ridi []byte `protobuf:"bytes,6,opt,name=ridi,proto3" json:"ridi,omitempty"`
Ai [][]byte `protobuf:"bytes,7,rep,name=Ai,proto3" json:"Ai,omitempty"`
Xi [][]byte `protobuf:"bytes,8,rep,name=Xi,proto3" json:"Xi,omitempty"`
}
func (x *KGRound2Message) Reset() {
@@ -156,6 +159,27 @@ func (x *KGRound2Message) GetH2() []byte {
return nil
}
func (x *KGRound2Message) GetRidi() []byte {
if x != nil {
return x.Ridi
}
return nil
}
func (x *KGRound2Message) GetAi() [][]byte {
if x != nil {
return x.Ai
}
return nil
}
func (x *KGRound2Message) GetXi() [][]byte {
if x != nil {
return x.Xi
}
return nil
}
//
// Represents a P2P message sent to each party during Round 2 of the ECDSA TSS keygen protocol.
type KGRound3Message struct {
@@ -163,9 +187,10 @@ type KGRound3Message struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Share []byte `protobuf:"bytes,1,opt,name=share,proto3" json:"share,omitempty"`
ModProof [][]byte `protobuf:"bytes,2,rep,name=mod_proof,json=modProof,proto3" json:"mod_proof,omitempty"`
PrmProof [][]byte `protobuf:"bytes,3,rep,name=prm_proof,json=prmProof,proto3" json:"prm_proof,omitempty"`
Share []byte `protobuf:"bytes,1,opt,name=share,proto3" json:"share,omitempty"`
ModProof [][]byte `protobuf:"bytes,2,rep,name=mod_proof,json=modProof,proto3" json:"mod_proof,omitempty"`
PrmProof [][]byte `protobuf:"bytes,3,rep,name=prm_proof,json=prmProof,proto3" json:"prm_proof,omitempty"`
PsiiProof [][]byte `protobuf:"bytes,4,rep,name=psii_proof,json=psiiProof,proto3" json:"psii_proof,omitempty"`
}
func (x *KGRound3Message) Reset() {
@@ -221,6 +246,13 @@ func (x *KGRound3Message) GetPrmProof() [][]byte {
return nil
}
func (x *KGRound3Message) GetPsiiProof() [][]byte {
if x != nil {
return x.PsiiProof
}
return nil
}
//
// Represents a BROADCAST message sent to each party during Round 3 of the ECDSA TSS keygen protocol.
type KGRound4Message struct {
@@ -279,24 +311,30 @@ var file_protob_ecdsa_keygen_proto_rawDesc = []byte{
0x61, 0x2e, 0x6b, 0x65, 0x79, 0x67, 0x65, 0x6e, 0x22, 0x27, 0x0a, 0x0f, 0x4b, 0x47, 0x52, 0x6f,
0x75, 0x6e, 0x64, 0x31, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56,
0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x56, 0x48, 0x61, 0x73,
0x68, 0x22, 0x79, 0x0a, 0x0f, 0x4b, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x32, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x76, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c,
0x52, 0x02, 0x76, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x69, 0x6c, 0x6c, 0x69, 0x65, 0x72,
0x5f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x61, 0x69, 0x6c, 0x6c, 0x69,
0x65, 0x72, 0x4e, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x5f, 0x74, 0x69, 0x6c, 0x64, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x54, 0x69, 0x6c, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02,
0x68, 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x68, 0x31, 0x12, 0x0e, 0x0a, 0x02,
0x68, 0x32, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x68, 0x32, 0x22, 0x61, 0x0a, 0x0f,
0x4b, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x33, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12,
0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x6f, 0x64, 0x5f, 0x70, 0x72, 0x6f,
0x6f, 0x66, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x6f, 0x64, 0x50, 0x72, 0x6f,
0x6f, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18,
0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x70, 0x72, 0x6d, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22,
0x27, 0x0a, 0x0f, 0x4b, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x34, 0x4d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0c, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x0e, 0x5a, 0x0c, 0x65, 0x63, 0x64, 0x73,
0x61, 0x2f, 0x6b, 0x65, 0x79, 0x67, 0x65, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x68, 0x22, 0xad, 0x01, 0x0a, 0x0f, 0x4b, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x32, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x76, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0c, 0x52, 0x02, 0x76, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x69, 0x6c, 0x6c, 0x69, 0x65,
0x72, 0x5f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x61, 0x69, 0x6c, 0x6c,
0x69, 0x65, 0x72, 0x4e, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x5f, 0x74, 0x69, 0x6c, 0x64, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x54, 0x69, 0x6c, 0x64, 0x65, 0x12, 0x0e, 0x0a,
0x02, 0x68, 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x68, 0x31, 0x12, 0x0e, 0x0a,
0x02, 0x68, 0x32, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x68, 0x32, 0x12, 0x12, 0x0a,
0x04, 0x72, 0x69, 0x64, 0x69, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x72, 0x69, 0x64,
0x69, 0x12, 0x0e, 0x0a, 0x02, 0x41, 0x69, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x41,
0x69, 0x12, 0x0e, 0x0a, 0x02, 0x58, 0x69, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x58,
0x69, 0x22, 0x80, 0x01, 0x0a, 0x0f, 0x4b, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x33, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d,
0x6f, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08,
0x6d, 0x6f, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x6d, 0x5f,
0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x70, 0x72, 0x6d,
0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x73, 0x69, 0x69, 0x5f, 0x70, 0x72,
0x6f, 0x6f, 0x66, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x73, 0x69, 0x69, 0x50,
0x72, 0x6f, 0x6f, 0x66, 0x22, 0x27, 0x0a, 0x0f, 0x4b, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x34,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x0e, 0x5a,
0x0c, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2f, 0x6b, 0x65, 0x79, 0x67, 0x65, 0x6e, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@@ -41,16 +41,25 @@ type (
localTempData struct {
// temp data (thrown away after keygen)
ui *big.Int // used for tests
shares vss.Shares
vs vss.Vs
ui *big.Int // used for tests
ridi *big.Int // used for tests
rid *big.Int
shares vss.Shares
vs vss.Vs
Ai *crypto.ECPoint
Xi *crypto.ECPoint
τ *big.Int
r1msgVHashs []*big.Int
r2msgVss [][]*crypto.ECPoint
r3msgxij []*big.Int
r3msgpfmod []*zkpmod.ProofMod
r3msgpfprm []*zkpprm.ProofPrm
r4msgpf []*zkpsch.ProofSch
r1msgVHashs []*big.Int
r2msgVss [][]*crypto.ECPoint
r2msgAj []*crypto.ECPoint
r2msgXj []*crypto.ECPoint
r2msgRidj []*big.Int
r3msgxij []*big.Int
r3msgpfmod []*zkpmod.ProofMod
r3msgpfprm []*zkpprm.ProofPrm
r3msgpfsch []*zkpsch.ProofSch
r4msgpf []*zkpsch.ProofSch
}
)
@@ -84,9 +93,13 @@ func NewLocalParty(
// msgs data init
p.temp.r1msgVHashs = make([]*big.Int, partyCount)
p.temp.r2msgVss = make([][]*crypto.ECPoint, partyCount)
p.temp.r2msgAj = make([]*crypto.ECPoint, partyCount)
p.temp.r2msgXj = make([]*crypto.ECPoint, partyCount)
p.temp.r2msgRidj = make([]*big.Int, partyCount)
p.temp.r3msgxij = make([]*big.Int, partyCount)
p.temp.r3msgpfmod = make([]*zkpmod.ProofMod, partyCount)
p.temp.r3msgpfprm = make([]*zkpprm.ProofPrm, partyCount)
p.temp.r3msgpfsch = make([]*zkpsch.ProofSch, partyCount)
p.temp.r4msgpf = make([]*zkpsch.ProofSch, partyCount)
return p
}
@@ -145,6 +158,9 @@ func (p *LocalParty) StoreMessage(msg tss.ParsedMessage) (bool, *tss.Error) {
p.data.H1j[fromPIdx], p.data.H2j[fromPIdx] = r2msg.UnmarshalH1(), r2msg.UnmarshalH2()
var err error
p.temp.r2msgVss[fromPIdx], err = r2msg.UnmarshalVs(p.params.EC())
p.temp.r2msgAj[fromPIdx], err = r2msg.UnmarshalAi(p.params.EC())
p.temp.r2msgXj[fromPIdx], err = r2msg.UnmarshalXi(p.params.EC())
p.temp.r2msgRidj[fromPIdx] = r2msg.UnmarshalRidi()
if err != nil {
return false, p.WrapError(err)
}
@@ -174,6 +190,11 @@ func (p *LocalParty) StoreMessage(msg tss.ParsedMessage) (bool, *tss.Error) {
// }
p.temp.r3msgpfprm[fromPIdx] = proofPrm
proofSch, err := r3msg.UnmarshalProofSch(p.params.EC())
if err != nil {
return false, p.WrapError(err, p.params.Parties().IDs()[fromPIdx])
}
p.temp.r3msgpfsch[fromPIdx] = proofSch
case *KGRound4Message:
//p.temp.kgRound4Messages[fromPIdx] = msg
r4msg := msg.Content().(*KGRound4Message)

View File

@@ -65,7 +65,8 @@ func NewKGRound2Message(
from *tss.PartyID,
vs vss.Vs,
paillierPK *paillier.PublicKey,
nTildeI, h1I, h2I *big.Int,
nTildeI, h1I, h2I, ridi *big.Int,
Ai, Xi *crypto.ECPoint,
) tss.ParsedMessage {
meta := tss.MessageRouting{
From: from,
@@ -73,15 +74,20 @@ func NewKGRound2Message(
}
vs_flat, _ := crypto.FlattenECPoints(vs)
vsbzs := make([][]byte, len(vs_flat))
for i, item := range(vs_flat) {
for i, item := range vs_flat {
vsbzs[i] = item.Bytes()
}
aiBytes := Ai.Bytes()
XiBytes := Xi.Bytes()
content := &KGRound2Message{
Vs: vsbzs[:],
PaillierN: paillierPK.N.Bytes(),
NTilde: nTildeI.Bytes(),
H1: h1I.Bytes(),
H2: h2I.Bytes(),
Vs: vsbzs[:],
PaillierN: paillierPK.N.Bytes(),
NTilde: nTildeI.Bytes(),
H1: h1I.Bytes(),
H2: h2I.Bytes(),
Ridi: ridi.Bytes(),
Ai: aiBytes[:],
Xi: XiBytes[:],
}
msg := tss.NewMessageWrapper(meta, content)
return tss.NewMessage(meta, content, msg)
@@ -92,13 +98,15 @@ func (m *KGRound2Message) ValidateBasic() bool {
common.NonEmptyBytes(m.GetPaillierN()) &&
common.NonEmptyBytes(m.GetNTilde()) &&
common.NonEmptyBytes(m.GetH1()) &&
common.NonEmptyBytes(m.GetH2())
common.NonEmptyBytes(m.GetH2()) &&
common.NonEmptyMultiBytes(m.GetAi()) &&
common.NonEmptyMultiBytes(m.GetXi())
}
func (m *KGRound2Message) UnmarshalVs(ec elliptic.Curve) ([]*crypto.ECPoint, error) {
bzs := m.GetVs()
vs_points := make([]*big.Int, len(bzs))
for i, item := range(m.GetVs()) {
for i, item := range m.GetVs() {
vs_points[i] = new(big.Int).SetBytes(item)
}
vs, err := crypto.UnFlattenECPoints(ec, vs_points)
@@ -124,6 +132,18 @@ func (m *KGRound2Message) UnmarshalH2() *big.Int {
return new(big.Int).SetBytes(m.GetH2())
}
func (m *KGRound2Message) UnmarshalAi(ec elliptic.Curve) (*crypto.ECPoint, error) {
return crypto.NewECPointFromBytes(ec, m.GetAi())
}
func (m *KGRound2Message) UnmarshalXi(ec elliptic.Curve) (*crypto.ECPoint, error) {
return crypto.NewECPointFromBytes(ec, m.GetXi())
}
func (m *KGRound2Message) UnmarshalRidi() *big.Int {
return new(big.Int).SetBytes(m.GetRidi())
}
// ----- //
func NewKGRound3Message(
@@ -131,6 +151,7 @@ func NewKGRound3Message(
share *big.Int,
proofMod *zkpmod.ProofMod,
proofPrm *zkpprm.ProofPrm,
ψi *zkpsch.ProofSch,
) tss.ParsedMessage {
meta := tss.MessageRouting{
From: from,
@@ -139,10 +160,12 @@ func NewKGRound3Message(
}
proofModBzs := proofMod.Bytes()
proofPrmBzs := proofPrm.Bytes()
proofPsiiBzs := ψi.Bytes()
content := &KGRound3Message{
Share: share.Bytes(),
ModProof: proofModBzs[:],
PrmProof: proofPrmBzs[:],
Share: share.Bytes(),
ModProof: proofModBzs[:],
PrmProof: proofPrmBzs[:],
PsiiProof: proofPsiiBzs[:],
}
msg := tss.NewMessageWrapper(meta, content)
return tss.NewMessage(meta, content, msg)
@@ -152,7 +175,8 @@ func (m *KGRound3Message) ValidateBasic() bool {
return m != nil &&
common.NonEmptyBytes(m.GetShare()) &&
common.NonEmptyMultiBytes(m.GetModProof(), zkpmod.ProofModBytesParts) &&
common.NonEmptyMultiBytes(m.GetPrmProof(), zkpprm.ProofPrmBytesParts)
common.NonEmptyMultiBytes(m.GetPrmProof(), zkpprm.ProofPrmBytesParts) &&
common.NonEmptyMultiBytes(m.GetPsiiProof(), zkpsch.ProofSchBytesParts)
}
func (m *KGRound3Message) UnmarshalShare() *big.Int {
@@ -167,6 +191,10 @@ func (m *KGRound3Message) UnmarshalProofPrm() (*zkpprm.ProofPrm, error) {
return zkpprm.NewProofFromBytes(m.GetPrmProof())
}
func (m *KGRound3Message) UnmarshalProofSch(ec elliptic.Curve) (*zkpsch.ProofSch, error) {
return zkpsch.NewProofFromBytes(ec, m.GetPsiiProof())
}
// ----- //
func NewKGRound4Message(

View File

@@ -13,6 +13,7 @@ import (
"github.com/binance-chain/tss-lib/common"
"github.com/binance-chain/tss-lib/crypto"
"github.com/binance-chain/tss-lib/crypto/vss"
zkpsch "github.com/binance-chain/tss-lib/crypto/zkp/sch"
"github.com/binance-chain/tss-lib/tss"
)
@@ -38,6 +39,7 @@ func (round *round1) Start() *tss.Error {
round.ok[i] = true
// Fig 5. Round 1. private key part
ridi := common.GetRandomPositiveInt(round.EC().Params().N)
ui := common.GetRandomPositiveInt(round.EC().Params().N)
// Fig 5. Round 1. pub key part, vss shares
@@ -46,6 +48,9 @@ func (round *round1) Start() *tss.Error {
if err != nil {
return round.WrapError(err, Pi)
}
xi := new(big.Int).Set(shares[i].Share)
Xi := crypto.ScalarBaseMult(round.EC(), xi)
Ai, τ, _ := zkpsch.NewProofCommitment(Xi, xi)
// Fig 6. Round 1.
var preParams *LocalPreParams
@@ -62,7 +67,7 @@ func (round *round1) Start() *tss.Error {
if err != nil {
return round.WrapError(err, Pi)
}
listToHash = append(listToHash, preParams.PaillierSK.PublicKey.N, preParams.NTildei, preParams.H1i, preParams.H2i)
listToHash = append(listToHash, preParams.PaillierSK.PublicKey.N, ridi, Xi.X(), Xi.Y(), Ai.X(), Ai.Y(), preParams.NTildei, preParams.H1i, preParams.H2i)
VHash := common.SHA512_256i(listToHash...)
{
msg := NewKGRound1Message(round.PartyID(), VHash)
@@ -70,7 +75,10 @@ func (round *round1) Start() *tss.Error {
}
round.temp.vs = vs
round.temp.ridi = ridi
round.temp.ui = ui
round.temp.Ai = Ai
round.temp.τ = τ
round.save.Ks = ids
round.save.LocalPreParams = *preParams
round.save.NTildej[i] = preParams.NTildei

View File

@@ -8,7 +8,9 @@ package keygen
import (
"errors"
"math/big"
"github.com/binance-chain/tss-lib/crypto"
"github.com/binance-chain/tss-lib/tss"
)
@@ -26,7 +28,10 @@ func (round *round2) Start() *tss.Error {
// Fig 5. Round 2. / Fig 6. Round 2.
{
msg := NewKGRound2Message(round.PartyID(), round.temp.vs, &round.save.PaillierSK.PublicKey, round.save.NTildei, round.save.H1i, round.save.H2i)
xi := new(big.Int).Set(round.temp.shares[i].Share)
Xi := crypto.ScalarBaseMult(round.EC(), xi)
msg := NewKGRound2Message(round.PartyID(), round.temp.vs, &round.save.PaillierSK.PublicKey, round.save.NTildei,
round.save.H1i, round.save.H2i, round.temp.ridi, round.temp.Ai, Xi)
round.out <- msg
}

View File

@@ -13,6 +13,7 @@ import (
"github.com/binance-chain/tss-lib/common"
"github.com/binance-chain/tss-lib/crypto"
zkpsch "github.com/binance-chain/tss-lib/crypto/zkp/sch"
"github.com/binance-chain/tss-lib/tss"
zkpmod "github.com/binance-chain/tss-lib/crypto/zkp/mod"
@@ -38,11 +39,13 @@ func (round *round3) Start() *tss.Error {
// Fig 5. Round 3.1 / Fig 6. Round 3.1
toCmp := new(big.Int).Lsh(big.NewInt(1), 1024)
errChs := make(chan *tss.Error, (len(round.Parties().IDs())-1)*3)
rid := round.temp.ridi
wg := sync.WaitGroup{}
for j, Pj := range round.Parties().IDs() {
if j == i {
continue
}
rid = new(big.Int).Xor(rid, round.temp.r2msgRidj[j])
wg.Add(1)
go func(j int, Pj *tss.PartyID) {
defer wg.Done()
@@ -60,7 +63,10 @@ func (round *round3) Start() *tss.Error {
errChs <- round.WrapError(err, Pj)
return
}
listToHash = append(listToHash, round.save.PaillierPKs[j].N, round.save.NTildej[j], round.save.H1j[j], round.save.H2j[j])
listToHash = append(listToHash, round.save.PaillierPKs[j].N, round.temp.r2msgRidj[j],
round.temp.r2msgXj[j].X(), round.temp.r2msgXj[j].Y(),
round.temp.r2msgAj[j].X(), round.temp.r2msgAj[j].Y(), round.save.NTildej[j], round.save.H1j[j],
round.save.H2j[j])
VjHash := common.SHA512_256i(listToHash...)
if VjHash.Cmp(round.temp.r1msgVHashs[j]) != 0 {
errChs <- round.WrapError(errors.New("verify hash failed"), Pj)
@@ -68,6 +74,7 @@ func (round *round3) Start() *tss.Error {
}
}(j, Pj)
}
round.temp.rid = rid
wg.Wait()
close(errChs)
culprits := make([]*tss.PartyID, 0)
@@ -88,6 +95,12 @@ func (round *round3) Start() *tss.Error {
if err != nil {
return round.WrapError(errors.New("create proofPrm failed"))
}
xi := new(big.Int).Set(round.temp.shares[i].Share)
Xi := crypto.ScalarBaseMult(round.EC(), xi)
ψi, err := zkpsch.NewProofWithAlpha(Xi, xi, round.temp.τ, rid)
if err != nil {
return round.WrapError(errors.New("create proofSch failed"))
}
errChs = make(chan *tss.Error, len(round.Parties().IDs())-1)
wg = sync.WaitGroup{}
@@ -104,8 +117,8 @@ func (round *round3) Start() *tss.Error {
errChs <- round.WrapError(errors.New("encrypt error"), Pi)
return
}
r3msg := NewKGRound3Message(Pj, round.PartyID(), Cij, proofMod, proofPrm)
r3msg := NewKGRound3Message(Pj, round.PartyID(), Cij, proofMod, proofPrm, ψi)
round.out <- r3msg
}(j, Pj)
}

View File

@@ -45,6 +45,14 @@ func (round *round4) Start() *tss.Error {
}
}(j, Pj)
wg.Add(1)
go func(j int, Pj *tss.PartyID) {
defer wg.Done()
if ok := round.temp.r3msgpfsch[j].A.Equals(round.temp.r2msgAj[j]); !ok { // Verify A^j = Aj
errChs <- round.WrapError(errors.New(" A^j != Aj"), Pj)
}
}(j, Pj)
wg.Add(1)
go func(j int, Pj *tss.PartyID) {
defer wg.Done()
@@ -132,6 +140,20 @@ func (round *round4) Start() *tss.Error {
return round.WrapError(errors.New("adding Vc[c].ScalarMult(z) to BigXj resulted in a point not on the curve"), culprits...)
}
}
{
culprits := make([]*tss.PartyID, 0)
for j, Pj := range round.Parties().IDs() {
if j == i {
continue
}
if ok := round.temp.r3msgpfsch[j].VerifyWithAux(round.temp.r2msgXj[j], round.temp.rid); !ok {
culprits = append(culprits, Pj)
}
}
if len(culprits) > 0 {
return round.WrapError(errors.New("schnorr verification failed"), culprits...)
}
}
// Compute and SAVE the ECDSA public key `y`
ecdsaPubKey, err := crypto.NewECPoint(round.Params().EC(), Vc[0].X(), Vc[0].Y())

View File

@@ -24,6 +24,9 @@ message KGRound2Message {
bytes n_tilde = 3;
bytes h1 = 4;
bytes h2 = 5;
bytes ridi = 6;
repeated bytes Ai = 7;
repeated bytes Xi = 8;
}
/*
@@ -33,6 +36,7 @@ message KGRound3Message {
bytes share = 1;
repeated bytes mod_proof = 2;
repeated bytes prm_proof = 3;
repeated bytes psii_proof = 4;
}
/*