github.com/lzy4123/fabric@v2.1.1+incompatible/bccsp/idemix/handlers/revocation.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 package handlers 7 8 import ( 9 "crypto/ecdsa" 10 "crypto/elliptic" 11 "crypto/sha256" 12 "crypto/x509" 13 "encoding/pem" 14 "fmt" 15 "reflect" 16 17 "github.com/hyperledger/fabric/bccsp" 18 "github.com/pkg/errors" 19 ) 20 21 // revocationSecretKey contains the revocation secret key 22 // and implements the bccsp.Key interface 23 type revocationSecretKey struct { 24 // sk is the idemix reference to the revocation key 25 privKey *ecdsa.PrivateKey 26 // exportable if true, sk can be exported via the Bytes function 27 exportable bool 28 } 29 30 func NewRevocationSecretKey(sk *ecdsa.PrivateKey, exportable bool) *revocationSecretKey { 31 return &revocationSecretKey{privKey: sk, exportable: exportable} 32 } 33 34 // Bytes converts this key to its byte representation, 35 // if this operation is allowed. 36 func (k *revocationSecretKey) Bytes() ([]byte, error) { 37 if k.exportable { 38 return k.privKey.D.Bytes(), nil 39 } 40 41 return nil, errors.New("not exportable") 42 } 43 44 // SKI returns the subject key identifier of this key. 45 func (k *revocationSecretKey) SKI() []byte { 46 // Marshall the public key 47 raw := elliptic.Marshal(k.privKey.Curve, k.privKey.PublicKey.X, k.privKey.PublicKey.Y) 48 49 // Hash it 50 hash := sha256.New() 51 hash.Write(raw) 52 return hash.Sum(nil) 53 } 54 55 // Symmetric returns true if this key is a symmetric key, 56 // false if this key is asymmetric 57 func (k *revocationSecretKey) Symmetric() bool { 58 return false 59 } 60 61 // Private returns true if this key is a private key, 62 // false otherwise. 63 func (k *revocationSecretKey) Private() bool { 64 return true 65 } 66 67 // PublicKey returns the corresponding public key part of an asymmetric public/private key pair. 68 // This method returns an error in symmetric key schemes. 69 func (k *revocationSecretKey) PublicKey() (bccsp.Key, error) { 70 return &revocationPublicKey{&k.privKey.PublicKey}, nil 71 } 72 73 type revocationPublicKey struct { 74 pubKey *ecdsa.PublicKey 75 } 76 77 func NewRevocationPublicKey(pubKey *ecdsa.PublicKey) *revocationPublicKey { 78 return &revocationPublicKey{pubKey: pubKey} 79 } 80 81 // Bytes converts this key to its byte representation, 82 // if this operation is allowed. 83 func (k *revocationPublicKey) Bytes() (raw []byte, err error) { 84 raw, err = x509.MarshalPKIXPublicKey(k.pubKey) 85 if err != nil { 86 return nil, fmt.Errorf("Failed marshalling key [%s]", err) 87 } 88 return 89 } 90 91 // SKI returns the subject key identifier of this key. 92 func (k *revocationPublicKey) SKI() []byte { 93 // Marshall the public key 94 raw := elliptic.Marshal(k.pubKey.Curve, k.pubKey.X, k.pubKey.Y) 95 96 // Hash it 97 hash := sha256.New() 98 hash.Write(raw) 99 return hash.Sum(nil) 100 } 101 102 // Symmetric returns true if this key is a symmetric key, 103 // false if this key is asymmetric 104 func (k *revocationPublicKey) Symmetric() bool { 105 return false 106 } 107 108 // Private returns true if this key is a private key, 109 // false otherwise. 110 func (k *revocationPublicKey) Private() bool { 111 return false 112 } 113 114 // PublicKey returns the corresponding public key part of an asymmetric public/private key pair. 115 // This method returns an error in symmetric key schemes. 116 func (k *revocationPublicKey) PublicKey() (bccsp.Key, error) { 117 return k, nil 118 } 119 120 // RevocationKeyGen generates revocation secret keys. 121 type RevocationKeyGen struct { 122 // exportable is a flag to allow an revocation secret key to be marked as exportable. 123 // If a secret key is marked as exportable, its Bytes method will return the key's byte representation. 124 Exportable bool 125 // Revocation implements the underlying cryptographic algorithms 126 Revocation Revocation 127 } 128 129 func (g *RevocationKeyGen) KeyGen(opts bccsp.KeyGenOpts) (bccsp.Key, error) { 130 // Create a new key pair 131 key, err := g.Revocation.NewKey() 132 if err != nil { 133 return nil, err 134 } 135 136 return &revocationSecretKey{exportable: g.Exportable, privKey: key}, nil 137 } 138 139 // RevocationPublicKeyImporter imports revocation public keys 140 type RevocationPublicKeyImporter struct { 141 } 142 143 func (i *RevocationPublicKeyImporter) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) { 144 der, ok := raw.([]byte) 145 if !ok { 146 return nil, errors.New("invalid raw, expected byte array") 147 } 148 149 if len(der) == 0 { 150 return nil, errors.New("invalid raw, it must not be nil") 151 } 152 153 blockPub, _ := pem.Decode(raw.([]byte)) 154 if blockPub == nil { 155 return nil, errors.New("Failed to decode revocation ECDSA public key") 156 } 157 revocationPk, err := x509.ParsePKIXPublicKey(blockPub.Bytes) 158 if err != nil { 159 return nil, errors.Wrap(err, "Failed to parse revocation ECDSA public key bytes") 160 } 161 ecdsaPublicKey, isECDSA := revocationPk.(*ecdsa.PublicKey) 162 if !isECDSA { 163 return nil, errors.Errorf("key is of type %v, not of type ECDSA", reflect.TypeOf(revocationPk)) 164 } 165 166 return &revocationPublicKey{ecdsaPublicKey}, nil 167 } 168 169 type CriSigner struct { 170 Revocation Revocation 171 } 172 173 func (s *CriSigner) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) ([]byte, error) { 174 revocationSecretKey, ok := k.(*revocationSecretKey) 175 if !ok { 176 return nil, errors.New("invalid key, expected *revocationSecretKey") 177 } 178 criOpts, ok := opts.(*bccsp.IdemixCRISignerOpts) 179 if !ok { 180 return nil, errors.New("invalid options, expected *IdemixCRISignerOpts") 181 } 182 183 return s.Revocation.Sign( 184 revocationSecretKey.privKey, 185 criOpts.UnrevokedHandles, 186 criOpts.Epoch, 187 criOpts.RevocationAlgorithm, 188 ) 189 } 190 191 type CriVerifier struct { 192 Revocation Revocation 193 } 194 195 func (v *CriVerifier) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (bool, error) { 196 revocationPublicKey, ok := k.(*revocationPublicKey) 197 if !ok { 198 return false, errors.New("invalid key, expected *revocationPublicKey") 199 } 200 criOpts, ok := opts.(*bccsp.IdemixCRISignerOpts) 201 if !ok { 202 return false, errors.New("invalid options, expected *IdemixCRISignerOpts") 203 } 204 if len(signature) == 0 { 205 return false, errors.New("invalid signature, it must not be empty") 206 } 207 208 err := v.Revocation.Verify( 209 revocationPublicKey.pubKey, 210 signature, 211 criOpts.Epoch, 212 criOpts.RevocationAlgorithm, 213 ) 214 if err != nil { 215 return false, err 216 } 217 218 return true, nil 219 }