diff --git a/pub_key.go b/pub_key.go index 54d1173eb..0c7f4663e 100644 --- a/pub_key.go +++ b/pub_key.go @@ -83,6 +83,11 @@ func (pubKey PubKeyEd25519) Bytes() []byte { } func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { + // unwrap if needed + if wrap, ok := sig_.(SignatureS); ok { + sig_ = wrap.Signature + } + // make sure we use the same algorithm to sign sig, ok := sig_.(SignatureEd25519) if !ok { return false @@ -155,14 +160,20 @@ func (pubKey PubKeySecp256k1) Bytes() []byte { } func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { - pub__, err := secp256k1.ParsePubKey(append([]byte{0x04}, pubKey[:]...), secp256k1.S256()) - if err != nil { - return false + // unwrap if needed + if wrap, ok := sig_.(SignatureS); ok { + sig_ = wrap.Signature } + // and assert same algorithm to sign and verify sig, ok := sig_.(SignatureSecp256k1) if !ok { return false } + + pub__, err := secp256k1.ParsePubKey(append([]byte{0x04}, pubKey[:]...), secp256k1.S256()) + if err != nil { + return false + } sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256()) if err != nil { return false diff --git a/signature.go b/signature.go index 3960088bd..fcef20a43 100644 --- a/signature.go +++ b/signature.go @@ -91,7 +91,7 @@ func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error { //------------------------------------- // Implements Signature -type SignatureSecp256k1 data.Bytes +type SignatureSecp256k1 []byte func (sig SignatureSecp256k1) Bytes() []byte { return wire.BinaryBytes(struct{ Signature }{sig}) @@ -108,3 +108,10 @@ func (sig SignatureSecp256k1) Equals(other Signature) bool { return false } } +func (p SignatureSecp256k1) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p) +} + +func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error { + return data.Encoder.Unmarshal((*[]byte)(p), enc) +} diff --git a/signature_test.go b/signature_test.go index 88c490f39..ac631eac5 100644 --- a/signature_test.go +++ b/signature_test.go @@ -1,11 +1,14 @@ package crypto import ( - "bytes" + "fmt" + "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/tendermint/ed25519" - "github.com/tendermint/go-wire" + data "github.com/tendermint/go-data" ) func TestSignAndValidateEd25519(t *testing.T) { @@ -56,68 +59,60 @@ func TestSignAndValidateSecp256k1(t *testing.T) { } } -func TestBinaryDecodeEd25519(t *testing.T) { - - privKey := GenPrivKeyEd25519() - pubKey := privKey.PubKey() - - msg := CRandBytes(128) - sig := privKey.Sign(msg) - t.Logf("msg: %X, sig: %X", msg, sig) - - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(struct{ Signature }{sig}, buf, n, err) - if *err != nil { - t.Fatalf("Failed to write Signature: %v", err) - } - - if len(buf.Bytes()) != ed25519.SignatureSize+1 { - // 1 byte TypeByte, 64 bytes signature bytes - t.Fatalf("Unexpected signature write size: %v", len(buf.Bytes())) - } - if buf.Bytes()[0] != SignatureTypeEd25519 { - t.Fatalf("Unexpected signature type byte") - } - - sigStruct := struct{ Signature }{} - sig2 := wire.ReadBinary(sigStruct, buf, 0, n, err) - if *err != nil { - t.Fatalf("Failed to read Signature: %v", err) - } - - // Test the signature - if !pubKey.VerifyBytes(msg, sig2.(struct{ Signature }).Signature.(SignatureEd25519)) { - t.Errorf("Account message signature verification failed") +func TestSignatureEncodings(t *testing.T) { + cases := []struct { + privKey PrivKeyS + sigSize int + sigType byte + sigName string + }{ + { + privKey: PrivKeyS{GenPrivKeyEd25519()}, + sigSize: ed25519.SignatureSize, + sigType: SignatureTypeEd25519, + sigName: SignatureNameEd25519, + }, + { + privKey: PrivKeyS{GenPrivKeySecp256k1()}, + sigSize: 0, // unknown + sigType: SignatureTypeSecp256k1, + sigName: SignatureNameSecp256k1, + }, } -} - -func TestBinaryDecodeSecp256k1(t *testing.T) { - - privKey := GenPrivKeySecp256k1() - pubKey := privKey.PubKey() - - msg := CRandBytes(128) - sig := privKey.Sign(msg) - t.Logf("msg: %X, sig: %X", msg, sig) - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(struct{ Signature }{sig}, buf, n, err) - if *err != nil { - t.Fatalf("Failed to write Signature: %v", err) - } - - if buf.Bytes()[0] != SignatureTypeSecp256k1 { - t.Fatalf("Unexpected signature type byte") - } - - sigStruct := struct{ Signature }{} - sig2 := wire.ReadBinary(sigStruct, buf, 0, n, err) - if *err != nil { - t.Fatalf("Failed to read Signature: %v", err) - } - - // Test the signature - if !pubKey.VerifyBytes(msg, sig2.(struct{ Signature }).Signature.(SignatureSecp256k1)) { - t.Errorf("Account message signature verification failed") + for _, tc := range cases { + // note we embed them from the beginning.... + pubKey := PubKeyS{tc.privKey.PubKey()} + + msg := CRandBytes(128) + sig := SignatureS{tc.privKey.Sign(msg)} + + // store as wire + bin, err := data.ToWire(sig) + require.Nil(t, err, "%+v", err) + if tc.sigSize != 0 { + assert.Equal(t, tc.sigSize+1, len(bin)) + } + assert.Equal(t, tc.sigType, bin[0]) + + // and back + sig2 := SignatureS{} + err = data.FromWire(bin, &sig2) + require.Nil(t, err, "%+v", err) + assert.EqualValues(t, sig, sig2) + assert.True(t, pubKey.VerifyBytes(msg, sig2)) + + // store as json + js, err := data.ToJSON(sig) + require.Nil(t, err, "%+v", err) + assert.True(t, strings.Contains(string(js), tc.sigName)) + fmt.Println(string(js)) + + // and back + sig3 := SignatureS{} + err = data.FromJSON(js, &sig3) + require.Nil(t, err, "%+v", err) + assert.EqualValues(t, sig, sig3) + assert.True(t, pubKey.VerifyBytes(msg, sig3)) } }