github.com/kaituanwang/hyperledger@v2.0.1+incompatible/common/tools/idemixgen/idemixca/idemixca.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package idemixca 8 9 import ( 10 "crypto/ecdsa" 11 12 "github.com/golang/protobuf/proto" 13 "github.com/hyperledger/fabric-amcl/amcl/FP256BN" 14 m "github.com/hyperledger/fabric-protos-go/msp" 15 "github.com/hyperledger/fabric/idemix" 16 "github.com/hyperledger/fabric/msp" 17 "github.com/pkg/errors" 18 ) 19 20 // GenerateIssuerKey invokes Idemix library to generate an issuer (CA) signing key pair. 21 // Currently four attributes are supported by the issuer: 22 // AttributeNameOU is the organization unit name 23 // AttributeNameRole is the role (member or admin) name 24 // AttributeNameEnrollmentId is the enrollment id 25 // AttributeNameRevocationHandle contains the revocation handle, which can be used to revoke this user 26 // Generated keys are serialized to bytes. 27 func GenerateIssuerKey() ([]byte, []byte, error) { 28 rng, err := idemix.GetRand() 29 if err != nil { 30 return nil, nil, err 31 } 32 AttributeNames := []string{msp.AttributeNameOU, msp.AttributeNameRole, msp.AttributeNameEnrollmentId, msp.AttributeNameRevocationHandle} 33 key, err := idemix.NewIssuerKey(AttributeNames, rng) 34 if err != nil { 35 return nil, nil, errors.WithMessage(err, "cannot generate CA key") 36 } 37 ipkSerialized, err := proto.Marshal(key.Ipk) 38 39 return key.Isk, ipkSerialized, err 40 } 41 42 // GenerateSignerConfig creates a new signer config. 43 // It generates a fresh user secret and issues a credential 44 // with four attributes (described above) using the CA's key pair. 45 func GenerateSignerConfig(roleMask int, ouString string, enrollmentId string, revocationHandle int, key *idemix.IssuerKey, revKey *ecdsa.PrivateKey) ([]byte, error) { 46 attrs := make([]*FP256BN.BIG, 4) 47 48 if ouString == "" { 49 return nil, errors.Errorf("the OU attribute value is empty") 50 } 51 52 if enrollmentId == "" { 53 return nil, errors.Errorf("the enrollment id value is empty") 54 } 55 56 attrs[msp.AttributeIndexOU] = idemix.HashModOrder([]byte(ouString)) 57 attrs[msp.AttributeIndexRole] = FP256BN.NewBIGint(roleMask) 58 attrs[msp.AttributeIndexEnrollmentId] = idemix.HashModOrder([]byte(enrollmentId)) 59 attrs[msp.AttributeIndexRevocationHandle] = FP256BN.NewBIGint(revocationHandle) 60 61 rng, err := idemix.GetRand() 62 if err != nil { 63 return nil, errors.WithMessage(err, "Error getting PRNG") 64 } 65 sk := idemix.RandModOrder(rng) 66 ni := idemix.BigToBytes(idemix.RandModOrder(rng)) 67 msg := idemix.NewCredRequest(sk, ni, key.Ipk, rng) 68 cred, err := idemix.NewCredential(key, msg, attrs, rng) 69 if err != nil { 70 return nil, errors.WithMessage(err, "failed to generate a credential") 71 } 72 73 credBytes, err := proto.Marshal(cred) 74 if err != nil { 75 return nil, errors.WithMessage(err, "failed to marshal credential") 76 } 77 78 // NOTE currently, idemixca creates CRI's with "ALG_NO_REVOCATION" 79 cri, err := idemix.CreateCRI(revKey, []*FP256BN.BIG{FP256BN.NewBIGint(revocationHandle)}, 0, idemix.ALG_NO_REVOCATION, rng) 80 if err != nil { 81 return nil, err 82 } 83 criBytes, err := proto.Marshal(cri) 84 if err != nil { 85 return nil, errors.WithMessage(err, "failed to marshal CRI") 86 } 87 88 signer := &m.IdemixMSPSignerConfig{ 89 Cred: credBytes, 90 Sk: idemix.BigToBytes(sk), 91 OrganizationalUnitIdentifier: ouString, 92 Role: int32(roleMask), 93 EnrollmentId: enrollmentId, 94 CredentialRevocationInformation: criBytes, 95 } 96 97 return proto.Marshal(signer) 98 }