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