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