github.com/canhui/fabric_ca2_2@v2.0.0-alpha+incompatible/lib/client/credential/x509/credential.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package x509 8 9 import ( 10 "encoding/hex" 11 "fmt" 12 "net/http" 13 14 "github.com/cloudflare/cfssl/log" 15 "github.com/hyperledger/fabric-ca/api" 16 "github.com/hyperledger/fabric-ca/lib/client/credential" 17 "github.com/hyperledger/fabric-ca/util" 18 "github.com/hyperledger/fabric/bccsp" 19 "github.com/pkg/errors" 20 ) 21 22 const ( 23 // CredType is the string that represents X509 credential type 24 CredType = "X509" 25 ) 26 27 // Client represents a client that will load/store an Idemix credential 28 type Client interface { 29 NewX509Identity(name string, creds []credential.Credential) Identity 30 GetCSP() bccsp.BCCSP 31 } 32 33 // Identity represents an identity 34 type Identity interface { 35 Revoke(req *api.RevocationRequest) (*api.RevocationResponse, error) 36 } 37 38 // Credential represents a X509 credential. Implements Credential interface 39 type Credential struct { 40 client Client 41 certFile string 42 keyFile string 43 val *Signer 44 } 45 46 // NewCredential is constructor for X509 Credential 47 func NewCredential(certFile, keyFile string, c Client) *Credential { 48 return &Credential{ 49 c, certFile, keyFile, nil, 50 } 51 } 52 53 // Type returns X509 54 func (cred *Credential) Type() string { 55 return CredType 56 } 57 58 // Val returns *Signer associated with this X509 credential 59 func (cred *Credential) Val() (interface{}, error) { 60 if cred.val == nil { 61 return nil, errors.New("X509 Credential value is not set") 62 } 63 return cred.val, nil 64 } 65 66 // EnrollmentID returns enrollment ID of this X509 credential 67 func (cred *Credential) EnrollmentID() (string, error) { 68 if cred.val == nil { 69 return "", errors.New("X509 Credential value is not set") 70 } 71 return cred.val.GetName(), nil 72 } 73 74 // SetVal sets *Signer for this X509 credential 75 func (cred *Credential) SetVal(val interface{}) error { 76 s, ok := val.(*Signer) 77 if !ok { 78 return errors.New("The X509 credential value must be of type *Signer for X509 credential") 79 } 80 cred.val = s 81 return nil 82 } 83 84 // Load loads the certificate and key from the location specified by 85 // certFile attribute using the BCCSP of the client. The private key is 86 // loaded from the location specified by the keyFile attribute, if the 87 // private key is not found in the keystore managed by BCCSP 88 func (cred *Credential) Load() error { 89 cert, err := util.ReadFile(cred.certFile) 90 if err != nil { 91 log.Debugf("No certificate found at %s", cred.certFile) 92 return err 93 } 94 csp := cred.getCSP() 95 key, _, _, err := util.GetSignerFromCertFile(cred.certFile, csp) 96 if err != nil { 97 // Fallback: attempt to read out of keyFile and import 98 log.Debugf("No key found in the BCCSP keystore, attempting fallback") 99 key, err = util.ImportBCCSPKeyFromPEM(cred.keyFile, csp, true) 100 if err != nil { 101 return errors.WithMessage(err, fmt.Sprintf("Could not find the private key in the BCCSP keystore nor in the keyfile %s", cred.keyFile)) 102 } 103 } 104 cred.val, err = NewSigner(key, cert) 105 if err != nil { 106 return err 107 } 108 return nil 109 } 110 111 // Store stores the certificate associated with this X509 credential to the location 112 // specified by certFile attribute 113 func (cred *Credential) Store() error { 114 if cred.val == nil { 115 return errors.New("X509 Credential value is not set") 116 } 117 err := util.WriteFile(cred.certFile, cred.val.Cert(), 0644) 118 if err != nil { 119 return errors.WithMessage(err, "Failed to store the certificate") 120 } 121 log.Infof("Stored client certificate at %s", cred.certFile) 122 return nil 123 } 124 125 // CreateToken creates token based on this X509 credential 126 func (cred *Credential) CreateToken(req *http.Request, reqBody []byte) (string, error) { 127 return util.CreateToken(cred.getCSP(), cred.val.certBytes, cred.val.key, req.Method, req.URL.RequestURI(), reqBody) 128 } 129 130 // RevokeSelf revokes this X509 credential 131 func (cred *Credential) RevokeSelf() (*api.RevocationResponse, error) { 132 name, err := cred.EnrollmentID() 133 if err != nil { 134 return nil, err 135 } 136 val := cred.val 137 serial := util.GetSerialAsHex(val.cert.SerialNumber) 138 aki := hex.EncodeToString(val.cert.AuthorityKeyId) 139 req := &api.RevocationRequest{ 140 Serial: serial, 141 AKI: aki, 142 } 143 144 id := cred.client.NewX509Identity(name, []credential.Credential{cred}) 145 return id.Revoke(req) 146 } 147 148 func (cred *Credential) getCSP() bccsp.BCCSP { 149 if cred.client != nil && cred.client.GetCSP() != nil { 150 return cred.client.GetCSP() 151 } 152 return util.GetDefaultBCCSP() 153 }