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  }