Skip to content

Commit b847a66

Browse files
committed
crypto: add test recovery of pubkey from signature
1 parent b795f4f commit b847a66

File tree

2 files changed

+76
-7
lines changed

2 files changed

+76
-7
lines changed

crypto/ecrecover.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2017 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package crypto
18+
19+
import (
20+
"github.com/btcsuite/btcd/btcec/v2"
21+
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
22+
)
23+
24+
// Ecrecover returns the uncompressed public key that created the given signature.
25+
func Ecrecover(hash, sig []byte) ([]byte, error) {
26+
pub, err := sigToPub(hash, sig)
27+
if err != nil {
28+
return nil, err
29+
}
30+
var x, y btcec.FieldVal
31+
x.SetByteSlice(pub.X().Bytes())
32+
y.SetByteSlice(pub.Y().Bytes())
33+
btcecPub := btcec.NewPublicKey(&x, &y)
34+
bytes := btcecPub.SerializeUncompressed()
35+
return bytes, err
36+
}
37+
38+
// sigToPub returns the public key that created the given signature.
39+
func sigToPub(hash, sig []byte) (*btcec.PublicKey, error) {
40+
// Convert to btcec input format with 'recovery id' v at the beginning.
41+
btcsig := make([]byte, 65)
42+
btcsig[0] = sig[64] + 27
43+
copy(btcsig[1:], sig)
44+
45+
pub, _, err := ecdsa.RecoverCompact(btcsig, hash)
46+
return pub, err
47+
}

ecdsa/signing/local_party_test.go

+29-7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package signing
88

99
import (
10+
"bytes"
1011
"crypto/ecdsa"
1112
"fmt"
1213
"runtime"
@@ -40,6 +41,10 @@ const (
4041
victimPartySimulatingAbort = 1
4142
)
4243

44+
var (
45+
msg = big.NewInt(42)
46+
)
47+
4348
func setUp(level string) {
4449
if err := log.SetLogLevel("tss-lib", level); err != nil {
4550
panic(err)
@@ -77,7 +82,7 @@ func TestE2EConcurrent(t *testing.T) {
7782
params, _ := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold)
7883

7984
keyDerivationDelta := big.NewInt(0)
80-
P_, errP := NewLocalParty(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
85+
P_, errP := NewLocalParty(msg, params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
8186
if errP != nil {
8287
t.Errorf("error %v", errP)
8388
t.FailNow()
@@ -123,7 +128,7 @@ signing:
123128
// P = ...... with dtemp
124129
// P.start
125130

126-
case <-endCh:
131+
case end := <-endCh:
127132
atomic.AddInt32(&ended, 1)
128133
if atomic.LoadInt32(&ended) == int32(len(signPIDs)) {
129134
t.Logf("Done. Received signature data from %d participants", ended)
@@ -148,7 +153,24 @@ signing:
148153
X: pkX,
149154
Y: pkY,
150155
}
151-
ok := ecdsa.Verify(&pk, big.NewInt(42).Bytes(), R.X(), sumS)
156+
157+
r, s, v := end.R, end.S, end.SignatureRecovery
158+
sig := make([]byte, 65)
159+
copy(sig[32-len(r):32], r)
160+
copy(sig[64-len(s):64], s)
161+
sig[64] = v[0] & 0x01
162+
163+
expPub := keys[0].ECDSAPub.ToBtcecPubKey().SerializeUncompressed()
164+
165+
gotPub, err2 := crypto.Ecrecover(msg.Bytes(), sig)
166+
if !assert.NoError(t, err2) {
167+
return
168+
}
169+
if !bytes.Equal(expPub, gotPub) {
170+
t.Fatalf("recovered key did not match the expected one")
171+
}
172+
173+
ok := ecdsa.Verify(&pk, msg.Bytes(), R.X(), sumS)
152174
assert.True(t, ok, "ecdsa verify must pass")
153175
t.Log("ECDSA signing test done.")
154176
// END ECDSA verify
@@ -200,7 +222,7 @@ func TestE2EWithHDKeyDerivation(t *testing.T) {
200222
for i := 0; i < len(signPIDs); i++ {
201223
params, _ := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold)
202224

203-
P_, _ := NewLocalParty(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
225+
P_, _ := NewLocalParty(msg, params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
204226
P := P_.(*LocalParty)
205227
parties = append(parties, P)
206228
go func(P *LocalParty) {
@@ -260,7 +282,7 @@ signing:
260282
X: pkX,
261283
Y: pkY,
262284
}
263-
ok := ecdsa.Verify(&pk, big.NewInt(42).Bytes(), R.X(), sumS)
285+
ok := ecdsa.Verify(&pk, msg.Bytes(), R.X(), sumS)
264286
assert.True(t, ok, "ecdsa verify must pass")
265287
t.Log("ECDSA signing test done.")
266288
// END ECDSA verify
@@ -396,7 +418,7 @@ func TestAbortIdentification(t *testing.T) {
396418
params, _ := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold)
397419

398420
keyDerivationDelta := big.NewInt(0)
399-
P_, _ := NewLocalParty(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
421+
P_, _ := NewLocalParty(msg, params, keys[i], keyDerivationDelta, outCh, endCh, sessionId)
400422
P := P_.(*LocalParty)
401423
parties = append(parties, P)
402424
go func(P *LocalParty) {
@@ -653,7 +675,7 @@ func TestTooManyParties(t *testing.T) {
653675

654676
var err error
655677
var void keygen.LocalPartySaveData
656-
_, err = NewLocalParty(big.NewInt(42), params, void, big.NewInt(0), nil, nil, sessionId)
678+
_, err = NewLocalParty(msg, params, void, big.NewInt(0), nil, nil, sessionId)
657679
if !assert.Error(t, err) {
658680
t.FailNow()
659681
return

0 commit comments

Comments
 (0)