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  }