/
signature.go
109 lines (90 loc) · 3.46 KB
/
signature.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
// Package verifier provides various verifier (e.g. signature)
package verifier
import (
"crypto/x509"
"time"
"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/bccsp/utils"
"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/status"
"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/third_party/github.com/hyperledger/fabric/protos/common"
"github.com/pkg/errors"
)
const loggerModule = "fabsdk/client"
var logger = logging.NewLogger(loggerModule)
// 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) || response.ProposalResponse.GetResponse().Status >= int32(common.Status_BAD_REQUEST) {
return status.NewFromProposalResponse(response.ProposalResponse, response.Endorser)
}
res := response.ProposalResponse
if res.GetEndorsement() == nil {
return errors.WithStack(status.New(status.EndorserClientStatus, status.MissingEndorsement.ToInt32(), "missing endorsement in proposal response", nil))
}
creatorID := res.GetEndorsement().Endorser
err := v.Membership.Validate(creatorID)
if err != nil {
return errors.WithStack(status.New(status.EndorserClientStatus, status.SignatureVerificationFailed.ToInt32(), "the creator certificate is not valid", []interface{}{err.Error()}))
}
// 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.WithStack(status.New(status.EndorserClientStatus, status.SignatureVerificationFailed.ToInt32(), "the creator's signature over the proposal is not valid", []interface{}{err.Error()}))
}
return nil
}
// Match matches transaction proposal responses (empty for signature verifier)
func (v *Signature) Match(response []*fab.TransactionProposalResponse) error {
return nil
}
//ValidateCertificateDates used to verify if certificate was expired or not valid until later date
func ValidateCertificateDates(cert *x509.Certificate) error {
if cert == nil {
return nil
}
if time.Now().UTC().Before(cert.NotBefore) {
return errors.New("Certificate provided is not valid until later date")
}
if time.Now().UTC().After(cert.NotAfter) {
return errors.New("Certificate provided has expired")
}
return nil
}
//VerifyPeerCertificate verifies raw certs and chain certs for expiry and not yet valid dates
func VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
for _, chaincert := range rawCerts {
cert, err := utils.DERToX509Certificate(chaincert)
if err != nil {
logger.Warn("Got error while verifying cert")
}
if cert != nil {
err = ValidateCertificateDates(cert)
if err != nil {
//cert is expired or not valid
logger.Warn(err.Error())
return err
}
}
}
for _, certs := range verifiedChains {
for _, cert := range certs {
err := ValidateCertificateDates(cert)
if err != nil {
//cert is expired or not valid
logger.Warn(err.Error())
return err
}
}
}
return nil
}