Skip to content

Commit

Permalink
Merge pull request #284 from zargarzadehm/master
Browse files Browse the repository at this point in the history
fix signing issue if the message is leading with 0x00
  • Loading branch information
ZhAnGeek authored Jan 15, 2024
2 parents 87f7e12 + 6b92e7d commit c0de534
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 18 deletions.
11 changes: 9 additions & 2 deletions ecdsa/signing/finalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,21 @@ func (round *finalization) Start() *tss.Error {
round.data.S = padToLengthBytesInPlace(sumS.Bytes(), bitSizeInBytes)
round.data.Signature = append(round.data.R, round.data.S...)
round.data.SignatureRecovery = []byte{byte(recid)}
round.data.M = round.temp.m.Bytes()
if round.temp.fullBytesLen == 0 {
round.data.M = round.temp.m.Bytes()
} else {
var mBytes = make([]byte, round.temp.fullBytesLen)
round.temp.m.FillBytes(mBytes)
round.data.M = mBytes
}

pk := ecdsa.PublicKey{
Curve: round.Params().EC(),
X: round.key.ECDSAPub.X(),
Y: round.key.ECDSAPub.Y(),
}
ok := ecdsa.Verify(&pk, round.temp.m.Bytes(), round.temp.rx, sumS)

ok := ecdsa.Verify(&pk, round.data.M, round.temp.rx, sumS)
if !ok {
return round.WrapError(fmt.Errorf("signature verification failed"))
}
Expand Down
19 changes: 13 additions & 6 deletions ecdsa/signing/local_party.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,11 @@ type (
sigma,
keyDerivationDelta,
gamma *big.Int
cis []*big.Int
bigWs []*crypto.ECPoint
pointGamma *crypto.ECPoint
deCommit cmt.HashDeCommitment
fullBytesLen int
cis []*big.Int
bigWs []*crypto.ECPoint
pointGamma *crypto.ECPoint
deCommit cmt.HashDeCommitment

// round 2
betas, // return value of Bob_mid
Expand Down Expand Up @@ -105,8 +106,8 @@ func NewLocalParty(
key keygen.LocalPartySaveData,
out chan<- tss.Message,
end chan<- *common.SignatureData,
) tss.Party {
return NewLocalPartyWithKDD(msg, params, key, nil, out, end)
fullBytesLen ...int) tss.Party {
return NewLocalPartyWithKDD(msg, params, key, nil, out, end, fullBytesLen...)
}

// NewLocalPartyWithKDD returns a party with key derivation delta for HD support
Expand All @@ -117,6 +118,7 @@ func NewLocalPartyWithKDD(
keyDerivationDelta *big.Int,
out chan<- tss.Message,
end chan<- *common.SignatureData,
fullBytesLen ...int,
) tss.Party {
partyCount := len(params.Parties().IDs())
p := &LocalParty{
Expand All @@ -142,6 +144,11 @@ func NewLocalPartyWithKDD(
// temp data init
p.temp.keyDerivationDelta = keyDerivationDelta
p.temp.m = msg
if len(fullBytesLen) > 0 {
p.temp.fullBytesLen = fullBytesLen[0]
} else {
p.temp.fullBytesLen = 0
}
p.temp.cis = make([]*big.Int, partyCount)
p.temp.bigWs = make([]*crypto.ECPoint, partyCount)
p.temp.betas = make([]*big.Int, partyCount)
Expand Down
100 changes: 97 additions & 3 deletions ecdsa/signing/local_party_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package signing
import (
"crypto/ecdsa"
"crypto/rand"
"encoding/hex"
"fmt"
"math/big"
"runtime"
Expand Down Expand Up @@ -56,11 +57,9 @@ func TestE2EConcurrent(t *testing.T) {
endCh := make(chan *common.SignatureData, len(signPIDs))

updater := test.SharedPartyUpdater

// init the parties
for i := 0; i < len(signPIDs); i++ {
params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold)

P := NewLocalParty(big.NewInt(42), params, keys[i], outCh, endCh).(*LocalParty)
parties = append(parties, P)
go func(P *LocalParty) {
Expand Down Expand Up @@ -132,6 +131,101 @@ signing:
}
}

func TestE2EConcurrentWithLeadingZeroInMSG(t *testing.T) {
setUp("info")
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 := test.SharedPartyUpdater
msgData, _ := hex.DecodeString("00f163ee51bcaeff9cdff5e0e3c1a646abd19885fffbab0b3b4236e0cf95c9f5")
// init the parties
for i := 0; i < len(signPIDs); i++ {
params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold)
P := NewLocalParty(new(big.Int).SetBytes(msgData), params, keys[i], outCh, endCh, len(msgData)).(*LocalParty)
parties = append(parties, P)
go func(P *LocalParty) {
if err := P.Start(); err != nil {
errCh <- err
}
}(P)
}

var ended int32
signing:
for {
fmt.Printf("ACTIVE GOROUTINES: %d\n", runtime.NumGoroutine())
select {
case err := <-errCh:
common.Logger.Errorf("Error: %s", err)
assert.FailNow(t, err.Error())
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, 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, errCh)
}

case <-endCh:
atomic.AddInt32(&ended, 1)
if atomic.LoadInt32(&ended) == int32(len(signPIDs)) {
t.Logf("Done. Received signature data from %d participants", ended)
R := parties[0].temp.bigR
r := parties[0].temp.rx
fmt.Printf("sign result: R(%s, %s), r=%s\n", R.X().String(), R.Y().String(), r.String())

modN := common.ModInt(tss.S256().Params().N)

// BEGIN check s correctness
sumS := big.NewInt(0)
for _, p := range parties {
sumS = modN.Add(sumS, p.temp.si)
}
fmt.Printf("S: %s\n", sumS.String())
// END check s correctness

// BEGIN ECDSA verify
pkX, pkY := keys[0].ECDSAPub.X(), keys[0].ECDSAPub.Y()
pk := ecdsa.PublicKey{
Curve: tss.EC(),
X: pkX,
Y: pkY,
}
ok := ecdsa.Verify(&pk, msgData, R.X(), sumS)
assert.True(t, ok, "ecdsa verify must pass")
t.Log("ECDSA signing test done.")
// END ECDSA verify

break signing
}
}
}
}

func TestE2EWithHDKeyDerivation(t *testing.T) {
setUp("info")
threshold := testThreshold
Expand Down Expand Up @@ -170,7 +264,7 @@ func TestE2EWithHDKeyDerivation(t *testing.T) {
for i := 0; i < len(signPIDs); i++ {
params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold)

P := NewLocalPartyWithKDD(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh).(*LocalParty)
P := NewLocalPartyWithKDD(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh, 0).(*LocalParty)
parties = append(parties, P)
go func(P *LocalParty) {
if err := P.Start(); err != nil {
Expand Down
13 changes: 9 additions & 4 deletions eddsa/signing/finalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import (
"math/big"

"github.com/agl/ed25519/edwards25519"
"github.com/decred/dcrd/dcrec/edwards/v2"

"github.com/bnb-chain/tss-lib/v2/tss"
"github.com/decred/dcrd/dcrec/edwards/v2"
)

func (round *finalization) Start() *tss.Error {
Expand Down Expand Up @@ -43,15 +42,21 @@ func (round *finalization) Start() *tss.Error {
round.data.Signature = append(bigIntToEncodedBytes(round.temp.r)[:], sumS[:]...)
round.data.R = round.temp.r.Bytes()
round.data.S = s.Bytes()
round.data.M = round.temp.m.Bytes()
if round.temp.fullBytesLen == 0 {
round.data.M = round.temp.m.Bytes()
} else {
var mBytes = make([]byte, round.temp.fullBytesLen)
round.temp.m.FillBytes(mBytes)
round.data.M = mBytes
}

pk := edwards.PublicKey{
Curve: round.Params().EC(),
X: round.key.EDDSAPub.X(),
Y: round.key.EDDSAPub.Y(),
}

ok := edwards.Verify(&pk, round.temp.m.Bytes(), round.temp.r, s)
ok := edwards.Verify(&pk, round.data.M, round.temp.r, s)
if !ok {
return round.WrapError(fmt.Errorf("signature verification failed"))
}
Expand Down
11 changes: 9 additions & 2 deletions eddsa/signing/local_party.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ type (
wi,
m,
ri *big.Int
pointRi *crypto.ECPoint
deCommit cmt.HashDeCommitment
fullBytesLen int
pointRi *crypto.ECPoint
deCommit cmt.HashDeCommitment

// round 2
cjs []*big.Int
Expand All @@ -71,6 +72,7 @@ func NewLocalParty(
key keygen.LocalPartySaveData,
out chan<- tss.Message,
end chan<- *common.SignatureData,
fullBytesLen ...int,
) tss.Party {
partyCount := len(params.Parties().IDs())
p := &LocalParty{
Expand All @@ -89,6 +91,11 @@ func NewLocalParty(

// temp data init
p.temp.m = msg
if len(fullBytesLen) > 0 {
p.temp.fullBytesLen = fullBytesLen[0]
} else {
p.temp.fullBytesLen = 0
}
p.temp.cjs = make([]*big.Int, partyCount)
return p
}
Expand Down
106 changes: 106 additions & 0 deletions eddsa/signing/local_party_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package signing

import (
"encoding/hex"
"fmt"
"math/big"
"sync/atomic"
Expand Down Expand Up @@ -142,3 +143,108 @@ signing:
}
}
}

func TestE2EConcurrentWithLeadingZeroInMSG(t *testing.T) {
setUp("info")

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

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 := test.SharedPartyUpdater

msg, _ := hex.DecodeString("00f163ee51bcaeff9cdff5e0e3c1a646abd19885fffbab0b3b4236e0cf95c9f5")
// init the parties
for i := 0; i < len(signPIDs); i++ {
params := tss.NewParameters(tss.Edwards(), p2pCtx, signPIDs[i], len(signPIDs), threshold)
P := NewLocalParty(new(big.Int).SetBytes(msg), params, keys[i], outCh, endCh, len(msg)).(*LocalParty)
parties = append(parties, P)
go func(P *LocalParty) {
if err := P.Start(); err != nil {
errCh <- err
}
}(P)
}

var ended int32
signing:
for {
select {
case err := <-errCh:
common.Logger.Errorf("Error: %s", err)
assert.FailNow(t, err.Error())
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, 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, errCh)
}

case <-endCh:
atomic.AddInt32(&ended, 1)
if atomic.LoadInt32(&ended) == int32(len(signPIDs)) {
t.Logf("Done. Received signature data from %d participants", ended)
R := parties[0].temp.r

// BEGIN check s correctness
sumS := parties[0].temp.si
for i, p := range parties {
if i == 0 {
continue
}

var tmpSumS [32]byte
edwards25519.ScMulAdd(&tmpSumS, sumS, bigIntToEncodedBytes(big.NewInt(1)), p.temp.si)
sumS = &tmpSumS
}
fmt.Printf("S: %s\n", encodedBytesToBigInt(sumS).String())
fmt.Printf("R: %s\n", R.String())
// END check s correctness

// BEGIN EDDSA verify
pkX, pkY := keys[0].EDDSAPub.X(), keys[0].EDDSAPub.Y()
pk := edwards.PublicKey{
Curve: tss.Edwards(),
X: pkX,
Y: pkY,
}

newSig, err := edwards.ParseSignature(parties[0].data.Signature)
if err != nil {
println("new sig error, ", err.Error())
}

ok := edwards.Verify(&pk, msg, newSig.R, newSig.S)
assert.True(t, ok, "eddsa verify must pass")
t.Log("EDDSA signing test done.")
// END EDDSA verify

break signing
}
}
}
}
Loading

0 comments on commit c0de534

Please sign in to comment.