gitee.com/zhaochuninhefei/fabric-ca-gm@v0.0.2/lib/server/idemix/enroll.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 "fmt" 11 "strconv" 12 "strings" 13 14 "gitee.com/zhaochuninhefei/fabric-ca-gm/internal/pkg/api" 15 "gitee.com/zhaochuninhefei/fabric-ca-gm/internal/pkg/util" 16 "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/user" 17 "gitee.com/zhaochuninhefei/fabric-gm/idemix" 18 log "gitee.com/zhaochuninhefei/zcgolog/zclog" 19 proto "github.com/golang/protobuf/proto" 20 fp256bn "github.com/hyperledger/fabric-amcl/amcl/FP256BN" 21 "github.com/pkg/errors" 22 ) 23 24 // EnrollmentResponse is the idemix enrollment response from the server 25 type EnrollmentResponse struct { 26 // Base64 encoding of idemix Credential 27 Credential string 28 // Attribute name-value pairs 29 Attrs map[string]interface{} 30 // Base64 encoding of Credential Revocation information 31 CRI string 32 // Base64 encoding of the issuer nonce 33 Nonce string 34 } 35 36 // EnrollRequestHandler is the handler for Idemix enroll request 37 type EnrollRequestHandler struct { 38 Ctx ServerRequestCtx 39 EnrollmentID string 40 Issuer MyIssuer 41 IdmxLib Lib 42 } 43 44 // HandleRequest handles processing for Idemix enroll 45 func (h *EnrollRequestHandler) HandleRequest() (*EnrollmentResponse, error) { 46 err := h.Authenticate() 47 if err != nil { 48 return nil, err 49 } 50 51 var req api.IdemixEnrollmentRequestNet 52 err = h.Ctx.ReadBody(&req) 53 if err != nil { 54 return nil, err 55 } 56 57 if req.CredRequest == nil { 58 nonce, err := h.Issuer.NonceManager().GetNonce() 59 if err != nil { 60 return nil, errors.New("Failed to generate nonce") 61 } 62 63 resp := &EnrollmentResponse{ 64 Nonce: util.B64Encode(idemix.BigToBytes(nonce)), 65 } 66 return resp, nil 67 } 68 69 ik, err := h.Issuer.IssuerCredential().GetIssuerKey() 70 if err != nil { 71 log.Errorf("Failed to get Idemix issuer key for the CA %s: %s", h.Issuer.Name(), err.Error()) 72 return nil, errors.WithMessage(err, fmt.Sprintf("Failed to get Idemix issuer key for the CA: %s", 73 h.Issuer.Name())) 74 } 75 76 caller, err := h.Ctx.GetCaller() 77 if err != nil { 78 log.Errorf("Failed to get caller of the request: %s", err.Error()) 79 return nil, err 80 } 81 82 nonce := fp256bn.FromBytes(req.GetIssuerNonce()) 83 err = h.Issuer.NonceManager().CheckNonce(nonce) 84 if err != nil { 85 return nil, errors.WithMessage(err, "Invalid nonce") 86 } 87 88 // Check the if credential request is valid 89 err = req.CredRequest.Check(ik.GetIpk()) 90 if err != nil { 91 log.Errorf("Invalid Idemix credential request: %s", err.Error()) 92 return nil, errors.WithMessage(err, "Invalid Idemix credential request") 93 } 94 95 // Get revocation handle for the credential 96 rh, err := h.Issuer.RevocationAuthority().GetNewRevocationHandle() 97 if err != nil { 98 return nil, err 99 } 100 101 // Get attributes for the identity 102 attrMap, attrs, err := h.GetAttributeValues(caller, ik.GetIpk(), rh) 103 if err != nil { 104 return nil, err 105 } 106 107 cred, err := h.IdmxLib.NewCredential(ik, req.CredRequest, attrs, h.Issuer.IdemixRand()) 108 if err != nil { 109 log.Errorf("Issuer '%s' failed to create new Idemix credential for identity '%s': %s", 110 h.Issuer.Name(), h.EnrollmentID, err.Error()) 111 return nil, errors.New("Failed to create new Idemix credential") 112 } 113 credBytes, err := proto.Marshal(cred) 114 if err != nil { 115 return nil, errors.New("Failed to marshal Idemix credential to bytes") 116 } 117 b64CredBytes := util.B64Encode(credBytes) 118 119 rhstr := util.B64Encode(idemix.BigToBytes(rh)) 120 121 // Store the credential in the database 122 err = h.Issuer.CredDBAccessor().InsertCredential(CredRecord{ 123 CALabel: h.Issuer.Name(), 124 ID: caller.GetName(), 125 Status: "good", 126 Cred: b64CredBytes, 127 RevocationHandle: rhstr, 128 }) 129 if err != nil { 130 log.Errorf("Failed to store the Idemix credential for identity '%s' in the database: %s", caller.GetName(), err.Error()) 131 return nil, errors.New("Failed to store the Idemix credential") 132 } 133 134 // Get CRL from revocation authority of the CA 135 cri, err := h.Issuer.RevocationAuthority().CreateCRI() 136 if err != nil { 137 log.Errorf("Failed to generate CRI while processing idemix/credential request: %s", err.Error()) 138 return nil, errors.New("Failed to generate CRI") 139 } 140 criBytes, err := proto.Marshal(cri) 141 if err != nil { 142 return nil, errors.New("Failed to marshal CRI to bytes") 143 } 144 b64CriBytes := util.B64Encode(criBytes) 145 resp := &EnrollmentResponse{ 146 Credential: b64CredBytes, 147 Attrs: attrMap, 148 CRI: b64CriBytes, 149 } 150 151 if h.Ctx.IsBasicAuth() { 152 err = caller.LoginComplete() 153 if err != nil { 154 return nil, err 155 } 156 } 157 158 // Success 159 return resp, nil 160 } 161 162 // Authenticate authenticates the Idemix enroll request 163 func (h *EnrollRequestHandler) Authenticate() error { 164 var err error 165 if h.Ctx.IsBasicAuth() { 166 h.EnrollmentID, err = h.Ctx.BasicAuthentication() 167 if err != nil { 168 return err 169 } 170 } else { 171 h.EnrollmentID, err = h.Ctx.TokenAuthentication() 172 if err != nil { 173 return err 174 } 175 } 176 return nil 177 } 178 179 // GenerateNonce generates a nonce for an Idemix enroll request 180 func (h *EnrollRequestHandler) GenerateNonce() (*fp256bn.BIG, error) { 181 return h.IdmxLib.RandModOrder(h.Issuer.IdemixRand()) 182 } 183 184 // GetAttributeValues returns attribute values of the caller of Idemix enroll request 185 func (h *EnrollRequestHandler) GetAttributeValues(caller user.User, ipk *idemix.IssuerPublicKey, 186 rh *fp256bn.BIG) (map[string]interface{}, []*fp256bn.BIG, error) { 187 rc := []*fp256bn.BIG{} 188 attrMap := make(map[string]interface{}) 189 for _, attrName := range ipk.AttributeNames { 190 if attrName == AttrEnrollmentID { 191 idBytes := []byte(caller.GetName()) 192 rc = append(rc, idemix.HashModOrder(idBytes)) 193 attrMap[attrName] = caller.GetName() 194 } else if attrName == AttrOU { 195 ou := append([]string{}, caller.GetAffiliationPath()...) 196 ouVal := strings.Join(ou, ".") 197 ouBytes := []byte(ouVal) 198 rc = append(rc, idemix.HashModOrder(ouBytes)) 199 attrMap[attrName] = ouVal 200 } else if attrName == AttrRevocationHandle { 201 rc = append(rc, rh) 202 attrMap[attrName] = util.B64Encode(idemix.BigToBytes(rh)) 203 } else if attrName == AttrRole { 204 role := MEMBER.getValue() 205 attrObj, err := caller.GetAttribute("role") 206 if err == nil { 207 role, err = strconv.Atoi(attrObj.GetValue()) 208 if err != nil { 209 log.Debugf("role attribute of user %s must be a integer value", caller.GetName()) 210 } 211 } 212 rc = append(rc, fp256bn.NewBIGint(role)) 213 attrMap[attrName] = role 214 } else { 215 attrObj, err := caller.GetAttribute(attrName) 216 if err != nil { 217 log.Errorf("Failed to get attribute %s for user %s: %s", attrName, caller.GetName(), err.Error()) 218 } else { 219 attrBytes := []byte(attrObj.GetValue()) 220 rc = append(rc, idemix.HashModOrder(attrBytes)) 221 attrMap[attrName] = attrObj.GetValue() 222 } 223 } 224 } 225 return attrMap, rc, nil 226 }