Identification of aborts with unit test.

This commit is contained in:
Gustavo Frederico
2021-10-26 23:39:42 -04:00
parent b961e02c70
commit ac1d2cc9a0
17 changed files with 400 additions and 103 deletions

View File

@@ -7,7 +7,20 @@
package common
import (
"math/big"
"github.com/ipfs/go-log"
)
var Logger = log.Logger("tss-lib")
func FormatBigInt(a *big.Int) string {
if a == nil {
return "<nil>"
}
var aux = new(big.Int).SetInt64(0xFFFFFFFF)
return func(i *big.Int) string {
return new(big.Int).And(i, aux).Text(16)
}(a)
}

View File

@@ -25,3 +25,9 @@ func GenerateNTildei(safePrimes [2]*big.Int) (NTildei, h1i, h2i *big.Int, err er
h2 := common.GetRandomGeneratorOfTheQuadraticResidue(NTildei)
return NTildei, h1, h2, nil
}
func FormatECPoint(p *ECPoint) string {
x := common.FormatBigInt(p.X())
y := common.FormatBigInt(p.Y())
return "(" + x + "," + y + ")"
}

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-signing.proto
package signing
@@ -310,6 +310,44 @@ func (x *SignRound4Message) GetSigmaShare() []byte {
return nil
}
type SignRound4AbortingMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *SignRound4AbortingMessage) Reset() {
*x = SignRound4AbortingMessage{}
if protoimpl.UnsafeEnabled {
mi := &file_protob_ecdsa_signing_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SignRound4AbortingMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SignRound4AbortingMessage) ProtoMessage() {}
func (x *SignRound4AbortingMessage) ProtoReflect() protoreflect.Message {
mi := &file_protob_ecdsa_signing_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SignRound4AbortingMessage.ProtoReflect.Descriptor instead.
func (*SignRound4AbortingMessage) Descriptor() ([]byte, []int) {
return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{4}
}
type IdentificationRound6Message struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -324,7 +362,7 @@ type IdentificationRound6Message struct {
func (x *IdentificationRound6Message) Reset() {
*x = IdentificationRound6Message{}
if protoimpl.UnsafeEnabled {
mi := &file_protob_ecdsa_signing_proto_msgTypes[4]
mi := &file_protob_ecdsa_signing_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -337,7 +375,7 @@ func (x *IdentificationRound6Message) String() string {
func (*IdentificationRound6Message) ProtoMessage() {}
func (x *IdentificationRound6Message) ProtoReflect() protoreflect.Message {
mi := &file_protob_ecdsa_signing_proto_msgTypes[4]
mi := &file_protob_ecdsa_signing_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -350,7 +388,7 @@ func (x *IdentificationRound6Message) ProtoReflect() protoreflect.Message {
// Deprecated: Use IdentificationRound6Message.ProtoReflect.Descriptor instead.
func (*IdentificationRound6Message) Descriptor() ([]byte, []int) {
return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{4}
return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{5}
}
func (x *IdentificationRound6Message) GetH() []byte {
@@ -393,7 +431,7 @@ type TempDataDumpMessage struct {
func (x *TempDataDumpMessage) Reset() {
*x = TempDataDumpMessage{}
if protoimpl.UnsafeEnabled {
mi := &file_protob_ecdsa_signing_proto_msgTypes[5]
mi := &file_protob_ecdsa_signing_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -406,7 +444,7 @@ func (x *TempDataDumpMessage) String() string {
func (*TempDataDumpMessage) ProtoMessage() {}
func (x *TempDataDumpMessage) ProtoReflect() protoreflect.Message {
mi := &file_protob_ecdsa_signing_proto_msgTypes[5]
mi := &file_protob_ecdsa_signing_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -419,7 +457,7 @@ func (x *TempDataDumpMessage) ProtoReflect() protoreflect.Message {
// Deprecated: Use TempDataDumpMessage.ProtoReflect.Descriptor instead.
func (*TempDataDumpMessage) Descriptor() ([]byte, []int) {
return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{5}
return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{6}
}
func (x *TempDataDumpMessage) GetDataDump() []byte {
@@ -476,22 +514,24 @@ var file_protob_ecdsa_signing_proto_rawDesc = []byte{
0x73, 0x74, 0x61, 0x72, 0x22, 0x33, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e,
0x64, 0x34, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x69, 0x67,
0x6d, 0x61, 0x53, 0x68, 0x61, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x53,
0x69, 0x67, 0x6d, 0x61, 0x53, 0x68, 0x61, 0x72, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x1b, 0x49, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x75, 0x6e,
0x64, 0x36, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0c, 0x0a, 0x01, 0x48, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x48, 0x12, 0x1a, 0x0a, 0x08, 0x4d, 0x75, 0x6c, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x4d, 0x75, 0x6c, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x53, 0x68, 0x61, 0x72,
0x65, 0x45, 0x6e, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x44, 0x65, 0x6c, 0x74,
0x61, 0x53, 0x68, 0x61, 0x72, 0x65, 0x45, 0x6e, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x44, 0x65, 0x63,
0x50, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x44, 0x65, 0x63,
0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x4d, 0x0a, 0x13, 0x54, 0x65, 0x6d, 0x70, 0x44, 0x61, 0x74,
0x61, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08,
0x44, 0x61, 0x74, 0x61, 0x44, 0x75, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08,
0x44, 0x61, 0x74, 0x61, 0x44, 0x75, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x6f, 0x75, 0x6e,
0x64, 0x4e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x52, 0x6f, 0x75, 0x6e,
0x64, 0x4e, 0x75, 0x6d, 0x42, 0x0f, 0x5a, 0x0d, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2f, 0x73, 0x69,
0x67, 0x6e, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x69, 0x67, 0x6d, 0x61, 0x53, 0x68, 0x61, 0x72, 0x65, 0x22, 0x1b, 0x0a, 0x19, 0x53, 0x69, 0x67,
0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x34, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x4d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x1b, 0x49, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x36, 0x4d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0c, 0x0a, 0x01, 0x48, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x01, 0x48, 0x12, 0x1a, 0x0a, 0x08, 0x4d, 0x75, 0x6c, 0x50, 0x72, 0x6f, 0x6f, 0x66,
0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x4d, 0x75, 0x6c, 0x50, 0x72, 0x6f, 0x6f, 0x66,
0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x53, 0x68, 0x61, 0x72, 0x65, 0x45, 0x6e,
0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x53, 0x68,
0x61, 0x72, 0x65, 0x45, 0x6e, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x44, 0x65, 0x63, 0x50, 0x72, 0x6f,
0x6f, 0x66, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x44, 0x65, 0x63, 0x50, 0x72, 0x6f,
0x6f, 0x66, 0x22, 0x4d, 0x0a, 0x13, 0x54, 0x65, 0x6d, 0x70, 0x44, 0x61, 0x74, 0x61, 0x44, 0x75,
0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x44, 0x61, 0x74,
0x61, 0x44, 0x75, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x44, 0x61, 0x74,
0x61, 0x44, 0x75, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x4e, 0x75,
0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x4e, 0x75,
0x6d, 0x42, 0x0f, 0x5a, 0x0d, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x69,
0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -506,14 +546,15 @@ func file_protob_ecdsa_signing_proto_rawDescGZIP() []byte {
return file_protob_ecdsa_signing_proto_rawDescData
}
var file_protob_ecdsa_signing_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_protob_ecdsa_signing_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_protob_ecdsa_signing_proto_goTypes = []interface{}{
(*PreSignRound1Message)(nil), // 0: binance.tsslib.ecdsa.signing.PreSignRound1Message
(*PreSignRound2Message)(nil), // 1: binance.tsslib.ecdsa.signing.PreSignRound2Message
(*PreSignRound3Message)(nil), // 2: binance.tsslib.ecdsa.signing.PreSignRound3Message
(*SignRound4Message)(nil), // 3: binance.tsslib.ecdsa.signing.SignRound4Message
(*IdentificationRound6Message)(nil), // 4: binance.tsslib.ecdsa.signing.IdentificationRound6Message
(*TempDataDumpMessage)(nil), // 5: binance.tsslib.ecdsa.signing.TempDataDumpMessage
(*SignRound4AbortingMessage)(nil), // 4: binance.tsslib.ecdsa.signing.SignRound4AbortingMessage
(*IdentificationRound6Message)(nil), // 5: binance.tsslib.ecdsa.signing.IdentificationRound6Message
(*TempDataDumpMessage)(nil), // 6: binance.tsslib.ecdsa.signing.TempDataDumpMessage
}
var file_protob_ecdsa_signing_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
@@ -578,7 +619,7 @@ func file_protob_ecdsa_signing_proto_init() {
}
}
file_protob_ecdsa_signing_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*IdentificationRound6Message); i {
switch v := v.(*SignRound4AbortingMessage); i {
case 0:
return &v.state
case 1:
@@ -590,6 +631,18 @@ func file_protob_ecdsa_signing_proto_init() {
}
}
file_protob_ecdsa_signing_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*IdentificationRound6Message); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_protob_ecdsa_signing_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TempDataDumpMessage); i {
case 0:
return &v.state
@@ -608,7 +661,7 @@ func file_protob_ecdsa_signing_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_protob_ecdsa_signing_proto_rawDesc,
NumEnums: 0,
NumMessages: 6,
NumMessages: 7,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -17,8 +17,8 @@ import (
)
func newRound6(params *tss.Parameters, key *keygen.LocalPartySaveData, data *common.SignatureData, temp *localTempData, out chan<- tss.Message, end chan<- common.SignatureData) tss.Round {
return &identification6{&sign4{&presign3{&presign2{&presign1{
&base{params, key, data, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 3}}}}}}
return &identification6{&identificationPrep{&sign4{&presign3{&presign2{&presign1{
&base{params, key, data, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 3}}}}, false}}}
}
func (round *identification6) Start() *tss.Error {

View File

@@ -16,8 +16,8 @@ import (
)
func newRound7(params *tss.Parameters, key *keygen.LocalPartySaveData, data *common.SignatureData, temp *localTempData, out chan<- tss.Message, end chan<- common.SignatureData) tss.Round {
return &identification7{&identification6{&sign4{&presign3{&presign2{&presign1{
&base{params, key, data, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 3}}}}}}}
return &identification7{&identification6{&identificationPrep{&sign4{&presign3{&presign2{&presign1{
&base{params, key, data, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 3}}}}, false}}}}
}
func (round *identification7) Start() *tss.Error {
@@ -50,7 +50,7 @@ func (round *identification7) Start() *tss.Error {
}
proofDec := round.temp.r6msgProofDec[j]
ok = proofDec.Verify(round.EC(), round.key.PaillierPKs[j], round.temp.r6msgDeltaShareEnc[j], round.temp.r3msgDeltaShare[j], round.key.NTildei, round.key.H1i, round.key.H2i)
ok = proofDec.Verify(round.EC(), round.key.PaillierPKs[j], round.temp.r6msgDeltaShareEnc[j], round.temp.r3msg𝛿j[j], round.key.NTildei, round.key.H1i, round.key.H2i)
if !ok {
errChs <- round.WrapError(errors.New("round7: proofdec verify failed"), Pj)
return

View File

@@ -0,0 +1,31 @@
// Copyright © 2021 Swingby
package signing
import (
"errors"
"github.com/binance-chain/tss-lib/tss"
)
func (round *identificationPrep) Start() *tss.Error {
if round.started {
return round.WrapError(errors.New("round already started"))
}
round.number = 5
round.started = true
round.AbortingSigning = true
round.setOK()
return nil
}
func (round *identificationPrep) NextRound() tss.Round {
round.started = false
return &identification6{round}
}
func (round *identificationPrep) setOK() {
for j := range round.ok {
round.ok[j] = true
}
}

View File

@@ -40,6 +40,7 @@ type (
out chan<- tss.Message
end chan<- common.SignatureData
startRndNum int
Aborting bool
}
// localMessageStore struct {
@@ -96,10 +97,11 @@ type (
r2msgChiF []*big.Int
r2msgChiProof []*zkpaffg.ProofAffg
r2msgProofLogstar []*zkplogstar.ProofLogstar
r3msgDeltaShare []*big.Int
r3msgBigDeltaShare []*crypto.ECPoint
r3msg𝛿j []*big.Int
r3msgΔj []*crypto.ECPoint
r3msgProofLogstar []*zkplogstar.ProofLogstar
r4msgSigmaShare []*big.Int
r4msg𝜎j []*big.Int
r4msgAborting []bool
// for identification
r6msgH []*big.Int
r6msgProofMul []*zkpmul.ProofMul
@@ -157,10 +159,11 @@ func NewLocalParty(
p.temp.r2msgChiF = make([]*big.Int, partyCount)
p.temp.r2msgChiProof = make([]*zkpaffg.ProofAffg, partyCount)
p.temp.r2msgProofLogstar = make([]*zkplogstar.ProofLogstar, partyCount)
p.temp.r3msgDeltaShare = make([]*big.Int, partyCount)
p.temp.r3msgBigDeltaShare = make([]*crypto.ECPoint, partyCount)
p.temp.r3msg𝛿j = make([]*big.Int, partyCount)
p.temp.r3msgΔj = make([]*crypto.ECPoint, partyCount)
p.temp.r3msgProofLogstar = make([]*zkplogstar.ProofLogstar, partyCount)
p.temp.r4msgSigmaShare = make([]*big.Int, partyCount)
p.temp.r4msg𝜎j = make([]*big.Int, partyCount)
p.temp.r4msgAborting = make([]bool, partyCount)
// for identification
p.temp.r6msgH = make([]*big.Int, partyCount)
p.temp.r6msgProofMul = make([]*zkpmul.ProofMul, partyCount)
@@ -261,12 +264,12 @@ func (p *LocalParty) StoreMessage(msg tss.ParsedMessage) (bool, *tss.Error) {
p.temp.r2msgChiProof[fromPIdx] = proofChi
case *PreSignRound3Message:
r3msg := msg.Content().(*PreSignRound3Message)
p.temp.r3msgDeltaShare[fromPIdx] = r3msg.UnmarshalDeltaShare()
p.temp.r3msg𝛿j[fromPIdx] = r3msg.UnmarshalDeltaShare()
BigDeltaShare, err := r3msg.UnmarshalBigDeltaShare(p.params.EC())
if err != nil {
return false, p.WrapError(err, msg.GetFrom())
}
p.temp.r3msgBigDeltaShare[fromPIdx] = BigDeltaShare
p.temp.r3msgΔj[fromPIdx] = BigDeltaShare
proofLogStar, err := r3msg.UnmarshalProofLogstar(p.params.EC())
if err != nil {
return false, p.WrapError(err, msg.GetFrom())
@@ -274,7 +277,10 @@ func (p *LocalParty) StoreMessage(msg tss.ParsedMessage) (bool, *tss.Error) {
p.temp.r3msgProofLogstar[fromPIdx] = proofLogStar
case *SignRound4Message:
r4msg := msg.Content().(*SignRound4Message)
p.temp.r4msgSigmaShare[fromPIdx] = r4msg.UnmarshalSigmaShare()
p.temp.r4msg𝜎j[fromPIdx] = r4msg.UnmarshalSigmaShare()
case *SignRound4AbortingMessage:
p.temp.r4msgAborting[fromPIdx] = true
p.Aborting = true
case *IdentificationRound6Message:
r6msg := msg.Content().(*IdentificationRound6Message)
p.temp.r6msgH[fromPIdx] = r6msg.UnmarshalH()

View File

@@ -11,9 +11,12 @@ import (
"fmt"
"math/big"
"runtime"
"strings"
"sync/atomic"
"testing"
"github.com/binance-chain/tss-lib/crypto"
zkplogstar "github.com/binance-chain/tss-lib/crypto/zkp/logstar"
"github.com/btcsuite/btcd/btcec"
"github.com/ipfs/go-log"
"github.com/stretchr/testify/assert"
@@ -27,6 +30,8 @@ import (
const (
testParticipants = test.TestParticipants
testThreshold = test.TestThreshold
maliciousPartySimulatingAbort = 2
innocentPartySimulatingAbort = 1
)
func setUp(level string) {
@@ -248,6 +253,134 @@ signing:
}
}
//
func identifiedAbortUpdater(party tss.Party, msg tss.Message, parties []*LocalParty, errCh chan<- *tss.Error) {
// do not send a message from this party back to itself
if party.PartyID() == msg.GetFrom() {
return
}
bz, _, err := msg.WireBytes()
if err != nil {
errCh <- party.WrapError(err)
return
}
pMsg, err := tss.ParseWireMessage(bz, msg.GetFrom(), msg.IsBroadcast())
if err != nil {
errCh <- party.WrapError(err)
return
}
// Intercepting a round 3 message to inject a bad zk-proof and trigger an abort
if strings.HasSuffix(msg.Type(),"PreSignRound3Message") && !msg.IsBroadcast() &&
msg.GetFrom().Index == maliciousPartySimulatingAbort &&
len(msg.GetTo()) > 0 && msg.GetTo()[0].Index==innocentPartySimulatingAbort {
meta := tss.MessageRouting{
From: msg.GetFrom(),
To: msg.GetTo(),
IsBroadcast: false,
}
i := msg.GetFrom().Index
j := msg.GetTo()[0].Index
common.Logger.Debugf("intercepting and changing message %s from %s", msg.Type(), msg.GetFrom())
round := party.Round().(*presign3)
otherRound := parties[i].Round().(*presign3)
ec := tss.EC()
common.Logger.Debugf(" test - fake proof - i:%v, j: %v, PK: %v, K(C): %v, Γ(g): %v, NTildej(NCap): %v, " +
"H1j(s): %v, H2j(t): %v, ki(x): %v, 𝜌i: %v",
i,j, common.FormatBigInt(round.key.PaillierPKs[i].N), common.FormatBigInt(round.temp.K),
crypto.FormatECPoint(round.temp.Γ),
common.FormatBigInt(round.key.NTildej[j]), common.FormatBigInt(round.key.H1j[j]), common.FormatBigInt(round.key.H2j[j]),
common.FormatBigInt(otherRound.temp.ki), common.FormatBigInt(otherRound.temp.𝜌i))
proof, errP := zkplogstar.NewProof(ec, round.key.PaillierPKs[i], round.temp.K, &crypto.ECPoint{}, round.temp.Γ, round.key.NTildej[j],
round.key.H1j[j], round.key.H2j[j], otherRound.temp.ki, otherRound.temp.𝜌i)
if errP!=nil {
common.Logger.Errorf("error changing message %s from %s", msg.Type(), msg.GetFrom())
}
otherRound.temp.Δi = crypto.ScalarBaseMult(ec, big.NewInt(1)) // trigger inequality for Δ in sign_4
r3msg := NewPreSignRound3Message(msg.GetTo()[0], msg.GetFrom(), otherRound.temp.𝛿i, otherRound.temp.Δi, proof)
// repackaging the malicious message
pMsg = tss.NewMessage(meta, r3msg.Content(), tss.NewMessageWrapper(meta, r3msg.Content()))
}
if _, errUpdate := party.Update(pMsg); errUpdate != nil {
if errUpdate.Culprits()!= nil && len(errUpdate.Culprits())>0 {
errCh <- errUpdate
}
}
}
func TestAbortIdentification(t *testing.T) {
setUp("debug")
threshold := testThreshold
// PHASE: load keygen fixtures
keys, signPIDs, err := keygen.LoadKeygenTestFixturesRandomSet(testThreshold+1, testParticipants)
assert.NoError(t, err, "should load keygen fixtures")
assert.Equal(t, testThreshold+1, len(keys))
assert.Equal(t, testThreshold+1, len(signPIDs))
// PHASE: signing
// use a shuffled selection of the list of parties for this test
p2pCtx := tss.NewPeerContext(signPIDs)
parties := make([]*LocalParty, 0, len(signPIDs))
errCh := make(chan *tss.Error, len(signPIDs))
outCh := make(chan tss.Message, len(signPIDs))
endCh := make(chan common.SignatureData, len(signPIDs))
updater := identifiedAbortUpdater
// init the parties
for i := 0; i < len(signPIDs); i++ {
params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold)
keyDerivationDelta := big.NewInt(0)
P := NewLocalParty(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh).(*LocalParty)
parties = append(parties, P)
go func(P *LocalParty) {
if err := P.Start(); err != nil {
errCh <- err
}
}(P)
}
signing:
for {
select {
case errS := <-errCh:
assert.NotNil(t, errS, "there should have been an error")
assert.EqualValues(t, len(errS.Culprits()), 1, "there should have been one culprit")
assert.EqualValues(t, errS.Culprits()[0].Index, maliciousPartySimulatingAbort, "error in test in identification of the malicious party")
break signing
case msg := <-outCh:
dest := msg.GetTo()
if dest == nil {
for _, P := range parties {
if P.PartyID().Index == msg.GetFrom().Index {
continue
}
go updater(P, msg, parties, errCh)
}
} else {
if dest[0].Index == msg.GetFrom().Index {
t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index)
}
go updater(parties[dest[0].Index], msg, parties, errCh)
}
case sigData := <-endCh:
common.Logger.Debugf("sigData: %v", sigData)
assert.FailNow(t, "signing should not succeed in this test")
break signing
}
}
}
func TestFillTo32BytesInPlace(t *testing.T) {
s := big.NewInt(123456789)
normalizedS := padToLengthBytesInPlace(s.Bytes(), 32)

View File

@@ -161,8 +161,8 @@ func (m *PreSignRound2Message) UnmarshalLogstarProof(ec elliptic.Curve) (*zkplog
func NewPreSignRound3Message(
to, from *tss.PartyID,
DeltaShare *big.Int,
BigDeltaShare *crypto.ECPoint,
𝛿i *big.Int,
Δi *crypto.ECPoint,
ProofLogstar *zkplogstar.ProofLogstar,
) tss.ParsedMessage {
meta := tss.MessageRouting{
@@ -170,10 +170,10 @@ func NewPreSignRound3Message(
To: []*tss.PartyID{to},
IsBroadcast: false,
}
BigDeltaShareBzs := BigDeltaShare.Bytes()
BigDeltaShareBzs := Δi.Bytes()
ProofBz := ProofLogstar.Bytes()
content := &PreSignRound3Message{
DeltaShare: DeltaShare.Bytes(),
DeltaShare: 𝛿i.Bytes(),
BigDeltaShare: BigDeltaShareBzs[:],
ProofLogstar: ProofBz[:],
}
@@ -202,6 +202,22 @@ func (m *PreSignRound3Message) UnmarshalProofLogstar(ec elliptic.Curve) (*zkplog
// ----- //
func NewSignRound4AbortingMessage(
from *tss.PartyID,
) tss.ParsedMessage {
meta := tss.MessageRouting{
From: from,
IsBroadcast: true,
}
content := &SignRound4AbortingMessage{}
msg := tss.NewMessageWrapper(meta, content)
return tss.NewMessage(meta, content, msg)
}
func (m *SignRound4AbortingMessage) ValidateBasic() bool {
return m != nil
}
func NewSignRound4Message(
from *tss.PartyID,
SigmaShare *big.Int,

View File

@@ -138,8 +138,7 @@ func (round *presign2) Start() *tss.Error {
round.temp.Γi = Γi
// retire unused variables
round.temp.G = nil
round.temp.𝜈i = nil
round.temp.r1msg𝜓0ij = make([]*zkpenc.ProofEnc, round.PartyCount()) // GF TODO
return nil

View File

@@ -136,6 +136,11 @@ func (round *presign3) Start() *tss.Error {
errChs = make(chan *tss.Error, len(round.Parties().IDs())-1)
wg = sync.WaitGroup{}
round.temp.𝛿i = 𝛿i
round.temp.𝜒i = 𝜒i
round.temp.Δi = Δi
round.temp.Γ = Γ
for j, Pj := range round.Parties().IDs() {
if j == i {
continue
@@ -161,17 +166,12 @@ func (round *presign3) Start() *tss.Error {
return err
}
round.temp.𝛿i = 𝛿i
round.temp.𝜒i = 𝜒i
round.temp.Δi = Δi
round.temp.Γ = Γ
// retire unused variables
round.temp.w = nil
round.temp.BigWs = nil
round.temp.𝛾i = nil
round.temp.Γi = nil
round.temp.K = nil
round.temp.𝜌i = nil
round.temp.DeltaShareBetas = nil
round.temp.ChiShareBetas = nil
round.temp.DeltaShareAlphas = nil
@@ -189,7 +189,7 @@ func (round *presign3) Start() *tss.Error {
}
func (round *presign3) Update() (bool, *tss.Error) {
for j, msg := range round.temp.r3msgDeltaShare {
for j, msg := range round.temp.r3msg𝛿j {
if round.ok[j] {
continue
}
@@ -210,5 +210,5 @@ func (round *presign3) CanAccept(msg tss.ParsedMessage) bool {
func (round *presign3) NextRound() tss.Round {
round.started = false
return &sign4{round}
return &sign4{round, false}
}

View File

@@ -39,6 +39,10 @@ type (
}
sign4 struct {
*presign3
AbortingSigning bool
}
identificationPrep struct {
*sign4
}
signout struct {
*sign4
@@ -46,7 +50,7 @@ type (
// identification rounds
identification6 struct {
*sign4
*identificationPrep
}
identification7 struct {
*identification6
@@ -112,7 +116,14 @@ func (round *base) resetOK() {
}
}
func (round *base) setOK() {
for j := range round.ok {
round.ok[j] = true
}
}
func (round *base) Dump(dumpCh chan tss.ParsedMessage) {
DumpMsg := NewTempDataDumpMessage(round.PartyID(), *round.temp, round.number)
dumpCh <- DumpMsg
}
}

View File

@@ -20,7 +20,7 @@ import (
func newRound4(params *tss.Parameters, key *keygen.LocalPartySaveData, data *common.SignatureData, temp *localTempData, out chan<- tss.Message, end chan<- common.SignatureData) tss.Round {
return &sign4{&presign3{&presign2{&presign1{
&base{params, key, data, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 4}}}}}
&base{params, key, data, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 4}}}}, false}
}
func (round *sign4) Start() *tss.Error {
@@ -30,6 +30,7 @@ func (round *sign4) Start() *tss.Error {
round.number = 4
round.started = true
round.resetOK()
round.resetAborting()
i := round.PartyID().Index
round.ok[i] = true
@@ -45,10 +46,10 @@ func (round *sign4) Start() *tss.Error {
go func(j int, Pj *tss.PartyID) {
defer wg.Done()
Kj := round.temp.r1msgK[j]
BigDeltaSharej := round.temp.r3msgBigDeltaShare[j]
Δj := round.temp.r3msgΔj[j]
ψDoublePrimeij := round.temp.r3msgProofLogstar[j]
ok := ψDoublePrimeij.Verify(round.EC(), round.key.PaillierPKs[j], Kj, BigDeltaSharej, round.temp.Γ, round.key.NTildei, round.key.H1i, round.key.H2i)
ok := ψDoublePrimeij.Verify(round.EC(), round.key.PaillierPKs[j], Kj, Δj, round.temp.Γ, round.key.NTildei, round.key.H1i, round.key.H2i)
if !ok {
errChs <- round.WrapError(errors.New("proof verify failed"), Pj)
return
@@ -73,18 +74,21 @@ func (round *sign4) Start() *tss.Error {
if j == i {
continue
}
𝛿 = modN.Add(𝛿, round.temp.r3msgDeltaShare[j])
BigDeltaShare := round.temp.r3msgBigDeltaShare[j]
𝛿 = modN.Add(𝛿, round.temp.r3msg𝛿j[j])
Δj := round.temp.r3msgΔj[j]
var err error
Δ, err = Δ.Add(BigDeltaShare)
Δ, err = Δ.Add(Δj)
if err != nil {
return round.WrapError(errors.New("round4: failed to collect BigDelta"))
}
}
DeltaPoint := crypto.ScalarBaseMult(round.EC(), 𝛿)
if !DeltaPoint.Equals(Δ) {
return round.WrapError(errors.New("verify BigDelta failed"))
if !crypto.ScalarBaseMult(round.EC(), 𝛿).Equals(Δ) {
common.Logger.Errorf("part %v: verify BigDelta failed", round.PartyID())
round.AbortingSigning = true
round.setOK()
round.out <- NewSignRound4AbortingMessage(round.PartyID())
return nil
}
// compute the multiplicative inverse thelta mod q
𝛿Inverse := modN.ModInverse(𝛿)
@@ -101,27 +105,39 @@ func (round *sign4) Start() *tss.Error {
round.temp.Rx = r
round.temp.SigmaShare = 𝜎i
// retire unused variables
round.temp.𝜌i = nil
round.temp.K = nil
round.temp.r1msgK = make([]*big.Int, round.PartyCount())
round.temp.r3msgBigDeltaShare = make([]*crypto.ECPoint, round.PartyCount())
round.temp.r3msgDeltaShare = make([]*big.Int, round.PartyCount())
round.temp.r3msgΔj = make([]*crypto.ECPoint, round.PartyCount())
round.temp.r3msg𝛿j = make([]*big.Int, round.PartyCount())
round.temp.r3msgProofLogstar = make([]*zkplogstar.ProofLogstar, round.PartyCount())
return nil
}
func (round *sign4) Update() (bool, *tss.Error) {
for j, msg := range round.temp.r4msgSigmaShare {
for j, msg := range round.temp.r4msg𝜎j {
if round.ok[j] {
continue
}
if msg == nil {
return false, nil
if msg == nil && !round.temp.r4msgAborting[j] {
if round.temp.r4msgAborting[j] {
round.AbortingSigning = true
} else {
return false, nil
}
}
round.ok[j] = true
}
return true, nil
}
func (round *sign4) resetAborting() {
for j := range round.temp.r4msgAborting {
round.temp.r4msgAborting[j] = false
}
}
func (round *sign4) CanAccept(msg tss.ParsedMessage) bool {
if _, ok := msg.Content().(*SignRound4Message); ok {
return msg.IsBroadcast()
@@ -131,5 +147,15 @@ func (round *sign4) CanAccept(msg tss.ParsedMessage) bool {
func (round *sign4) NextRound() tss.Round {
round.started = false
otherPartyAborted := false
for _, abortingMsg := range round.temp.r4msgAborting {
if abortingMsg {
otherPartyAborted = true
break
}
}
if round.AbortingSigning || otherPartyAborted {
return &identificationPrep{round}
}
return &signout{round}
}

View File

@@ -32,7 +32,7 @@ func VerirySig(ec elliptic.Curve, R *crypto.ECPoint, S *big.Int, m *big.Int, PK
func newRound5(params *tss.Parameters, key *keygen.LocalPartySaveData, data *common.SignatureData, temp *localTempData, out chan<- tss.Message, end chan<- common.SignatureData) tss.Round {
return &signout{&sign4{&presign3{&presign2{&presign1{
&base{params, key, data, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 5}}}}}}
&base{params, key, data, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 5}}}}, false}}
}
func (round *signout) Start() *tss.Error {
@@ -51,7 +51,7 @@ func (round *signout) Start() *tss.Error {
if j == round.PartyID().Index {
continue
}
Sigma = modN.Add(Sigma, round.temp.r4msgSigmaShare[j])
Sigma = modN.Add(Sigma, round.temp.r4msg𝜎j[j])
}
recid := 0
// byte v = if(R.X > curve.N) then 2 else 0) | (if R.Y.IsEven then 0 else 1);
@@ -91,7 +91,8 @@ func (round *signout) Start() *tss.Error {
}
round.end <- *round.data
round.temp.G = nil
round.temp.𝜈i = nil
return nil
}

View File

@@ -46,6 +46,8 @@ message PreSignRound3Message {
message SignRound4Message {
bytes SigmaShare = 1;
}
message SignRound4AbortingMessage {
}
message IdentificationRound6Message {
bytes H = 1;

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/message.proto
package tss

View File

@@ -32,7 +32,7 @@ type Party interface {
// Private lifecycle methods
setRound(Round) *Error
round() Round
Round() Round
advance()
lock()
unlock()
@@ -79,7 +79,7 @@ func (p *BaseParty) ValidateMessage(msg ParsedMessage) (bool, *Error) {
}
func (p *BaseParty) String() string {
return fmt.Sprintf("round: %d", p.round().RoundNumber())
return fmt.Sprintf("round: %d", p.Round().RoundNumber())
}
// -----
@@ -93,7 +93,7 @@ func (p *BaseParty) setRound(round Round) *Error {
return nil
}
func (p *BaseParty) round() Round {
func (p *BaseParty) Round() Round {
return p.rnd
}
@@ -117,7 +117,7 @@ func BaseStart(p Party, task string, prepare ...func(Round) *Error) *Error {
if p.PartyID() == nil || !p.PartyID().ValidateBasic() {
return p.WrapError(fmt.Errorf("could not start. this party has an invalid PartyID: %+v", p.PartyID()))
}
if p.round() != nil {
if p.Round() != nil {
return p.WrapError(errors.New("could not start. this party is in an unexpected state. use the constructor and Start()"))
}
round := p.FirstRound()
@@ -132,11 +132,11 @@ func BaseStart(p Party, task string, prepare ...func(Round) *Error) *Error {
return err
}
}
common.Logger.Infof("party %s: %s round %d starting", p.round().Params().PartyID(), task, 1)
common.Logger.Infof("party %s: %s round %d starting", p.Round().Params().PartyID(), task, 1)
defer func() {
common.Logger.Debugf("party %s: %s round %d finished", p.round().Params().PartyID(), task, 1)
common.Logger.Debugf("party %s: %s round %d finished", p.Round().Params().PartyID(), task, 1)
}()
return p.round().Start()
return p.Round().Start()
}
// an implementation of Update that is shared across the different types of parties (keygen, signing, dynamic groups)
@@ -152,24 +152,24 @@ func BaseUpdate2(p Party, msg ParsedMessage, task string) (ok bool, err *Error)
}
p.lock() // data is written to P state below
common.Logger.Debugf("party %s received message: %s", p.PartyID(), msg.String())
if p.round() != nil {
common.Logger.Debugf("party %s round %d update: %s", p.PartyID(), p.round().RoundNumber(), msg.String())
if p.Round() != nil {
common.Logger.Debugf("party %s round %d update: %s", p.PartyID(), p.Round().RoundNumber(), msg.String())
}
if ok, err := p.StoreMessage(msg); err != nil || !ok {
return r(false, err)
}
if p.round() != nil {
common.Logger.Debugf("party %s: %s round %d update", p.round().Params().PartyID(), task, p.round().RoundNumber())
if _, err := p.round().Update(); err != nil {
if p.Round() != nil {
common.Logger.Debugf("party %s: %s round %d update", p.Round().Params().PartyID(), task, p.Round().RoundNumber())
if _, err := p.Round().Update(); err != nil {
return r(false, err)
}
if p.round().CanProceed() {
if p.advance(); p.round() != nil {
if err := p.round().Start(); err != nil {
if p.Round().CanProceed() {
if p.advance(); p.Round() != nil {
if err := p.Round().Start(); err != nil {
return r(false, err)
}
rndNum := p.round().RoundNumber()
common.Logger.Infof("party %s: %s round %d started", p.round().Params().PartyID(), task, rndNum)
rndNum := p.Round().RoundNumber()
common.Logger.Infof("party %s: %s round %d started", p.Round().Params().PartyID(), task, rndNum)
} else {
// finished! the round implementation will have sent the data through the `end` channel.
common.Logger.Infof("party %s: %s finished!", p.PartyID(), task)
@@ -195,24 +195,24 @@ func BaseUpdate(p Party, msg ParsedMessage, task string) (ok bool, err *Error) {
}
p.lock() // data is written to P state below
common.Logger.Debugf("party %s received message: %s", p.PartyID(), msg.String())
if p.round() != nil {
common.Logger.Debugf("party %s round %d update: %s", p.PartyID(), p.round().RoundNumber(), msg.String())
if p.Round() != nil {
common.Logger.Debugf("party %s round %d update: %s", p.PartyID(), p.Round().RoundNumber(), msg.String())
}
if ok, err := p.StoreMessage(msg); err != nil || !ok {
return r(false, err)
}
if p.round() != nil {
common.Logger.Debugf("party %s: %s round %d update", p.round().Params().PartyID(), task, p.round().RoundNumber())
if _, err := p.round().Update(); err != nil {
if p.Round() != nil {
common.Logger.Debugf("party %s: %s round %d update", p.Round().Params().PartyID(), task, p.Round().RoundNumber())
if _, err := p.Round().Update(); err != nil {
return r(false, err)
}
if p.round().CanProceed() {
if p.advance(); p.round() != nil {
if err := p.round().Start(); err != nil {
if p.Round().CanProceed() {
if p.advance(); p.Round() != nil {
if err := p.Round().Start(); err != nil {
return r(false, err)
}
rndNum := p.round().RoundNumber()
common.Logger.Infof("party %s: %s round %d started", p.round().Params().PartyID(), task, rndNum)
rndNum := p.Round().RoundNumber()
common.Logger.Infof("party %s: %s round %d started", p.Round().Params().PartyID(), task, rndNum)
} else {
// finished! the round implementation will have sent the data through the `end` channel.
common.Logger.Infof("party %s: %s finished!", p.PartyID(), task)