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