github.com/tw-bc-group/fabric-ca-gm@v0.0.0-20201218004200-3b690512bd5a/lib/gmca.go (about) 1 package lib 2 3 import ( 4 "crypto/sha1" 5 "crypto/x509" 6 "crypto/x509/pkix" 7 "encoding/asn1" 8 "encoding/hex" 9 "errors" 10 "fmt" 11 "net" 12 "net/mail" 13 "time" 14 15 "github.com/cloudflare/cfssl/config" 16 cferr "github.com/cloudflare/cfssl/errors" 17 "github.com/cloudflare/cfssl/helpers" 18 19 "crypto" 20 "crypto/rand" 21 "encoding/pem" 22 "io" 23 "math/big" 24 25 "github.com/Hyperledger-TWGC/tjfoc-gm/sm2" 26 x509GM "github.com/Hyperledger-TWGC/tjfoc-gm/x509" 27 "github.com/cloudflare/cfssl/certdb" 28 "github.com/cloudflare/cfssl/csr" 29 "github.com/cloudflare/cfssl/log" 30 "github.com/tw-bc-group/fabric-gm/bccsp" 31 "github.com/tw-bc-group/fabric-gm/bccsp/gm" 32 33 "github.com/cloudflare/cfssl/signer" 34 "github.com/tw-bc-group/fabric-ca-gm/util" 35 ) 36 37 // add by thoughtwork's matrix 38 func OverrideHosts(template *x509GM.Certificate, hosts []string) { 39 if hosts != nil { 40 template.IPAddresses = []net.IP{} 41 template.EmailAddresses = []string{} 42 template.DNSNames = []string{} 43 } 44 45 for i := range hosts { 46 if ip := net.ParseIP(hosts[i]); ip != nil { 47 template.IPAddresses = append(template.IPAddresses, ip) 48 } else if email, err := mail.ParseAddress(hosts[i]); err == nil && email != nil { 49 template.EmailAddresses = append(template.EmailAddresses, email.Address) 50 } else { 51 template.DNSNames = append(template.DNSNames, hosts[i]) 52 } 53 } 54 } 55 56 // replaceSliceIfEmpty replaces the contents of replaced with newContents if 57 // the slice referenced by replaced is empty 58 func replaceSliceIfEmpty(replaced, newContents *[]string) { 59 if len(*replaced) == 0 { 60 *replaced = *newContents 61 } 62 } 63 64 // PopulateSubjectFromCSR has functionality similar to Name, except 65 // it fills the fields of the resulting pkix.Name with req's if the 66 // subject's corresponding fields are empty 67 func PopulateSubjectFromCSR(s *signer.Subject, req pkix.Name) pkix.Name { 68 // if no subject, use req 69 if s == nil { 70 return req 71 } 72 name := s.Name() 73 74 if name.CommonName == "" { 75 name.CommonName = req.CommonName 76 } 77 78 replaceSliceIfEmpty(&name.Country, &req.Country) 79 replaceSliceIfEmpty(&name.Province, &req.Province) 80 replaceSliceIfEmpty(&name.Locality, &req.Locality) 81 replaceSliceIfEmpty(&name.Organization, &req.Organization) 82 replaceSliceIfEmpty(&name.OrganizationalUnit, &req.OrganizationalUnit) 83 if name.SerialNumber == "" { 84 name.SerialNumber = req.SerialNumber 85 } 86 return name 87 } 88 89 //证书签名 90 func signCert(req signer.SignRequest, ca *CA) (cert []byte, err error) { 91 block, _ := pem.Decode([]byte(req.Request)) 92 if block == nil { 93 return nil, fmt.Errorf("decode error") 94 } 95 if block.Type != "NEW CERTIFICATE REQUEST" && block.Type != "CERTIFICATE REQUEST" { 96 return nil, fmt.Errorf("not a csr") 97 } 98 template, err := parseCertificateRequest(block.Bytes) 99 if err != nil { 100 log.Infof("xxxx gmca.go ParseCertificateRequest error:[%s]", err) 101 return nil, err 102 } 103 104 certfile := ca.Config.CA.Certfile 105 //certfile := req.Profile 106 log.Infof("^^^^^^^^^^^^^^^^^^^^^^^certifle = %s", certfile) 107 _, rootSigner, x509cert, err := util.GetSignerFromCertFile(certfile, ca.csp) 108 if err != nil { 109 110 return nil, err 111 } 112 log.Infof("^^^^^^^^^^^^^^^^^^^^^^^x509cert = %v", x509cert) 113 rootca := ParseX509Certificate2Sm2(x509cert) 114 115 // add by thoughtwork's matrix 116 // override the ou with role 117 OverrideHosts(template, req.Hosts) 118 template.Subject = PopulateSubjectFromCSR(req.Subject, template.Subject) 119 profile, err := FindProfile(ca.enrollSigner.Policy(), req.Profile) 120 if err != nil { 121 return nil, err 122 } 123 124 err = FillTemplate(template, ca.enrollSigner.Policy().Default, profile, template.NotBefore, template.NotAfter) 125 if err != nil { 126 return nil, err 127 } 128 129 130 131 cert, err = gm.CreateCertificateToMem(template, rootca, rootSigner) 132 if err != nil { 133 return nil, err 134 } 135 log.Infof("^^^^^^^^^^^^^^^^^^^^^^^template = %v\n cert = %v\n Type = %T", template, cert, template.PublicKey) 136 clientCert, err := x509GM.ReadCertificateFromPem(cert) 137 log.Info("==================== Exit ParseCertificate") 138 if err == nil { 139 log.Infof("xxxx gmca.go signCert ok the sign cert len [%d]", len(cert)) 140 } else { 141 return nil, err 142 } 143 144 var certRecord = certdb.CertificateRecord{ 145 Serial: clientCert.SerialNumber.String(), 146 AKI: hex.EncodeToString(clientCert.AuthorityKeyId), 147 CALabel: req.Label, 148 Status: "good", 149 Expiry: clientCert.NotAfter, 150 PEM: string(cert), 151 } 152 //aki := hex.EncodeToString(cert.AuthorityKeyId) 153 //serial := util.GetSerialAsHex(cert.SerialNumber) 154 err = ca.certDBAccessor.InsertCertificate(certRecord) 155 return 156 } 157 158 // CAPolicy contains the CA issuing policy as default policy. 159 var CAPolicy = func() *config.Signing { 160 return &config.Signing{ 161 Default: &config.SigningProfile{ 162 Usage: []string{"cert sign", "crl sign"}, 163 ExpiryString: "43800h", 164 Expiry: 5 * helpers.OneYear, 165 CAConstraint: config.CAConstraint{IsCA: true}, 166 }, 167 } 168 } 169 170 type subjectPublicKeyInfo struct { 171 Algorithm pkix.AlgorithmIdentifier 172 SubjectPublicKey asn1.BitString 173 } 174 175 func ComputeSKI(template *x509GM.Certificate) ([]byte, error) { 176 pub := template.PublicKey 177 encodedPub, err := x509GM.MarshalPKIXPublicKey(pub) 178 if err != nil { 179 return nil, err 180 } 181 182 var subPKI subjectPublicKeyInfo 183 _, err = asn1.Unmarshal(encodedPub, &subPKI) 184 if err != nil { 185 return nil, err 186 } 187 188 pubHash := sha1.Sum(subPKI.SubjectPublicKey.Bytes) 189 return pubHash[:], nil 190 } 191 192 type policyInformation struct { 193 PolicyIdentifier asn1.ObjectIdentifier 194 Qualifiers []interface{} `asn1:"tag:optional,omitempty"` 195 } 196 197 type cpsPolicyQualifier struct { 198 PolicyQualifierID asn1.ObjectIdentifier 199 Qualifier string `asn1:"tag:optional,ia5"` 200 } 201 202 type userNotice struct { 203 ExplicitText string `asn1:"tag:optional,utf8"` 204 } 205 type userNoticePolicyQualifier struct { 206 PolicyQualifierID asn1.ObjectIdentifier 207 Qualifier userNotice 208 } 209 210 var ( 211 // Per https://tools.ietf.org/html/rfc3280.html#page-106, this represents: 212 // iso(1) identified-organization(3) dod(6) internet(1) security(5) 213 // mechanisms(5) pkix(7) id-qt(2) id-qt-cps(1) 214 iDQTCertificationPracticeStatement = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 1} 215 // iso(1) identified-organization(3) dod(6) internet(1) security(5) 216 // mechanisms(5) pkix(7) id-qt(2) id-qt-unotice(2) 217 iDQTUserNotice = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 2} 218 219 // CTPoisonOID is the object ID of the critical poison extension for precertificates 220 // https://tools.ietf.org/html/rfc6962#page-9 221 CTPoisonOID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 3} 222 223 // SCTListOID is the object ID for the Signed Certificate Timestamp certificate extension 224 // https://tools.ietf.org/html/rfc6962#page-14 225 SCTListOID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2} 226 ) 227 228 func addPolicies(template *x509GM.Certificate, policies []config.CertificatePolicy) error { 229 var asn1PolicyList []policyInformation 230 231 for _, policy := range policies { 232 pi := policyInformation{ 233 // The PolicyIdentifier is an OID assigned to a given issuer. 234 PolicyIdentifier: asn1.ObjectIdentifier(policy.ID), 235 } 236 for _, qualifier := range policy.Qualifiers { 237 switch qualifier.Type { 238 case "id-qt-unotice": 239 pi.Qualifiers = append(pi.Qualifiers, 240 userNoticePolicyQualifier{ 241 PolicyQualifierID: iDQTUserNotice, 242 Qualifier: userNotice{ 243 ExplicitText: qualifier.Value, 244 }, 245 }) 246 case "id-qt-cps": 247 pi.Qualifiers = append(pi.Qualifiers, 248 cpsPolicyQualifier{ 249 PolicyQualifierID: iDQTCertificationPracticeStatement, 250 Qualifier: qualifier.Value, 251 }) 252 default: 253 return errors.New("Invalid qualifier type in Policies " + qualifier.Type) 254 } 255 } 256 asn1PolicyList = append(asn1PolicyList, pi) 257 } 258 259 asn1Bytes, err := asn1.Marshal(asn1PolicyList) 260 if err != nil { 261 return err 262 } 263 264 template.ExtraExtensions = append(template.ExtraExtensions, pkix.Extension{ 265 Id: asn1.ObjectIdentifier{2, 5, 29, 32}, 266 Critical: false, 267 Value: asn1Bytes, 268 }) 269 return nil 270 } 271 272 func FillTemplate(template *x509GM.Certificate, defaultProfile, profile *config.SigningProfile, notBefore time.Time, notAfter time.Time) error { 273 ski, err := ComputeSKI(template) 274 if err != nil { 275 return err 276 } 277 278 var ( 279 eku []x509.ExtKeyUsage 280 ku x509.KeyUsage 281 backdate time.Duration 282 expiry time.Duration 283 crlURL, ocspURL string 284 issuerURL = profile.IssuerURL 285 ) 286 287 // The third value returned from Usages is a list of unknown key usages. 288 // This should be used when validating the profile at load, and isn't used 289 // here. 290 ku, eku, _ = profile.Usages() 291 sm2eku := make([]x509GM.ExtKeyUsage, len(eku)) 292 293 for i := 0; i < len(eku); i++ { 294 sm2eku[i] = x509GM.ExtKeyUsage(eku[i]) 295 } 296 297 if profile.IssuerURL == nil { 298 issuerURL = defaultProfile.IssuerURL 299 } 300 301 if ku == 0 && len(eku) == 0 { 302 return cferr.New(cferr.PolicyError, cferr.NoKeyUsages) 303 } 304 305 if expiry = profile.Expiry; expiry == 0 { 306 expiry = defaultProfile.Expiry 307 } 308 309 if crlURL = profile.CRL; crlURL == "" { 310 crlURL = defaultProfile.CRL 311 } 312 if ocspURL = profile.OCSP; ocspURL == "" { 313 ocspURL = defaultProfile.OCSP 314 } 315 316 if notBefore.IsZero() { 317 if !profile.NotBefore.IsZero() { 318 notBefore = profile.NotBefore 319 } else { 320 if backdate = profile.Backdate; backdate == 0 { 321 backdate = -5 * time.Minute 322 } else { 323 backdate = -1 * profile.Backdate 324 } 325 notBefore = time.Now().Round(time.Minute).Add(backdate) 326 } 327 } 328 notBefore = notBefore.UTC() 329 330 if notAfter.IsZero() { 331 if !profile.NotAfter.IsZero() { 332 notAfter = profile.NotAfter 333 } else { 334 notAfter = notBefore.Add(expiry) 335 } 336 } 337 notAfter = notAfter.UTC() 338 339 template.NotBefore = notBefore 340 template.NotAfter = notAfter 341 template.KeyUsage = x509GM.KeyUsage(ku) 342 template.ExtKeyUsage = sm2eku 343 template.BasicConstraintsValid = true 344 template.IsCA = profile.CAConstraint.IsCA 345 if template.IsCA { 346 template.MaxPathLen = profile.CAConstraint.MaxPathLen 347 if template.MaxPathLen == 0 { 348 template.MaxPathLenZero = profile.CAConstraint.MaxPathLenZero 349 } 350 template.DNSNames = nil 351 template.EmailAddresses = nil 352 } 353 template.SubjectKeyId = ski 354 355 if ocspURL != "" { 356 template.OCSPServer = []string{ocspURL} 357 } 358 if crlURL != "" { 359 template.CRLDistributionPoints = []string{crlURL} 360 } 361 362 if len(issuerURL) != 0 { 363 template.IssuingCertificateURL = issuerURL 364 } 365 if len(profile.Policies) != 0 { 366 err = addPolicies(template, profile.Policies) 367 if err != nil { 368 return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err) 369 } 370 } 371 if profile.OCSPNoCheck { 372 ocspNoCheckExtension := pkix.Extension{ 373 Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 5}, 374 Critical: false, 375 Value: []byte{0x05, 0x00}, 376 } 377 template.ExtraExtensions = append(template.ExtraExtensions, ocspNoCheckExtension) 378 } 379 380 return nil 381 } 382 383 func FindProfile(policy *config.Signing, profile string) (*config.SigningProfile, error) { 384 var p *config.SigningProfile 385 if policy != nil && policy.Profiles != nil && profile != "" { 386 p = policy.Profiles[profile] 387 } 388 389 if p == nil && policy != nil { 390 p = policy.Default 391 } 392 393 if p == nil { 394 return nil, cferr.Wrap(cferr.APIClientError, cferr.ClientHTTPError, errors.New("profile must not be nil")) 395 } 396 return p, nil 397 } 398 399 //生成证书 400 func createGmSm2Cert(key bccsp.Key, req *csr.CertificateRequest, signer crypto.Signer) (cert []byte, err error) { 401 log.Infof("xxx xxx in gmca.go createGmSm2Cert...key :%T", key) 402 403 policy := CAPolicy() 404 if req.CA != nil { 405 if req.CA.Expiry != "" { 406 policy.Default.ExpiryString = req.CA.Expiry 407 policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry) 408 if err != nil { 409 return nil, err 410 } 411 } 412 413 policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength 414 if req.CA.PathLength != 0 && req.CA.PathLenZero == true { 415 log.Infof("ignore invalid 'pathlenzero' value") 416 } else { 417 policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero 418 } 419 } 420 421 if !policy.Valid() { 422 return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy) 423 } 424 425 csrPEM, err := generate(signer, req) 426 if err != nil { 427 log.Infof("xxxxxxxxxxxxx create csr error:%s", err) 428 } 429 log.Infof("xxxxxxxxxxxxx create gm csr completed!") 430 block, _ := pem.Decode(csrPEM) 431 if block == nil { 432 return nil, fmt.Errorf("sm2 csr DecodeFailed") 433 } 434 435 if block.Type != "NEW CERTIFICATE REQUEST" && block.Type != "CERTIFICATE REQUEST" { 436 return nil, fmt.Errorf("sm2 not a csr") 437 } 438 sm2Template, err := parseCertificateRequest(block.Bytes) 439 if err != nil { 440 log.Infof("parseCertificateRequest return err:%s", err) 441 return nil, err 442 } 443 444 err = FillTemplate(sm2Template, policy.Default, policy.Default, time.Time{}, time.Time{}) 445 if err != nil { 446 return nil, err 447 } 448 449 sm2Template.SubjectKeyId = key.SKI() 450 log.Infof("key is %T ---%T", sm2Template.PublicKey, sm2Template) 451 cert, err = gm.CreateCertificateToMem(sm2Template, sm2Template, signer) 452 return cert, err 453 } 454 455 //证书请求转换成证书 参数为 block .Bytes 456 func parseCertificateRequest(csrBytes []byte) (template *x509GM.Certificate, err error) { 457 csrv, err := x509GM.ParseCertificateRequest(csrBytes) 458 if err != nil { 459 //err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err) 460 return 461 } 462 err = csrv.CheckSignature() 463 // if err != nil { 464 // //err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err) 465 // return 466 // } 467 template = &x509GM.Certificate{ 468 Subject: csrv.Subject, 469 PublicKeyAlgorithm: csrv.PublicKeyAlgorithm, 470 PublicKey: csrv.PublicKey, 471 SignatureAlgorithm: csrv.SignatureAlgorithm, 472 DNSNames: csrv.DNSNames, 473 IPAddresses: csrv.IPAddresses, 474 EmailAddresses: csrv.EmailAddresses, 475 } 476 477 fmt.Printf("^^^^^^^^^^^^^^^^^^^^^^^^^^algorithn = %v, %v\n", template.PublicKeyAlgorithm, template.SignatureAlgorithm) 478 log.Infof("xxxx publicKey :%T", template.PublicKey) 479 480 template.NotBefore = time.Now() 481 template.NotAfter = time.Now().Add(time.Hour * 1000) 482 //log.Infof("-----------csrv = %+v", csrv) 483 for _, val := range csrv.Extensions { 484 // Check the CSR for the X.509 BasicConstraints (RFC 5280, 4.2.1.9) 485 // extension and append to template if necessary 486 if val.Id.Equal(asn1.ObjectIdentifier{2, 5, 29, 19}) { 487 var constraints csr.BasicConstraints 488 var rest []byte 489 490 if rest, err = asn1.Unmarshal(val.Value, &constraints); err != nil { 491 //return nil, cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err) 492 } else if len(rest) != 0 { 493 //return nil, cferr.Wrap(cferr.CSRError, cferr.ParseFailed, errors.New("x509: trailing data after X.509 BasicConstraints")) 494 } 495 496 template.BasicConstraintsValid = true 497 template.IsCA = constraints.IsCA 498 template.MaxPathLen = constraints.MaxPathLen 499 template.MaxPathLenZero = template.MaxPathLen == 0 500 } 501 } 502 serialNumber := make([]byte, 20) 503 _, err = io.ReadFull(rand.Reader, serialNumber) 504 if err != nil { 505 return nil, err 506 } 507 508 // SetBytes interprets buf as the bytes of a big-endian 509 // unsigned integer. The leading byte should be masked 510 // off to ensure it isn't negative. 511 serialNumber[0] &= 0x7F 512 513 template.SerialNumber = new(big.Int).SetBytes(serialNumber) 514 515 return 516 } 517 518 //cloudflare 证书请求 转成 国密证书请求 519 func generate(priv crypto.Signer, req *csr.CertificateRequest) (csr []byte, err error) { 520 log.Info("xx entry gm generate") 521 sigAlgo := signerAlgo(priv) 522 if sigAlgo == x509GM.UnknownSignatureAlgorithm { 523 return nil, fmt.Errorf("Private key is unavailable") 524 } 525 log.Info("xx begin create sm2.CertificateRequest") 526 var tpl = x509GM.CertificateRequest{ 527 Subject: req.Name(), 528 SignatureAlgorithm: sigAlgo, 529 } 530 for i := range req.Hosts { 531 if ip := net.ParseIP(req.Hosts[i]); ip != nil { 532 tpl.IPAddresses = append(tpl.IPAddresses, ip) 533 } else if email, err := mail.ParseAddress(req.Hosts[i]); err == nil && email != nil { 534 tpl.EmailAddresses = append(tpl.EmailAddresses, email.Address) 535 } else { 536 tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i]) 537 } 538 } 539 540 if req.CA != nil { 541 err = appendCAInfoToCSRSm2(req.CA, &tpl) 542 if err != nil { 543 err = fmt.Errorf("sm2 GenerationFailed") 544 return 545 } 546 } 547 if req.SerialNumber != "" { 548 549 } 550 csr, err = gm.CreateSm2CertificateRequestToMem(&tpl, priv) 551 log.Info("xx exit generate") 552 return csr, err 553 } 554 555 func signerAlgo(priv crypto.Signer) x509GM.SignatureAlgorithm { 556 switch pub := priv.Public().(type) { 557 case *sm2.PublicKey: 558 switch pub.Curve { 559 case sm2.P256Sm2(): 560 return x509GM.SM2WithSM3 561 default: 562 return x509GM.SM2WithSM3 563 } 564 default: 565 return x509GM.UnknownSignatureAlgorithm 566 } 567 } 568 569 // appendCAInfoToCSR appends CAConfig BasicConstraint extension to a CSR 570 func appendCAInfoToCSR(reqConf *csr.CAConfig, csreq *x509.CertificateRequest) error { 571 pathlen := reqConf.PathLength 572 if pathlen == 0 && !reqConf.PathLenZero { 573 pathlen = -1 574 } 575 val, err := asn1.Marshal(csr.BasicConstraints{true, pathlen}) 576 577 if err != nil { 578 return err 579 } 580 581 csreq.ExtraExtensions = []pkix.Extension{ 582 { 583 Id: asn1.ObjectIdentifier{2, 5, 29, 19}, 584 Value: val, 585 Critical: true, 586 }, 587 } 588 return nil 589 } 590 591 // appendCAInfoToCSR appends CAConfig BasicConstraint extension to a CSR 592 func appendCAInfoToCSRSm2(reqConf *csr.CAConfig, csreq *x509GM.CertificateRequest) error { 593 pathlen := reqConf.PathLength 594 if pathlen == 0 && !reqConf.PathLenZero { 595 pathlen = -1 596 } 597 val, err := asn1.Marshal(csr.BasicConstraints{true, pathlen}) 598 599 if err != nil { 600 return err 601 } 602 603 csreq.ExtraExtensions = []pkix.Extension{ 604 { 605 Id: asn1.ObjectIdentifier{2, 5, 29, 19}, 606 Value: val, 607 Critical: true, 608 }, 609 } 610 611 return nil 612 } 613 614 func ParseX509Certificate2Sm2(x509Cert *x509.Certificate) *x509GM.Certificate { 615 sm2cert := &x509GM.Certificate{ 616 Raw: x509Cert.Raw, 617 RawTBSCertificate: x509Cert.RawTBSCertificate, 618 RawSubjectPublicKeyInfo: x509Cert.RawSubjectPublicKeyInfo, 619 RawSubject: x509Cert.RawSubject, 620 RawIssuer: x509Cert.RawIssuer, 621 Signature: x509Cert.Signature, 622 SignatureAlgorithm: x509GM.SignatureAlgorithm(x509Cert.SignatureAlgorithm), 623 PublicKeyAlgorithm: x509GM.PublicKeyAlgorithm(x509Cert.PublicKeyAlgorithm), 624 PublicKey: x509Cert.PublicKey, 625 Version: x509Cert.Version, 626 SerialNumber: x509Cert.SerialNumber, 627 Issuer: x509Cert.Issuer, 628 Subject: x509Cert.Subject, 629 NotBefore: x509Cert.NotBefore, 630 NotAfter: x509Cert.NotAfter, 631 KeyUsage: x509GM.KeyUsage(x509Cert.KeyUsage), 632 Extensions: x509Cert.Extensions, 633 ExtraExtensions: x509Cert.ExtraExtensions, 634 UnhandledCriticalExtensions: x509Cert.UnhandledCriticalExtensions, 635 //ExtKeyUsage: []x509.ExtKeyUsage(x509Cert.ExtKeyUsage) , 636 UnknownExtKeyUsage: x509Cert.UnknownExtKeyUsage, 637 BasicConstraintsValid: x509Cert.BasicConstraintsValid, 638 IsCA: x509Cert.IsCA, 639 MaxPathLen: x509Cert.MaxPathLen, 640 // MaxPathLenZero indicates that BasicConstraintsValid==true and 641 // MaxPathLen==0 should be interpreted as an actual maximum path length 642 // of zero. Otherwise, that combination is interpreted as MaxPathLen 643 // not being set. 644 MaxPathLenZero: x509Cert.MaxPathLenZero, 645 SubjectKeyId: x509Cert.SubjectKeyId, 646 AuthorityKeyId: x509Cert.AuthorityKeyId, 647 // RFC 5280, 4.2.2.1 (Authority Information Access) 648 OCSPServer: x509Cert.OCSPServer, 649 IssuingCertificateURL: x509Cert.IssuingCertificateURL, 650 // Subject Alternate Name values 651 DNSNames: x509Cert.DNSNames, 652 EmailAddresses: x509Cert.EmailAddresses, 653 IPAddresses: x509Cert.IPAddresses, 654 // Name constraints 655 PermittedDNSDomainsCritical: x509Cert.PermittedDNSDomainsCritical, 656 PermittedDNSDomains: x509Cert.PermittedDNSDomains, 657 // CRL Distribution Points 658 CRLDistributionPoints: x509Cert.CRLDistributionPoints, 659 PolicyIdentifiers: x509Cert.PolicyIdentifiers, 660 } 661 for _, val := range x509Cert.ExtKeyUsage { 662 sm2cert.ExtKeyUsage = append(sm2cert.ExtKeyUsage, x509GM.ExtKeyUsage(val)) 663 } 664 return sm2cert 665 }