Skip to content

Commit

Permalink
crypto: add test recovery of pubkey from signature
Browse files Browse the repository at this point in the history
  • Loading branch information
notatestuser committed Oct 21, 2022
1 parent b795f4f commit b847a66
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 7 deletions.
47 changes: 47 additions & 0 deletions crypto/ecrecover.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package crypto

import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
)

// Ecrecover returns the uncompressed public key that created the given signature.
func Ecrecover(hash, sig []byte) ([]byte, error) {
pub, err := sigToPub(hash, sig)
if err != nil {
return nil, err
}
var x, y btcec.FieldVal
x.SetByteSlice(pub.X().Bytes())
y.SetByteSlice(pub.Y().Bytes())
btcecPub := btcec.NewPublicKey(&x, &y)
bytes := btcecPub.SerializeUncompressed()
return bytes, err
}

// sigToPub returns the public key that created the given signature.
func sigToPub(hash, sig []byte) (*btcec.PublicKey, error) {
// Convert to btcec input format with 'recovery id' v at the beginning.
btcsig := make([]byte, 65)
btcsig[0] = sig[64] + 27
copy(btcsig[1:], sig)

pub, _, err := ecdsa.RecoverCompact(btcsig, hash)
return pub, err
}
36 changes: 29 additions & 7 deletions ecdsa/signing/local_party_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package signing

import (
"bytes"
"crypto/ecdsa"
"fmt"
"runtime"
Expand Down Expand Up @@ -40,6 +41,10 @@ const (
victimPartySimulatingAbort = 1
)

var (
msg = big.NewInt(42)
)

func setUp(level string) {
if err := log.SetLogLevel("tss-lib", level); err != nil {
panic(err)
Expand Down Expand Up @@ -77,7 +82,7 @@ func TestE2EConcurrent(t *testing.T) {
params, _ := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold)

keyDerivationDelta := big.NewInt(0)
P_, errP := NewLocalParty(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
P_, errP := NewLocalParty(msg, params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
if errP != nil {
t.Errorf("error %v", errP)
t.FailNow()
Expand Down Expand Up @@ -123,7 +128,7 @@ signing:
// P = ...... with dtemp
// P.start

case <-endCh:
case end := <-endCh:
atomic.AddInt32(&ended, 1)
if atomic.LoadInt32(&ended) == int32(len(signPIDs)) {
t.Logf("Done. Received signature data from %d participants", ended)
Expand All @@ -148,7 +153,24 @@ signing:
X: pkX,
Y: pkY,
}
ok := ecdsa.Verify(&pk, big.NewInt(42).Bytes(), R.X(), sumS)

r, s, v := end.R, end.S, end.SignatureRecovery
sig := make([]byte, 65)
copy(sig[32-len(r):32], r)
copy(sig[64-len(s):64], s)
sig[64] = v[0] & 0x01

expPub := keys[0].ECDSAPub.ToBtcecPubKey().SerializeUncompressed()

gotPub, err2 := crypto.Ecrecover(msg.Bytes(), sig)
if !assert.NoError(t, err2) {
return
}
if !bytes.Equal(expPub, gotPub) {
t.Fatalf("recovered key did not match the expected one")
}

ok := ecdsa.Verify(&pk, msg.Bytes(), R.X(), sumS)
assert.True(t, ok, "ecdsa verify must pass")
t.Log("ECDSA signing test done.")
// END ECDSA verify
Expand Down Expand Up @@ -200,7 +222,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_, _ := NewLocalParty(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
P_, _ := NewLocalParty(msg, params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
P := P_.(*LocalParty)
parties = append(parties, P)
go func(P *LocalParty) {
Expand Down Expand Up @@ -260,7 +282,7 @@ signing:
X: pkX,
Y: pkY,
}
ok := ecdsa.Verify(&pk, big.NewInt(42).Bytes(), R.X(), sumS)
ok := ecdsa.Verify(&pk, msg.Bytes(), R.X(), sumS)
assert.True(t, ok, "ecdsa verify must pass")
t.Log("ECDSA signing test done.")
// END ECDSA verify
Expand Down Expand Up @@ -396,7 +418,7 @@ func TestAbortIdentification(t *testing.T) {
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, sessionId)
P_, _ := NewLocalParty(msg, params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
P := P_.(*LocalParty)
parties = append(parties, P)
go func(P *LocalParty) {
Expand Down Expand Up @@ -653,7 +675,7 @@ func TestTooManyParties(t *testing.T) {

var err error
var void keygen.LocalPartySaveData
_, err = NewLocalParty(big.NewInt(42), params, void, big.NewInt(0), nil, nil, sessionId)
_, err = NewLocalParty(msg, params, void, big.NewInt(0), nil, nil, sessionId)
if !assert.Error(t, err) {
t.FailNow()
return
Expand Down

0 comments on commit b847a66

Please sign in to comment.