github.com/anjalikarhana/fabric@v2.1.1+incompatible/idemix/revocation_authority.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/elliptic"
    12  	"crypto/rand"
    13  	"crypto/sha256"
    14  	"encoding/asn1"
    15  	"math/big"
    16  
    17  	"github.com/golang/protobuf/proto"
    18  	"github.com/hyperledger/fabric-amcl/amcl"
    19  	"github.com/hyperledger/fabric-amcl/amcl/FP256BN"
    20  	"github.com/pkg/errors"
    21  )
    22  
    23  type RevocationAlgorithm int32
    24  
    25  const (
    26  	ALG_NO_REVOCATION RevocationAlgorithm = iota
    27  )
    28  
    29  var ProofBytes = map[RevocationAlgorithm]int{
    30  	ALG_NO_REVOCATION: 0,
    31  }
    32  
    33  // GenerateLongTermRevocationKey generates a long term signing key that will be used for revocation
    34  func GenerateLongTermRevocationKey() (*ecdsa.PrivateKey, error) {
    35  	return ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
    36  }
    37  
    38  // CreateCRI creates the Credential Revocation Information for a certain time period (epoch).
    39  // Users can use the CRI to prove that they are not revoked.
    40  // Note that when not using revocation (i.e., alg = ALG_NO_REVOCATION), the entered unrevokedHandles are not used,
    41  // and the resulting CRI can be used by any signer.
    42  func CreateCRI(key *ecdsa.PrivateKey, unrevokedHandles []*FP256BN.BIG, epoch int, alg RevocationAlgorithm, rng *amcl.RAND) (*CredentialRevocationInformation, error) {
    43  	if key == nil || rng == nil {
    44  		return nil, errors.Errorf("CreateCRI received nil input")
    45  	}
    46  	cri := &CredentialRevocationInformation{}
    47  	cri.RevocationAlg = int32(alg)
    48  	cri.Epoch = int64(epoch)
    49  
    50  	if alg == ALG_NO_REVOCATION {
    51  		// put a dummy PK in the proto
    52  		cri.EpochPk = Ecp2ToProto(GenG2)
    53  	} else {
    54  		// create epoch key
    55  		_, epochPk := WBBKeyGen(rng)
    56  		cri.EpochPk = Ecp2ToProto(epochPk)
    57  	}
    58  
    59  	// sign epoch + epoch key with long term key
    60  	bytesToSign, err := proto.Marshal(cri)
    61  	if err != nil {
    62  		return nil, errors.Wrap(err, "failed to marshal CRI")
    63  	}
    64  
    65  	digest := sha256.Sum256(bytesToSign)
    66  
    67  	cri.EpochPkSig, err = key.Sign(rand.Reader, digest[:], nil)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	if alg == ALG_NO_REVOCATION {
    73  		return cri, nil
    74  	} else {
    75  		return nil, errors.Errorf("the specified revocation algorithm is not supported.")
    76  	}
    77  }
    78  
    79  // VerifyEpochPK verifies that the revocation PK for a certain epoch is valid,
    80  // by checking that it was signed with the long term revocation key.
    81  // Note that even if we use no revocation (i.e., alg = ALG_NO_REVOCATION), we need
    82  // to verify the signature to make sure the issuer indeed signed that no revocation
    83  // is used in this epoch.
    84  func VerifyEpochPK(pk *ecdsa.PublicKey, epochPK *ECP2, epochPkSig []byte, epoch int, alg RevocationAlgorithm) error {
    85  	if pk == nil || epochPK == nil {
    86  		return errors.Errorf("EpochPK invalid: received nil input")
    87  	}
    88  	cri := &CredentialRevocationInformation{}
    89  	cri.RevocationAlg = int32(alg)
    90  	cri.EpochPk = epochPK
    91  	cri.Epoch = int64(epoch)
    92  	bytesToSign, err := proto.Marshal(cri)
    93  	if err != nil {
    94  		return err
    95  	}
    96  	digest := sha256.Sum256(bytesToSign)
    97  
    98  	var sig struct{ R, S *big.Int }
    99  	if _, err := asn1.Unmarshal(epochPkSig, &sig); err != nil {
   100  		return errors.Wrap(err, "failed unmashalling signature")
   101  	}
   102  
   103  	if !ecdsa.Verify(pk, digest[:], sig.R, sig.S) {
   104  		return errors.Errorf("EpochPKSig invalid")
   105  	}
   106  
   107  	return nil
   108  }