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