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 }