Skip to content

Commit

Permalink
fix mismatched solomachine signature data type verification (#7882)
Browse files Browse the repository at this point in the history
* fix mismatched signature data type verification

* update godoc

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
  • Loading branch information
colin-axner and fedekunze authored Nov 10, 2020
1 parent 0895a2a commit 0bd4657
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 14 deletions.
30 changes: 16 additions & 14 deletions x/ibc/light-clients/06-solomachine/types/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
62 changes: 62 additions & 0 deletions x/ibc/light-clients/06-solomachine/types/proof_test.go
Original file line number Diff line number Diff line change
@@ -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()

Expand Down

0 comments on commit 0bd4657

Please sign in to comment.