github.com/dddengyunjie/fabric-ca@v0.0.0-20190606043049-92df60ae2f0f/lib/server/idemix/revocationkey.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package idemix
     8  
     9  import (
    10  	"encoding/pem"
    11  	"io/ioutil"
    12  
    13  	"github.com/cloudflare/cfssl/log"
    14  	"github.com/hyperledger/fabric-ca/util"
    15  	"github.com/pkg/errors"
    16  	"github.com/tjfoc/gmsm/sm2"
    17  )
    18  
    19  // RevocationKey represents issuer revocation public and private key
    20  type RevocationKey interface {
    21  	// Load loads this revocation key from the disk
    22  	Load() error
    23  	// Store stores this revocation key to the disk
    24  	Store() error
    25  	// GetKey returns *sm2.PrivateKey that represents revocation public and private key pair
    26  	GetKey() *sm2.PrivateKey
    27  	// SetKey sets revocation public and private key
    28  	SetKey(key *sm2.PrivateKey)
    29  	// SetNewKey creates new revocation public and private key pair and sets them in this object
    30  	SetNewKey() error
    31  }
    32  
    33  // caIdemixRevocationKey implements RevocationKey interface
    34  type caIdemixRevocationKey struct {
    35  	pubKeyFile     string
    36  	privateKeyFile string
    37  	key            *sm2.PrivateKey
    38  	idemixLib      Lib
    39  }
    40  
    41  // NewRevocationKey returns an instance of an object that implements RevocationKey interface
    42  func NewRevocationKey(pubKeyFile, privateKeyFile string, lib Lib) RevocationKey {
    43  	return &caIdemixRevocationKey{
    44  		pubKeyFile:     pubKeyFile,
    45  		privateKeyFile: privateKeyFile,
    46  		idemixLib:      lib,
    47  	}
    48  }
    49  
    50  // Load loads the Issuer revocation public and private key from the location specified
    51  // by pubKeyFile and privateKeyFile attributes, respectively
    52  func (rk *caIdemixRevocationKey) Load() error {
    53  	pubKeyBytes, err := ioutil.ReadFile(rk.pubKeyFile)
    54  	if err != nil {
    55  		return errors.Wrapf(err, "Failed to read revocation public key from %s", rk.pubKeyFile)
    56  	}
    57  	if len(pubKeyBytes) == 0 {
    58  		return errors.New("Revocation public key file is empty")
    59  	}
    60  	privKey, err := ioutil.ReadFile(rk.privateKeyFile)
    61  	if err != nil {
    62  		return errors.Wrapf(err, "Failed to read revocation private key from %s", rk.privateKeyFile)
    63  	}
    64  	if len(privKey) == 0 {
    65  		return errors.New("Revocation private key file is empty")
    66  	}
    67  	pk, pubKey, err := DecodeKeys(privKey, pubKeyBytes)
    68  	if err != nil {
    69  		return errors.WithMessage(err, "Failed to decode revocation key")
    70  	}
    71  	pk.PublicKey = *pubKey
    72  	rk.key = pk
    73  	return nil
    74  }
    75  
    76  // Store stores the CA's Idemix public and private key to the location
    77  // specified by pubKeyFile and secretKeyFile attributes, respectively
    78  func (rk *caIdemixRevocationKey) Store() error {
    79  	pk := rk.GetKey()
    80  	if pk == nil {
    81  		return errors.New("Revocation key is not set")
    82  	}
    83  	pkBytes, pubKeyBytes, err := EncodeKeys(pk, &pk.PublicKey)
    84  	if err != nil {
    85  		return errors.WithMessage(err, "Failed to encode revocation public key")
    86  	}
    87  	err = util.WriteFile(rk.privateKeyFile, []byte(pkBytes), 0644)
    88  	if err != nil {
    89  		log.Errorf("Failed to store revocation private key: %s", err.Error())
    90  		return errors.Wrapf(err, "Failed to store revocation private key at %s", rk.privateKeyFile)
    91  	}
    92  
    93  	err = util.WriteFile(rk.pubKeyFile, []byte(pubKeyBytes), 0644)
    94  	if err != nil {
    95  		log.Errorf("Failed to store revocation public key: %s", err.Error())
    96  		return errors.Wrapf(err, "Failed to store revocation public key at %s", rk.pubKeyFile)
    97  	}
    98  
    99  	log.Infof("The revocation key was successfully stored. The public key is at: %s, private key is at: %s",
   100  		rk.pubKeyFile, rk.privateKeyFile)
   101  	return nil
   102  }
   103  
   104  // GetKey returns revocation key
   105  func (rk *caIdemixRevocationKey) GetKey() *sm2.PrivateKey {
   106  	return rk.key
   107  }
   108  
   109  // SetKey sets revocation key
   110  func (rk *caIdemixRevocationKey) SetKey(key *sm2.PrivateKey) {
   111  	rk.key = key
   112  }
   113  
   114  // SetNewKey creates new revocation key and sets it in this object
   115  func (rk *caIdemixRevocationKey) SetNewKey() (err error) {
   116  	rk.key, err = rk.idemixLib.GenerateLongTermRevocationKey()
   117  	return err
   118  }
   119  
   120  // EncodeKeys encodes ECDSA key pair to PEM encoding
   121  func EncodeKeys(privateKey *sm2.PrivateKey, publicKey *sm2.PublicKey) ([]byte, []byte, error) {
   122  	encodedPK, err := sm2.MarshalSm2UnecryptedPrivateKey(privateKey)
   123  	if err != nil {
   124  		return nil, nil, errors.Wrap(err, "Failed to encode ECDSA private key")
   125  	}
   126  	pemEncodedPK := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: encodedPK})
   127  
   128  	encodedPubKey, err := sm2.MarshalPKIXPublicKey(publicKey)
   129  	if err != nil {
   130  		return nil, nil, errors.Wrap(err, "Failed to encode ECDSA public key")
   131  	}
   132  	pemEncodedPubKey := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: encodedPubKey})
   133  	return pemEncodedPK, pemEncodedPubKey, nil
   134  }
   135  
   136  // DecodeKeys decodes ECDSA key pair that are pem encoded
   137  func DecodeKeys(pemEncodedPK, pemEncodedPubKey []byte) (*sm2.PrivateKey, *sm2.PublicKey, error) {
   138  	block, _ := pem.Decode(pemEncodedPK)
   139  	if block == nil {
   140  		return nil, nil, errors.New("Failed to decode ECDSA private key")
   141  	}
   142  	pk, err := sm2.ParsePKCS8UnecryptedPrivateKey(block.Bytes)
   143  	if err != nil {
   144  		return nil, nil, errors.Wrap(err, "Failed to parse ECDSA private key bytes")
   145  	}
   146  	blockPub, _ := pem.Decode(pemEncodedPubKey)
   147  	if blockPub == nil {
   148  		return nil, nil, errors.New("Failed to decode ECDSA public key")
   149  	}
   150  	key, err := sm2.ParsePKIXPublicKey(blockPub.Bytes)
   151  	if err != nil {
   152  		return nil, nil, errors.Wrap(err, "Failed to parse ECDSA public key bytes")
   153  	}
   154  	publicKey := key.(*sm2.PublicKey)
   155  
   156  	return pk, publicKey, nil
   157  }