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 }