-
Notifications
You must be signed in to change notification settings - Fork 0
/
credential.go
153 lines (134 loc) · 4.23 KB
/
credential.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package x509
import (
"encoding/hex"
"fmt"
"net/http"
"github.com/cloudflare/cfssl/log"
"github.com/hyperledger/fabric-ca/api"
"github.com/hyperledger/fabric-ca/lib/client/credential"
"github.com/hyperledger/fabric-ca/util"
"github.com/hyperledger/fabric/bccsp"
"github.com/pkg/errors"
)
const (
// CredType is the string that represents X509 credential type
CredType = "X509"
)
// Client represents a client that will load/store an Idemix credential
type Client interface {
NewX509Identity(name string, creds []credential.Credential) Identity
GetCSP() bccsp.BCCSP
}
// Identity represents an identity
type Identity interface {
Revoke(req *api.RevocationRequest) (*api.RevocationResponse, error)
}
// Credential represents a X509 credential. Implements Credential interface
type Credential struct {
client Client
certFile string
keyFile string
val *Signer
}
// NewCredential is constructor for X509 Credential
func NewCredential(certFile, keyFile string, c Client) *Credential {
return &Credential{
c, certFile, keyFile, nil,
}
}
// Type returns X509
func (cred *Credential) Type() string {
return CredType
}
// Val returns *Signer associated with this X509 credential
func (cred *Credential) Val() (interface{}, error) {
if cred.val == nil {
return nil, errors.New("X509 Credential value is not set")
}
return cred.val, nil
}
// EnrollmentID returns enrollment ID of this X509 credential
func (cred *Credential) EnrollmentID() (string, error) {
if cred.val == nil {
return "", errors.New("X509 Credential value is not set")
}
return cred.val.GetName(), nil
}
// SetVal sets *Signer for this X509 credential
func (cred *Credential) SetVal(val interface{}) error {
s, ok := val.(*Signer)
if !ok {
return errors.New("The X509 credential value must be of type *Signer for X509 credential")
}
cred.val = s
return nil
}
// Load loads the certificate and key from the location specified by
// certFile attribute using the BCCSP of the client. The private key is
// loaded from the location specified by the keyFile attribute, if the
// private key is not found in the keystore managed by BCCSP
func (cred *Credential) Load() error {
cert, err := util.ReadFile(cred.certFile)
if err != nil {
log.Debugf("No certificate found at %s", cred.certFile)
return err
}
csp := cred.getCSP()
key, _, _, err := util.GetSignerFromCertFile(cred.certFile, csp)
if err != nil {
// Fallback: attempt to read out of keyFile and import
log.Debugf("No key found in the BCCSP keystore, attempting fallback")
key, err = util.ImportBCCSPKeyFromPEM(cred.keyFile, csp, true)
if err != nil {
return errors.WithMessage(err, fmt.Sprintf("Could not find the private key in the BCCSP keystore nor in the keyfile %s", cred.keyFile))
}
}
cred.val, err = NewSigner(key, cert)
if err != nil {
return err
}
return nil
}
// Store stores the certificate associated with this X509 credential to the location
// specified by certFile attribute
func (cred *Credential) Store() error {
if cred.val == nil {
return errors.New("X509 Credential value is not set")
}
err := util.WriteFile(cred.certFile, cred.val.Cert(), 0644)
if err != nil {
return errors.WithMessage(err, "Failed to store the certificate")
}
log.Infof("Stored client certificate at %s", cred.certFile)
return nil
}
// CreateToken creates token based on this X509 credential
func (cred *Credential) CreateToken(req *http.Request, reqBody []byte) (string, error) {
return util.CreateToken(cred.getCSP(), cred.val.certBytes, cred.val.key, req.Method, req.URL.RequestURI(), reqBody)
}
// RevokeSelf revokes this X509 credential
func (cred *Credential) RevokeSelf() (*api.RevocationResponse, error) {
name, err := cred.EnrollmentID()
if err != nil {
return nil, err
}
val := cred.val
serial := util.GetSerialAsHex(val.cert.SerialNumber)
aki := hex.EncodeToString(val.cert.AuthorityKeyId)
req := &api.RevocationRequest{
Serial: serial,
AKI: aki,
}
id := cred.client.NewX509Identity(name, []credential.Credential{cred})
return id.Revoke(req)
}
func (cred *Credential) getCSP() bccsp.BCCSP {
if cred.client != nil && cred.client.GetCSP() != nil {
return cred.client.GetCSP()
}
return util.GetDefaultBCCSP()
}