github.com/lzy4123/fabric@v2.1.1+incompatible/bccsp/idemix/bridge/credential.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 "bytes" 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 // Credential encapsulates the idemix algorithms to produce (sign) a credential 21 // and verify it. Recall that a credential is produced by the Issuer upon a credential request, 22 // and it is verified by the requester. 23 type Credential struct { 24 NewRand func() *amcl.RAND 25 } 26 27 // Sign produces an idemix credential. It takes in input the issuer secret key, 28 // a serialised credential request, and a list of attribute values. 29 // Notice that attributes should not contain attributes whose type is IdemixHiddenAttribute 30 // cause the credential needs to carry all the attribute values. 31 func (c *Credential) Sign(key handlers.IssuerSecretKey, credentialRequest []byte, attributes []bccsp.IdemixAttribute) (res []byte, err error) { 32 defer func() { 33 if r := recover(); r != nil { 34 res = nil 35 err = errors.Errorf("failure [%s]", r) 36 } 37 }() 38 39 iisk, ok := key.(*IssuerSecretKey) 40 if !ok { 41 return nil, errors.Errorf("invalid issuer secret key, expected *Big, got [%T]", key) 42 } 43 44 cr := &cryptolib.CredRequest{} 45 err = proto.Unmarshal(credentialRequest, cr) 46 if err != nil { 47 return nil, errors.Wrap(err, "failed unmarshalling credential request") 48 } 49 50 attrValues := make([]*FP256BN.BIG, len(attributes)) 51 for i := 0; i < len(attributes); i++ { 52 switch attributes[i].Type { 53 case bccsp.IdemixBytesAttribute: 54 attrValues[i] = cryptolib.HashModOrder(attributes[i].Value.([]byte)) 55 case bccsp.IdemixIntAttribute: 56 attrValues[i] = FP256BN.NewBIGint(attributes[i].Value.(int)) 57 default: 58 return nil, errors.Errorf("attribute type not allowed or supported [%v] at position [%d]", attributes[i].Type, i) 59 } 60 } 61 62 cred, err := cryptolib.NewCredential(iisk.SK, cr, attrValues, c.NewRand()) 63 if err != nil { 64 return nil, errors.WithMessage(err, "failed creating new credential") 65 } 66 67 return proto.Marshal(cred) 68 } 69 70 // Verify checks that an idemix credential is cryptographically correct. It takes 71 // in input the user secret key (sk), the issuer public key (ipk), the serialised credential (credential), 72 // and a list of attributes. The list of attributes is optional, in case it is specified, Verify 73 // checks that the credential carries the specified attributes. 74 func (*Credential) Verify(sk handlers.Big, ipk handlers.IssuerPublicKey, credential []byte, attributes []bccsp.IdemixAttribute) (err error) { 75 defer func() { 76 if r := recover(); r != nil { 77 err = errors.Errorf("failure [%s]", r) 78 } 79 }() 80 81 isk, ok := sk.(*Big) 82 if !ok { 83 return errors.Errorf("invalid user secret key, expected *Big, got [%T]", sk) 84 } 85 iipk, ok := ipk.(*IssuerPublicKey) 86 if !ok { 87 return errors.Errorf("invalid issuer public key, expected *IssuerPublicKey, got [%T]", sk) 88 } 89 90 cred := &cryptolib.Credential{} 91 err = proto.Unmarshal(credential, cred) 92 if err != nil { 93 return err 94 } 95 96 for i := 0; i < len(attributes); i++ { 97 switch attributes[i].Type { 98 case bccsp.IdemixBytesAttribute: 99 if !bytes.Equal( 100 cryptolib.BigToBytes(cryptolib.HashModOrder(attributes[i].Value.([]byte))), 101 cred.Attrs[i]) { 102 return errors.Errorf("credential does not contain the correct attribute value at position [%d]", i) 103 } 104 case bccsp.IdemixIntAttribute: 105 if !bytes.Equal( 106 cryptolib.BigToBytes(FP256BN.NewBIGint(attributes[i].Value.(int))), 107 cred.Attrs[i]) { 108 return errors.Errorf("credential does not contain the correct attribute value at position [%d]", i) 109 } 110 case bccsp.IdemixHiddenAttribute: 111 continue 112 default: 113 return errors.Errorf("attribute type not allowed or supported [%v] at position [%d]", attributes[i].Type, i) 114 } 115 } 116 117 return cred.Ver(isk.E, iipk.PK) 118 }