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