fix mismatched solomachine signature data type verification (#7882)

* fix mismatched signature data type verification

* update godoc

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
colin axnér 2020-11-10 21:37:10 +01:00 committed by GitHub
parent 0895a2ab92
commit 0bd46574f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 14 deletions

View File

@ -15,32 +15,34 @@ import (
// VerifySignature verifies if the the provided public key generated the signature
// over the given data. Single and Multi signature public keys are supported.
// The type of the signature data determines how the public key is used to
// verify the signature. An error is returned if signature verification fails
// or an invalid SignatureData type is provided.
// The signature data type must correspond to the public key type. An error is
// returned if signature verification fails or an invalid SignatureData type is
// provided.
func VerifySignature(pubKey cryptotypes.PubKey, signBytes []byte, sigData signing.SignatureData) error {
switch data := sigData.(type) {
case *signing.SingleSignatureData:
if !pubKey.VerifySignature(signBytes, data.Signature) {
return ErrSignatureVerificationFailed
}
case *signing.MultiSignatureData:
multiPK, ok := pubKey.(multisig.PubKey)
switch pubKey := pubKey.(type) {
case multisig.PubKey:
data, ok := sigData.(*signing.MultiSignatureData)
if !ok {
return sdkerrors.Wrapf(ErrSignatureVerificationFailed, "invalid pubkey type: expected %T, got %T", (multisig.PubKey)(nil), pubKey)
return sdkerrors.Wrapf(ErrSignatureVerificationFailed, "invalid signature data type, expected %T, got %T", (*signing.MultiSignatureData)(nil), data)
}
// The function supplied fulfills the VerifyMultisignature interface. No special
// adjustments need to be made to the sign bytes based on the sign mode.
if err := multiPK.VerifyMultisignature(func(signing.SignMode) ([]byte, error) {
if err := pubKey.VerifyMultisignature(func(signing.SignMode) ([]byte, error) {
return signBytes, nil
}, data); err != nil {
return err
}
default:
return sdkerrors.Wrapf(ErrSignatureVerificationFailed, "unsupported signature data type %T", data)
data, ok := sigData.(*signing.SingleSignatureData)
if !ok {
return sdkerrors.Wrapf(ErrSignatureVerificationFailed, "invalid signature data type, expected %T, got %T", (*signing.SingleSignatureData)(nil), data)
}
if !pubKey.VerifySignature(signBytes, data.Signature) {
return ErrSignatureVerificationFailed
}
}
return nil

View File

@ -1,10 +1,72 @@
package types_test
import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types"
solomachinetypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types"
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
)
func (suite *SoloMachineTestSuite) TestVerifySignature() {
cdc := suite.chainA.App.AppCodec()
signBytes := []byte("sign bytes")
singleSignature := suite.solomachine.GenerateSignature(signBytes)
singleSigData, err := solomachinetypes.UnmarshalSignatureData(cdc, singleSignature)
suite.Require().NoError(err)
multiSignature := suite.solomachineMulti.GenerateSignature(signBytes)
multiSigData, err := solomachinetypes.UnmarshalSignatureData(cdc, multiSignature)
suite.Require().NoError(err)
testCases := []struct {
name string
publicKey cryptotypes.PubKey
sigData signing.SignatureData
expPass bool
}{
{
"single signature with regular public key",
suite.solomachine.PublicKey,
singleSigData,
true,
},
{
"multi signature with multisig public key",
suite.solomachineMulti.PublicKey,
multiSigData,
true,
},
{
"single signature with multisig public key",
suite.solomachineMulti.PublicKey,
singleSigData,
false,
},
{
"multi signature with regular public key",
suite.solomachine.PublicKey,
multiSigData,
false,
},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
err := solomachinetypes.VerifySignature(tc.publicKey, signBytes, tc.sigData)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *SoloMachineTestSuite) TestClientStateSignBytes() {
cdc := suite.chainA.App.AppCodec()