github.com/adecaro/fabric-ca@v2.0.0-alpha+incompatible/lib/server/idemix/issuercredential.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  	"io/ioutil"
    11  
    12  	"github.com/cloudflare/cfssl/log"
    13  	proto "github.com/golang/protobuf/proto"
    14  	"github.com/hyperledger/fabric-ca/util"
    15  	"github.com/hyperledger/fabric/idemix"
    16  	"github.com/pkg/errors"
    17  )
    18  
    19  const (
    20  	// AttrEnrollmentID is the attribute name for enrollment ID
    21  	AttrEnrollmentID = "EnrollmentID"
    22  	// AttrRole is the attribute name for role
    23  	AttrRole = "Role"
    24  	// AttrOU is the attribute name for OU
    25  	AttrOU = "OU"
    26  	// AttrRevocationHandle is the attribute name for revocation handle
    27  	AttrRevocationHandle = "RevocationHandle"
    28  )
    29  
    30  // IssuerCredential represents CA's Idemix credential
    31  type IssuerCredential interface {
    32  	// Load loads the CA's Idemix credential from the disk
    33  	Load() error
    34  	// Store stores the CA's Idemix credential to the disk
    35  	Store() error
    36  	// GetIssuerKey returns *idemix.IssuerKey that represents
    37  	// CA's Idemix public and secret key
    38  	GetIssuerKey() (*idemix.IssuerKey, error)
    39  	// SetIssuerKey sets issuer key
    40  	SetIssuerKey(key *idemix.IssuerKey)
    41  	// Returns new instance of idemix.IssuerKey
    42  	NewIssuerKey() (*idemix.IssuerKey, error)
    43  }
    44  
    45  // caIdemixCredential implements IssuerCredential interface
    46  type caIdemixCredential struct {
    47  	pubKeyFile    string
    48  	secretKeyFile string
    49  	issuerKey     *idemix.IssuerKey
    50  	idemixLib     Lib
    51  }
    52  
    53  // NewIssuerCredential returns an instance of an object that implements IssuerCredential interface
    54  func NewIssuerCredential(pubKeyFile, secretKeyFile string, lib Lib) IssuerCredential {
    55  	return &caIdemixCredential{
    56  		pubKeyFile:    pubKeyFile,
    57  		secretKeyFile: secretKeyFile,
    58  		idemixLib:     lib,
    59  	}
    60  }
    61  
    62  // Load loads the CA's Idemix public and private key from the location specified
    63  // by pubKeyFile and secretKeyFile attributes, respectively
    64  func (ic *caIdemixCredential) Load() error {
    65  	pubKeyBytes, err := ioutil.ReadFile(ic.pubKeyFile)
    66  	if err != nil {
    67  		return errors.Wrapf(err, "Failed to read Issuer public key")
    68  	}
    69  	if len(pubKeyBytes) == 0 {
    70  		return errors.New("Issuer public key file is empty")
    71  	}
    72  	pubKey := &idemix.IssuerPublicKey{}
    73  	err = proto.Unmarshal(pubKeyBytes, pubKey)
    74  	if err != nil {
    75  		return errors.Wrapf(err, "Failed to unmarshal Issuer public key bytes")
    76  	}
    77  	err = pubKey.Check()
    78  	if err != nil {
    79  		return errors.Wrapf(err, "Issuer public key check failed")
    80  	}
    81  	privKey, err := ioutil.ReadFile(ic.secretKeyFile)
    82  	if err != nil {
    83  		return errors.Wrapf(err, "Failed to read Issuer secret key")
    84  	}
    85  	if len(privKey) == 0 {
    86  		return errors.New("Issuer secret key file is empty")
    87  	}
    88  	ic.issuerKey = &idemix.IssuerKey{
    89  		Ipk: pubKey,
    90  		Isk: privKey,
    91  	}
    92  	//TODO: check if issuer key is valid by checking public and secret key pair
    93  	return nil
    94  }
    95  
    96  // Store stores the CA's Idemix public and private key to the location
    97  // specified by pubKeyFile and secretKeyFile attributes, respectively
    98  func (ic *caIdemixCredential) Store() error {
    99  	ik, err := ic.GetIssuerKey()
   100  	if err != nil {
   101  		return err
   102  	}
   103  
   104  	ipkBytes, err := proto.Marshal(ik.Ipk)
   105  	if err != nil {
   106  		return errors.New("Failed to marshal Issuer public key")
   107  	}
   108  
   109  	err = util.WriteFile(ic.pubKeyFile, ipkBytes, 0644)
   110  	if err != nil {
   111  		log.Errorf("Failed to store Issuer public key: %s", err.Error())
   112  		return errors.New("Failed to store Issuer public key")
   113  	}
   114  
   115  	err = util.WriteFile(ic.secretKeyFile, ik.Isk, 0644)
   116  	if err != nil {
   117  		log.Errorf("Failed to store Issuer secret key: %s", err.Error())
   118  		return errors.New("Failed to store Issuer secret key")
   119  	}
   120  
   121  	log.Infof("The issuer key was successfully stored. The public key is at: %s, secret key is at: %s",
   122  		ic.pubKeyFile, ic.secretKeyFile)
   123  	return nil
   124  }
   125  
   126  // GetIssuerKey returns idemix.IssuerKey object that is associated with
   127  // this CAIdemixCredential
   128  func (ic *caIdemixCredential) GetIssuerKey() (*idemix.IssuerKey, error) {
   129  	if ic.issuerKey == nil {
   130  		return nil, errors.New("Issuer credential is not set")
   131  	}
   132  	return ic.issuerKey, nil
   133  }
   134  
   135  // SetIssuerKey sets idemix.IssuerKey object
   136  func (ic *caIdemixCredential) SetIssuerKey(key *idemix.IssuerKey) {
   137  	ic.issuerKey = key
   138  }
   139  
   140  // NewIssuerKey creates new Issuer key
   141  func (ic *caIdemixCredential) NewIssuerKey() (*idemix.IssuerKey, error) {
   142  	rng, err := ic.idemixLib.GetRand()
   143  	if err != nil {
   144  		return nil, errors.Wrapf(err, "Error creating new issuer key")
   145  	}
   146  	// Currently, Idemix library supports these four attributes. The supported attribute names
   147  	// must also be known when creating issuer key. In the future, Idemix library will support
   148  	// arbitary attribute names, so removing the need to hardcode attribute names in the issuer
   149  	// key.
   150  	// OU - organization unit
   151  	// Role - if the user is admin or member
   152  	// EnrollmentID - enrollment ID of the user
   153  	// RevocationHandle - revocation handle of a credential
   154  	ik, err := ic.idemixLib.NewIssuerKey(GetAttributeNames(), rng)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	return ik, nil
   159  }
   160  
   161  // GetAttributeNames returns attribute names supported by the Fabric CA for Idemix credentials
   162  func GetAttributeNames() []string {
   163  	return []string{AttrOU, AttrRole, AttrEnrollmentID, AttrRevocationHandle}
   164  }