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