Skip to content

Commit

Permalink
[FAB-8965] Resource Mgmt: Verify signature
Browse files Browse the repository at this point in the history
Change-Id: I9176dc573bd458ad5f84b0fbafaaaae400cac96f
Signed-off-by: Sandra Vrtikapa <sandra.vrtikapa@securekey.com>
  • Loading branch information
sandrask committed Mar 19, 2018
1 parent 406f79d commit 86817d7
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 74 deletions.
35 changes: 5 additions & 30 deletions pkg/client/channel/invoke/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@ SPDX-License-Identifier: Apache-2.0
package invoke

import (
"github.com/hyperledger/fabric-sdk-go/pkg/client/common/verifiers"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/util/errors/status"

"github.com/pkg/errors"

"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
)

//NewSignatureValidationHandler returns a handler that validates an endorsement
Expand Down Expand Up @@ -43,37 +40,15 @@ func (f *SignatureValidationHandler) Handle(requestContext *RequestContext, clie

func (f *SignatureValidationHandler) validate(txProposalResponse []*fab.TransactionProposalResponse, ctx *ClientContext) error {
for _, r := range txProposalResponse {
if r.ProposalResponse.GetResponse().Status != int32(common.Status_SUCCESS) {
return status.NewFromProposalResponse(r.ProposalResponse, r.Endorser)
}

if err := verifyProposalResponse(r.ProposalResponse, ctx); err != nil {
if err := verifyProposalResponse(r, ctx); err != nil {
return err
}
}

return nil
}

func verifyProposalResponse(res *pb.ProposalResponse, ctx *ClientContext) error {
if res.GetEndorsement() == nil {
return errors.Errorf("Missing endorsement in proposal response")
}
creatorID := res.GetEndorsement().Endorser

err := ctx.Membership.Validate(creatorID)
if err != nil {
return errors.WithMessage(err, "The creator certificate is not valid")
}

// check the signature against the endorser and payload hash
digest := append(res.GetPayload(), res.GetEndorsement().Endorser...)

// validate the signature
err = ctx.Membership.Verify(creatorID, digest, res.GetEndorsement().Signature)
if err != nil {
return errors.WithMessage(err, "The creator's signature over the proposal is not valid")
}

return nil
func verifyProposalResponse(res *fab.TransactionProposalResponse, ctx *ClientContext) error {
sv := &verifiers.Signature{Membership: ctx.Membership}
return sv.Verify(res)
}
59 changes: 59 additions & 0 deletions pkg/client/common/verifiers/signature.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

// Package verifiers provides various verifiers (e.g. signature)
package verifiers

import (
"github.com/hyperledger/fabric-sdk-go/pkg/common/logging"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/util/errors/status"
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
"github.com/pkg/errors"
)

var logger = logging.NewLogger("fabsdk/client")

// Signature verifies response signature
type Signature struct {
Membership fab.ChannelMembership
}

// Verify checks transaction proposal response
func (v *Signature) Verify(response *fab.TransactionProposalResponse) error {

if response.ProposalResponse.GetResponse().Status != int32(common.Status_SUCCESS) {
return status.NewFromProposalResponse(response.ProposalResponse, response.Endorser)
}

res := response.ProposalResponse

if res.GetEndorsement() == nil {
return errors.Errorf("Missing endorsement in proposal response")
}
creatorID := res.GetEndorsement().Endorser

err := v.Membership.Validate(creatorID)
if err != nil {
return errors.WithMessage(err, "The creator certificate is not valid")
}

// check the signature against the endorser and payload hash
digest := append(res.GetPayload(), res.GetEndorsement().Endorser...)

// validate the signature
err = v.Membership.Verify(creatorID, digest, res.GetEndorsement().Signature)
if err != nil {
return errors.WithMessage(err, "The creator's signature over the proposal is not valid")
}

return nil
}

// Match matches transaction proposal responses (empty for signature verifier)
func (v *Signature) Match(response []*fab.TransactionProposalResponse) error {
return nil
}
45 changes: 3 additions & 42 deletions pkg/client/ledger/ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/golang/protobuf/proto"

"github.com/hyperledger/fabric-sdk-go/pkg/client/common/verifiers"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/util/errors/status"
Expand All @@ -40,7 +41,7 @@ type Client struct {
ctx context.Channel
filter fab.TargetFilter
ledger *channel.Ledger
verifier *requestVerifier
verifier *verifiers.Signature
}

// mspFilter is default filter
Expand Down Expand Up @@ -78,7 +79,7 @@ func New(channelProvider context.ChannelProvider, opts ...ClientOption) (*Client
ledgerClient := Client{
ctx: channelContext,
ledger: ledger,
verifier: &requestVerifier{membership: membership},
verifier: &verifiers.Signature{Membership: membership},
}

for _, opt := range opts {
Expand Down Expand Up @@ -423,43 +424,3 @@ func shuffle(a []fab.Peer) {
a[i], a[j] = a[j], a[i]
}
}

type requestVerifier struct {
membership fab.ChannelMembership
}

// Verify checks transaction proposal response
func (v *requestVerifier) Verify(response *fab.TransactionProposalResponse) error {

if response.ProposalResponse.GetResponse().Status != int32(common.Status_SUCCESS) {
return status.NewFromProposalResponse(response.ProposalResponse, response.Endorser)
}

res := response.ProposalResponse

if res.GetEndorsement() == nil {
return errors.Errorf("Missing endorsement in proposal response")
}
creatorID := res.GetEndorsement().Endorser

err := v.membership.Validate(creatorID)
if err != nil {
return errors.WithMessage(err, "The creator certificate is not valid")
}

// check the signature against the endorser and payload hash
digest := append(res.GetPayload(), res.GetEndorsement().Endorser...)

// validate the signature
err = v.membership.Verify(creatorID, digest, res.GetEndorsement().Signature)
if err != nil {
return errors.WithMessage(err, "The creator's signature over the proposal is not valid")
}

return nil
}

// Match matches transaction proposal responses (empty)
func (v *requestVerifier) Match(response []*fab.TransactionProposalResponse) error {
return nil
}
29 changes: 27 additions & 2 deletions pkg/client/resmgmt/resmgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"os"
"time"

"github.com/hyperledger/fabric-sdk-go/pkg/client/common/verifiers"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp"
Expand Down Expand Up @@ -481,8 +482,18 @@ func (rc *Client) QueryInstantiatedChaincodes(channelID string, options ...Reque
reqCtx, cancel := rc.createRequestContext(opts, core.PeerResponse)
defer cancel()

// TODO: Should we move QueryInstantiatedChaincodes to ledger client
responses, err := l.QueryInstantiatedChaincodes(reqCtx, []fab.ProposalProcessor{target}, nil)
// Channel service membership is required to verify signature
channelService, err := rc.ctx.ChannelProvider().ChannelService(rc.ctx, channelID)
if err != nil {
return nil, errors.WithMessage(err, "Unable to get channel service")
}

membership, err := channelService.Membership()
if err != nil {
return nil, errors.WithMessage(err, "membership creation failed")
}

responses, err := l.QueryInstantiatedChaincodes(reqCtx, []fab.ProposalProcessor{target}, &verifiers.Signature{Membership: membership})
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -573,6 +584,20 @@ func (rc *Client) sendCCProposal(reqCtx reqContext.Context, ccProposalType chain
return errors.WithMessage(err, "sending deploy transaction proposal failed")
}

// Membership is required to verify signature
membership, err := channelService.Membership()
if err != nil {
return errors.WithMessage(err, "membership creation failed")
}

// Verify signature(s)
sv := &verifiers.Signature{Membership: membership}
for _, r := range txProposalResponse {
if err := sv.Verify(r); err != nil {
return errors.WithMessage(err, "Failed to verify signature")
}
}

eventService, err := channelService.EventService()
if err != nil {
return errors.WithMessage(err, "unable to get event service")
Expand Down

0 comments on commit 86817d7

Please sign in to comment.