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 }