github.com/yimialmonte/fabric@v2.1.1+incompatible/bccsp/idemix/bridge/signaturescheme.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  package bridge
     7  
     8  import (
     9  	"crypto/ecdsa"
    10  
    11  	"github.com/golang/protobuf/proto"
    12  	"github.com/hyperledger/fabric-amcl/amcl"
    13  	"github.com/hyperledger/fabric-amcl/amcl/FP256BN"
    14  	"github.com/hyperledger/fabric/bccsp"
    15  	"github.com/hyperledger/fabric/bccsp/idemix/handlers"
    16  	cryptolib "github.com/hyperledger/fabric/idemix"
    17  	"github.com/pkg/errors"
    18  )
    19  
    20  // SignatureScheme encapsulates the idemix algorithms to sign and verify using an idemix credential.
    21  type SignatureScheme struct {
    22  	NewRand func() *amcl.RAND
    23  }
    24  
    25  // Sign produces an idemix-signature with the respect to the passed serialised credential (cred),
    26  // user secret key (sk), pseudonym public key (Nym) and secret key (RNym), issuer public key (ipk),
    27  // and attributes to be disclosed.
    28  func (s *SignatureScheme) Sign(cred []byte, sk handlers.Big, Nym handlers.Ecp, RNym handlers.Big, ipk handlers.IssuerPublicKey, attributes []bccsp.IdemixAttribute,
    29  	msg []byte, rhIndex int, criRaw []byte) (res []byte, err error) {
    30  	defer func() {
    31  		if r := recover(); r != nil {
    32  			res = nil
    33  			err = errors.Errorf("failure [%s]", r)
    34  		}
    35  	}()
    36  
    37  	isk, ok := sk.(*Big)
    38  	if !ok {
    39  		return nil, errors.Errorf("invalid user secret key, expected *Big, got [%T]", sk)
    40  	}
    41  	inym, ok := Nym.(*Ecp)
    42  	if !ok {
    43  		return nil, errors.Errorf("invalid nym public key, expected *Ecp, got [%T]", Nym)
    44  	}
    45  	irnym, ok := RNym.(*Big)
    46  	if !ok {
    47  		return nil, errors.Errorf("invalid nym secret key, expected *Big, got [%T]", RNym)
    48  	}
    49  	iipk, ok := ipk.(*IssuerPublicKey)
    50  	if !ok {
    51  		return nil, errors.Errorf("invalid issuer public key, expected *IssuerPublicKey, got [%T]", ipk)
    52  	}
    53  
    54  	credential := &cryptolib.Credential{}
    55  	err = proto.Unmarshal(cred, credential)
    56  	if err != nil {
    57  		return nil, errors.Wrap(err, "failed unmarshalling credential")
    58  	}
    59  
    60  	cri := &cryptolib.CredentialRevocationInformation{}
    61  	err = proto.Unmarshal(criRaw, cri)
    62  	if err != nil {
    63  		return nil, errors.Wrap(err, "failed unmarshalling credential revocation information")
    64  	}
    65  
    66  	disclosure := make([]byte, len(attributes))
    67  	for i := 0; i < len(attributes); i++ {
    68  		if attributes[i].Type == bccsp.IdemixHiddenAttribute {
    69  			disclosure[i] = 0
    70  		} else {
    71  			disclosure[i] = 1
    72  		}
    73  	}
    74  
    75  	sig, err := cryptolib.NewSignature(
    76  		credential,
    77  		isk.E,
    78  		inym.E,
    79  		irnym.E,
    80  		iipk.PK,
    81  		disclosure,
    82  		msg,
    83  		rhIndex,
    84  		cri,
    85  		s.NewRand())
    86  	if err != nil {
    87  		return nil, errors.WithMessage(err, "failed creating new signature")
    88  	}
    89  
    90  	return proto.Marshal(sig)
    91  }
    92  
    93  // Verify checks that an idemix signature is valid with the respect to the passed issuer public key, digest, attributes,
    94  // revocation index (rhIndex), revocation public key, and epoch.
    95  func (*SignatureScheme) Verify(ipk handlers.IssuerPublicKey, signature, digest []byte, attributes []bccsp.IdemixAttribute, rhIndex int, revocationPublicKey *ecdsa.PublicKey, epoch int) (err error) {
    96  	defer func() {
    97  		if r := recover(); r != nil {
    98  			err = errors.Errorf("failure [%s]", r)
    99  		}
   100  	}()
   101  
   102  	iipk, ok := ipk.(*IssuerPublicKey)
   103  	if !ok {
   104  		return errors.Errorf("invalid issuer public key, expected *IssuerPublicKey, got [%T]", ipk)
   105  	}
   106  
   107  	sig := &cryptolib.Signature{}
   108  	err = proto.Unmarshal(signature, sig)
   109  	if err != nil {
   110  		return err
   111  	}
   112  
   113  	disclosure := make([]byte, len(attributes))
   114  	attrValues := make([]*FP256BN.BIG, len(attributes))
   115  	for i := 0; i < len(attributes); i++ {
   116  		switch attributes[i].Type {
   117  		case bccsp.IdemixHiddenAttribute:
   118  			disclosure[i] = 0
   119  			attrValues[i] = nil
   120  		case bccsp.IdemixBytesAttribute:
   121  			disclosure[i] = 1
   122  			attrValues[i] = cryptolib.HashModOrder(attributes[i].Value.([]byte))
   123  		case bccsp.IdemixIntAttribute:
   124  			disclosure[i] = 1
   125  			attrValues[i] = FP256BN.NewBIGint(attributes[i].Value.(int))
   126  		default:
   127  			err = errors.Errorf("attribute type not allowed or supported [%v] at position [%d]", attributes[i].Type, i)
   128  		}
   129  	}
   130  	if err != nil {
   131  		return
   132  	}
   133  
   134  	return sig.Ver(
   135  		disclosure,
   136  		iipk.PK,
   137  		digest,
   138  		attrValues,
   139  		rhIndex,
   140  		revocationPublicKey,
   141  		epoch)
   142  }