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