github.com/emmansun/gmsm@v0.29.1/smx509/verify_test.go (about) 1 package smx509 2 3 import ( 4 "crypto" 5 "crypto/ecdsa" 6 "crypto/elliptic" 7 "crypto/rand" 8 "crypto/x509" 9 "crypto/x509/pkix" 10 "encoding/asn1" 11 "encoding/pem" 12 "errors" 13 "fmt" 14 "math/big" 15 "reflect" 16 "runtime" 17 "sort" 18 "strings" 19 "testing" 20 "time" 21 ) 22 23 type verifyTest struct { 24 name string 25 leaf string 26 intermediates []string 27 roots []string 28 currentTime int64 29 dnsName string 30 systemSkip bool 31 systemLax bool 32 keyUsages []ExtKeyUsage 33 34 errorCallback func(*testing.T, error) 35 expectedChains [][]string 36 } 37 38 var verifyTests = []verifyTest{ 39 { 40 name: "Valid", 41 leaf: googleLeaf, 42 intermediates: []string{giag2Intermediate}, 43 roots: []string{geoTrustRoot}, 44 currentTime: 1395785200, 45 dnsName: "www.google.com", 46 47 expectedChains: [][]string{ 48 {"Google", "Google Internet Authority", "GeoTrust"}, 49 }, 50 }, 51 { 52 name: "MixedCase", 53 leaf: googleLeaf, 54 intermediates: []string{giag2Intermediate}, 55 roots: []string{geoTrustRoot}, 56 currentTime: 1395785200, 57 dnsName: "WwW.GooGLE.coM", 58 59 expectedChains: [][]string{ 60 {"Google", "Google Internet Authority", "GeoTrust"}, 61 }, 62 }, 63 { 64 name: "HostnameMismatch", 65 leaf: googleLeaf, 66 intermediates: []string{giag2Intermediate}, 67 roots: []string{geoTrustRoot}, 68 currentTime: 1395785200, 69 dnsName: "www.example.com", 70 71 errorCallback: expectHostnameError("certificate is valid for"), 72 }, 73 { 74 name: "IPMissing", 75 leaf: googleLeaf, 76 intermediates: []string{giag2Intermediate}, 77 roots: []string{geoTrustRoot}, 78 currentTime: 1395785200, 79 dnsName: "1.2.3.4", 80 81 errorCallback: expectHostnameError("doesn't contain any IP SANs"), 82 }, 83 { 84 name: "Expired", 85 leaf: googleLeaf, 86 intermediates: []string{giag2Intermediate}, 87 roots: []string{geoTrustRoot}, 88 currentTime: 1, 89 dnsName: "www.example.com", 90 91 errorCallback: expectExpired, 92 }, 93 { 94 name: "MissingIntermediate", 95 leaf: googleLeaf, 96 roots: []string{geoTrustRoot}, 97 currentTime: 1395785200, 98 dnsName: "www.google.com", 99 100 // Skip when using systemVerify, since Windows 101 // *will* find the missing intermediate cert. 102 systemSkip: true, 103 errorCallback: expectAuthorityUnknown, 104 }, 105 { 106 name: "RootInIntermediates", 107 leaf: googleLeaf, 108 intermediates: []string{geoTrustRoot, giag2Intermediate}, 109 roots: []string{geoTrustRoot}, 110 currentTime: 1395785200, 111 dnsName: "www.google.com", 112 113 expectedChains: [][]string{ 114 {"Google", "Google Internet Authority", "GeoTrust"}, 115 }, 116 // CAPI doesn't build the chain with the duplicated GeoTrust 117 // entry so the results don't match. 118 systemLax: true, 119 }, 120 { 121 name: "dnssec-exp", 122 leaf: dnssecExpLeaf, 123 intermediates: []string{startComIntermediate}, 124 roots: []string{startComRoot}, 125 currentTime: 1302726541, 126 127 // The StartCom root is not trusted by Windows when the default 128 // ServerAuth EKU is requested. 129 systemSkip: true, 130 131 expectedChains: [][]string{ 132 {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, 133 }, 134 }, 135 { 136 name: "dnssec-exp/AnyEKU", 137 leaf: dnssecExpLeaf, 138 intermediates: []string{startComIntermediate}, 139 roots: []string{startComRoot}, 140 currentTime: 1302726541, 141 keyUsages: []ExtKeyUsage{ExtKeyUsageAny}, 142 143 expectedChains: [][]string{ 144 {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, 145 }, 146 }, 147 { 148 name: "dnssec-exp/RootInIntermediates", 149 leaf: dnssecExpLeaf, 150 intermediates: []string{startComIntermediate, startComRoot}, 151 roots: []string{startComRoot}, 152 currentTime: 1302726541, 153 systemSkip: true, // see dnssec-exp test 154 155 expectedChains: [][]string{ 156 {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, 157 }, 158 }, 159 { 160 name: "InvalidHash", 161 leaf: googleLeafWithInvalidHash, 162 intermediates: []string{giag2Intermediate}, 163 roots: []string{geoTrustRoot}, 164 currentTime: 1395785200, 165 dnsName: "www.google.com", 166 167 // The specific error message may not occur when using system 168 // verification. 169 systemLax: true, 170 errorCallback: expectHashError, 171 }, 172 // EKULeaf tests use an unconstrained chain leading to a leaf certificate 173 // with an E-mail Protection EKU but not a Server Auth one, checking that 174 // the EKUs on the leaf are enforced. 175 { 176 name: "EKULeaf", 177 leaf: smimeLeaf, 178 intermediates: []string{smimeIntermediate}, 179 roots: []string{smimeRoot}, 180 currentTime: 1594673418, 181 182 errorCallback: expectUsageError, 183 }, 184 { 185 name: "EKULeafExplicit", 186 leaf: smimeLeaf, 187 intermediates: []string{smimeIntermediate}, 188 roots: []string{smimeRoot}, 189 currentTime: 1594673418, 190 keyUsages: []ExtKeyUsage{ExtKeyUsageServerAuth}, 191 192 errorCallback: expectUsageError, 193 }, 194 { 195 name: "EKULeafValid", 196 leaf: smimeLeaf, 197 intermediates: []string{smimeIntermediate}, 198 roots: []string{smimeRoot}, 199 currentTime: 1594673418, 200 keyUsages: []ExtKeyUsage{ExtKeyUsageEmailProtection}, 201 202 expectedChains: [][]string{ 203 {"CORPORATIVO FICTICIO ACTIVO", "EAEko Herri Administrazioen CA - CA AAPP Vascas (2)", "IZENPE S.A."}, 204 }, 205 }, 206 { 207 // Check that a name constrained intermediate works even when 208 // it lists multiple constraints. 209 name: "MultipleConstraints", 210 leaf: nameConstraintsLeaf, 211 intermediates: []string{nameConstraintsIntermediate1, nameConstraintsIntermediate2}, 212 roots: []string{globalSignRoot}, 213 currentTime: 1382387896, 214 dnsName: "secure.iddl.vt.edu", 215 216 expectedChains: [][]string{ 217 { 218 "Technology-enhanced Learning and Online Strategies", 219 "Virginia Tech Global Qualified Server CA", 220 "Trusted Root CA G2", 221 "GlobalSign Root CA", 222 }, 223 }, 224 }, 225 { 226 // Check that SHA-384 intermediates (which are popping up) 227 // work. 228 name: "SHA-384", 229 leaf: moipLeafCert, 230 intermediates: []string{comodoIntermediateSHA384, comodoRSAAuthority}, 231 roots: []string{addTrustRoot}, 232 currentTime: 1397502195, 233 dnsName: "api.moip.com.br", 234 235 // CryptoAPI can find alternative validation paths. 236 systemLax: true, 237 238 expectedChains: [][]string{ 239 { 240 "api.moip.com.br", 241 "COMODO RSA Extended Validation Secure Server CA", 242 "COMODO RSA Certification Authority", 243 "AddTrust External CA Root", 244 }, 245 }, 246 }, 247 { 248 // Putting a certificate as a root directly should work as a 249 // way of saying “exactly this”. 250 name: "LeafInRoots", 251 leaf: selfSigned, 252 roots: []string{selfSigned}, 253 currentTime: 1471624472, 254 dnsName: "foo.example", 255 systemSkip: true, // does not chain to a system root 256 257 expectedChains: [][]string{ 258 {"Acme Co"}, 259 }, 260 }, 261 { 262 // Putting a certificate as a root directly should not skip 263 // other checks however. 264 name: "LeafInRootsInvalid", 265 leaf: selfSigned, 266 roots: []string{selfSigned}, 267 currentTime: 1471624472, 268 dnsName: "notfoo.example", 269 systemSkip: true, // does not chain to a system root 270 271 errorCallback: expectHostnameError("certificate is valid for"), 272 }, 273 { 274 // An X.509 v1 certificate should not be accepted as an 275 // intermediate. 276 name: "X509v1Intermediate", 277 leaf: x509v1TestLeaf, 278 intermediates: []string{x509v1TestIntermediate}, 279 roots: []string{x509v1TestRoot}, 280 currentTime: 1481753183, 281 systemSkip: true, // does not chain to a system root 282 283 errorCallback: expectNotAuthorizedError, 284 }, 285 { 286 name: "IgnoreCNWithSANs", 287 leaf: ignoreCNWithSANLeaf, 288 dnsName: "foo.example.com", 289 roots: []string{ignoreCNWithSANRoot}, 290 currentTime: 1486684488, 291 systemSkip: true, // does not chain to a system root 292 293 errorCallback: expectHostnameError("certificate is not valid for any names"), 294 }, 295 { 296 // Test that excluded names are respected. 297 name: "ExcludedNames", 298 leaf: excludedNamesLeaf, 299 dnsName: "bender.local", 300 intermediates: []string{excludedNamesIntermediate}, 301 roots: []string{excludedNamesRoot}, 302 currentTime: 1486684488, 303 systemSkip: true, // does not chain to a system root 304 305 errorCallback: expectNameConstraintsError, 306 }, 307 { 308 // Test that unknown critical extensions in a leaf cause a 309 // verify error. 310 name: "CriticalExtLeaf", 311 leaf: criticalExtLeafWithExt, 312 intermediates: []string{criticalExtIntermediate}, 313 roots: []string{criticalExtRoot}, 314 currentTime: 1486684488, 315 systemSkip: true, // does not chain to a system root 316 317 errorCallback: expectUnhandledCriticalExtension, 318 }, 319 { 320 // Test that unknown critical extensions in an intermediate 321 // cause a verify error. 322 name: "CriticalExtIntermediate", 323 leaf: criticalExtLeaf, 324 intermediates: []string{criticalExtIntermediateWithExt}, 325 roots: []string{criticalExtRoot}, 326 currentTime: 1486684488, 327 systemSkip: true, // does not chain to a system root 328 329 errorCallback: expectUnhandledCriticalExtension, 330 }, 331 { 332 name: "ValidCN", 333 leaf: validCNWithoutSAN, 334 dnsName: "foo.example.com", 335 roots: []string{invalidCNRoot}, 336 currentTime: 1540000000, 337 systemSkip: true, // does not chain to a system root 338 339 errorCallback: expectHostnameError("certificate relies on legacy Common Name field"), 340 }, 341 { 342 // A certificate with an AKID should still chain to a parent without SKID. 343 // See Issue 30079. 344 name: "AKIDNoSKID", 345 leaf: leafWithAKID, 346 roots: []string{rootWithoutSKID}, 347 currentTime: 1550000000, 348 dnsName: "example", 349 systemSkip: true, // does not chain to a system root 350 351 expectedChains: [][]string{ 352 {"Acme LLC", "Acme Co"}, 353 }, 354 }, 355 { 356 // When there are two parents, one with a incorrect subject but matching SKID 357 // and one with a correct subject but missing SKID, the latter should be 358 // considered as a possible parent. 359 leaf: leafMatchingAKIDMatchingIssuer, 360 roots: []string{rootMatchingSKIDMismatchingSubject, rootMismatchingSKIDMatchingSubject}, 361 currentTime: 1550000000, 362 dnsName: "example", 363 systemSkip: true, 364 365 expectedChains: [][]string{ 366 {"Leaf", "Root B"}, 367 }, 368 }, 369 } 370 371 func expectHostnameError(msg string) func(*testing.T, error) { 372 return func(t *testing.T, err error) { 373 if _, ok := err.(x509.HostnameError); !ok { 374 t.Fatalf("error was not a HostnameError: %v", err) 375 } 376 if !strings.Contains(err.Error(), msg) { 377 t.Fatalf("HostnameError did not contain %q: %v", msg, err) 378 } 379 } 380 } 381 382 func expectExpired(t *testing.T, err error) { 383 if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired { 384 t.Fatalf("error was not Expired: %v", err) 385 } 386 } 387 388 func expectUsageError(t *testing.T, err error) { 389 if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != IncompatibleUsage { 390 t.Fatalf("error was not IncompatibleUsage: %v", err) 391 } 392 } 393 394 func expectAuthorityUnknown(t *testing.T, err error) { 395 e, ok := err.(UnknownAuthorityError) 396 if !ok { 397 t.Fatalf("error was not UnknownAuthorityError: %v", err) 398 } 399 if e.Cert == nil { 400 t.Fatalf("error was UnknownAuthorityError, but missing Cert: %v", err) 401 } 402 } 403 404 func expectHashError(t *testing.T, err error) { 405 if err == nil { 406 t.Fatalf("no error resulted from invalid hash") 407 } 408 if expected := "algorithm unimplemented"; !strings.Contains(err.Error(), expected) { 409 t.Fatalf("error resulting from invalid hash didn't contain '%s', rather it was: %v", expected, err) 410 } 411 } 412 413 func expectNameConstraintsError(t *testing.T, err error) { 414 if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != CANotAuthorizedForThisName { 415 t.Fatalf("error was not a CANotAuthorizedForThisName: %v", err) 416 } 417 } 418 419 func expectNotAuthorizedError(t *testing.T, err error) { 420 if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NotAuthorizedToSign { 421 t.Fatalf("error was not a NotAuthorizedToSign: %v", err) 422 } 423 } 424 425 func expectUnhandledCriticalExtension(t *testing.T, err error) { 426 if _, ok := err.(x509.UnhandledCriticalExtension); !ok { 427 t.Fatalf("error was not an UnhandledCriticalExtension: %v", err) 428 } 429 } 430 431 func certificateFromPEM(pemBytes string) (*Certificate, error) { 432 block, _ := pem.Decode([]byte(pemBytes)) 433 if block == nil { 434 return nil, errors.New("failed to decode PEM") 435 } 436 return ParseCertificate(block.Bytes) 437 } 438 439 func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { 440 opts := VerifyOptions{ 441 Intermediates: NewCertPool(), 442 DNSName: test.dnsName, 443 CurrentTime: time.Unix(test.currentTime, 0), 444 KeyUsages: test.keyUsages, 445 } 446 447 if !useSystemRoots { 448 opts.Roots = NewCertPool() 449 for j, root := range test.roots { 450 ok := opts.Roots.AppendCertsFromPEM([]byte(root)) 451 if !ok { 452 t.Fatalf("failed to parse root #%d", j) 453 } 454 } 455 } 456 457 for j, intermediate := range test.intermediates { 458 ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate)) 459 if !ok { 460 t.Fatalf("failed to parse intermediate #%d", j) 461 } 462 } 463 464 leaf, err := certificateFromPEM(test.leaf) 465 if err != nil { 466 t.Fatalf("failed to parse leaf: %v", err) 467 } 468 469 chains, err := leaf.Verify(opts) 470 471 if test.errorCallback == nil && err != nil { 472 //if runtime.GOOS == "windows" && strings.HasSuffix(testenv.Builder(), "-2008") && err.Error() == "x509: certificate signed by unknown authority" { 473 // testenv.SkipFlaky(t, 19564) 474 //} 475 t.Fatalf("unexpected error: %v", err) 476 } 477 if test.errorCallback != nil { 478 if useSystemRoots && test.systemLax { 479 if err == nil { 480 t.Fatalf("expected error") 481 } 482 } else { 483 test.errorCallback(t, err) 484 } 485 } 486 487 doesMatch := func(expectedChain []string, chain []*Certificate) bool { 488 if len(chain) != len(expectedChain) { 489 return false 490 } 491 492 for k, cert := range chain { 493 if !strings.Contains(nameToKey(&cert.Subject), expectedChain[k]) { 494 return false 495 } 496 } 497 return true 498 } 499 500 // Every expected chain should match one (or more) returned chain. We tolerate multiple 501 // matches, as due to root store semantics it is plausible that (at least on the system 502 // verifiers) multiple identical (looking) chains may be returned when two roots with the 503 // same subject are present. 504 for _, expectedChain := range test.expectedChains { 505 var match bool 506 for _, chain := range chains { 507 if doesMatch(expectedChain, chain) { 508 match = true 509 break 510 } 511 } 512 513 if !match { 514 t.Errorf("No match found for %v", expectedChain) 515 } 516 } 517 518 // Every returned chain should match 1 expected chain (or <2 if testing against the system) 519 for _, chain := range chains { 520 nMatched := 0 521 for _, expectedChain := range test.expectedChains { 522 if doesMatch(expectedChain, chain) { 523 nMatched++ 524 } 525 } 526 // Allow additional unknown chains if systemLax is set 527 if nMatched == 0 && test.systemLax == false || nMatched > 1 { 528 t.Errorf("Got %v matches for chain %v", nMatched, chainToDebugString(chain)) 529 for _, expectedChain := range test.expectedChains { 530 if doesMatch(expectedChain, chain) { 531 t.Errorf("\t matched %v", expectedChain) 532 } 533 } 534 } 535 } 536 } 537 538 func TestGoVerify(t *testing.T) { 539 // Temporarily enable SHA-1 verification since a number of test chains 540 // require it. TODO(filippo): regenerate test chains. 541 defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1) 542 debugAllowSHA1 = true 543 544 for _, test := range verifyTests { 545 t.Run(test.name, func(t *testing.T) { 546 testVerify(t, test, false) 547 }) 548 } 549 } 550 551 func TestSystemVerify(t *testing.T) { 552 if runtime.GOOS != "windows" { 553 t.Skipf("skipping verify test using system APIs on %q", runtime.GOOS) 554 } 555 556 for _, test := range verifyTests { 557 t.Run(test.name, func(t *testing.T) { 558 if test.systemSkip { 559 t.SkipNow() 560 } 561 testVerify(t, test, true) 562 }) 563 } 564 } 565 566 func chainToDebugString(chain []*Certificate) string { 567 var chainStr string 568 for _, cert := range chain { 569 if len(chainStr) > 0 { 570 chainStr += " -> " 571 } 572 chainStr += nameToKey(&cert.Subject) 573 } 574 return chainStr 575 } 576 577 func nameToKey(name *pkix.Name) string { 578 return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName 579 } 580 581 const geoTrustRoot = `-----BEGIN CERTIFICATE----- 582 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT 583 MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i 584 YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG 585 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg 586 R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 587 9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq 588 fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv 589 iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU 590 1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ 591 bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW 592 MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA 593 ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l 594 uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn 595 Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS 596 tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF 597 PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un 598 hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV 599 5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== 600 -----END CERTIFICATE-----` 601 602 const giag2Intermediate = `-----BEGIN CERTIFICATE----- 603 MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT 604 MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i 605 YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG 606 EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy 607 bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB 608 AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP 609 VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv 610 h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE 611 ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ 612 EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC 613 DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7 614 qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD 615 VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g 616 K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI 617 KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n 618 ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB 619 BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY 620 /iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/ 621 zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza 622 HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto 623 WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6 624 yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx 625 -----END CERTIFICATE-----` 626 627 const googleLeaf = `-----BEGIN CERTIFICATE----- 628 MIIEdjCCA16gAwIBAgIIcR5k4dkoe04wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE 629 BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl 630 cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMzEyMDkzODMwWhcNMTQwNjEwMDAwMDAw 631 WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN 632 TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3 633 Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4zYCe 634 m0oUBhwE0EwBr65eBOcgcQO2PaSIAB2dEP/c1EMX2tOy0ov8rk83ePhJ+MWdT1z6 635 jge9X4zQQI8ZyA9qIiwrKBZOi8DNUvrqNZC7fJAVRrb9aX/99uYOJCypIbpmWG1q 636 fhbHjJewhwf8xYPj71eU4rLG80a+DapWmphtfq3h52lDQIBzLVf1yYbyrTaELaz4 637 NXF7HXb5YkId/gxIsSzM0aFUVu2o8sJcLYAsJqwfFKBKOMxUcn545nlspf0mTcWZ 638 0APlbwsKznNs4/xCDwIxxWjjqgHrYAFl6y07i1gzbAOqdNEyR24p+3JWI8WZBlBI 639 dk2KGj0W1fIfsvyxAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEFBQcDAQYI 640 KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE 641 XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0 642 MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G 643 A1UdDgQWBBTXD5Bx6iqT+dmEhbFL4OUoHyZn8zAMBgNVHRMBAf8EAjAAMB8GA1Ud 644 IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYKKwYBBAHW 645 eQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB 646 RzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCR3RJtHzgDh33b/MI1ugiki+nl8Ikj 647 5larbJRE/rcA5oite+QJyAr6SU1gJJ/rRrK3ItVEHr9L621BCM7GSdoNMjB9MMcf 648 tJAW0kYGJ+wqKm53wG/JaOADTnnq2Mt/j6F2uvjgN/ouns1nRHufIvd370N0LeH+ 649 orKqTuAPzXK7imQk6+OycYABbqCtC/9qmwRd8wwn7sF97DtYfK8WuNHtFalCAwyi 650 8LxJJYJCLWoMhZ+V8GZm+FOex5qkQAjnZrtNlbQJ8ro4r+rpKXtmMFFhfa+7L+PA 651 Kom08eUK8skxAzfDDijZPh10VtJ66uBoiDPdT+uCBehcBIcmSTrKjFGX 652 -----END CERTIFICATE-----` 653 654 // googleLeafWithInvalidHash is the same as googleLeaf, but the signature 655 // algorithm in the certificate contains a nonsense OID. 656 const googleLeafWithInvalidHash = `-----BEGIN CERTIFICATE----- 657 MIIEdjCCA16gAwIBAgIIcR5k4dkoe04wDQYJKoZIhvcNAWAFBQAwSTELMAkGA1UE 658 BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl 659 cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMzEyMDkzODMwWhcNMTQwNjEwMDAwMDAw 660 WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN 661 TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3 662 Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4zYCe 663 m0oUBhwE0EwBr65eBOcgcQO2PaSIAB2dEP/c1EMX2tOy0ov8rk83ePhJ+MWdT1z6 664 jge9X4zQQI8ZyA9qIiwrKBZOi8DNUvrqNZC7fJAVRrb9aX/99uYOJCypIbpmWG1q 665 fhbHjJewhwf8xYPj71eU4rLG80a+DapWmphtfq3h52lDQIBzLVf1yYbyrTaELaz4 666 NXF7HXb5YkId/gxIsSzM0aFUVu2o8sJcLYAsJqwfFKBKOMxUcn545nlspf0mTcWZ 667 0APlbwsKznNs4/xCDwIxxWjjqgHrYAFl6y07i1gzbAOqdNEyR24p+3JWI8WZBlBI 668 dk2KGj0W1fIfsvyxAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEFBQcDAQYI 669 KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE 670 XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0 671 MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G 672 A1UdDgQWBBTXD5Bx6iqT+dmEhbFL4OUoHyZn8zAMBgNVHRMBAf8EAjAAMB8GA1Ud 673 IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYKKwYBBAHW 674 eQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB 675 RzIuY3JsMA0GCSqGSIb3DQFgBQUAA4IBAQCR3RJtHzgDh33b/MI1ugiki+nl8Ikj 676 5larbJRE/rcA5oite+QJyAr6SU1gJJ/rRrK3ItVEHr9L621BCM7GSdoNMjB9MMcf 677 tJAW0kYGJ+wqKm53wG/JaOADTnnq2Mt/j6F2uvjgN/ouns1nRHufIvd370N0LeH+ 678 orKqTuAPzXK7imQk6+OycYABbqCtC/9qmwRd8wwn7sF97DtYfK8WuNHtFalCAwyi 679 8LxJJYJCLWoMhZ+V8GZm+FOex5qkQAjnZrtNlbQJ8ro4r+rpKXtmMFFhfa+7L+PA 680 Kom08eUK8skxAzfDDijZPh10VtJ66uBoiDPdT+uCBehcBIcmSTrKjFGX 681 -----END CERTIFICATE-----` 682 683 const dnssecExpLeaf = `-----BEGIN CERTIFICATE----- 684 MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ 685 TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0 686 YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg 687 MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTAwNzA0MTQ1MjQ1 688 WhcNMTEwNzA1MTA1NzA0WjCBwTEgMB4GA1UEDRMXMjIxMTM3LWxpOWE5dHhJRzZM 689 NnNyVFMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVQZXJzb25hIE5vdCBWYWxpZGF0 690 ZWQxKTAnBgNVBAsTIFN0YXJ0Q29tIEZyZWUgQ2VydGlmaWNhdGUgTWVtYmVyMRsw 691 GQYDVQQDExJ3d3cuZG5zc2VjLWV4cC5vcmcxKDAmBgkqhkiG9w0BCQEWGWhvc3Rt 692 YXN0ZXJAZG5zc2VjLWV4cC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK 693 AoIBAQDEdF/22vaxrPbqpgVYMWi+alfpzBctpbfLBdPGuqOazJdCT0NbWcK8/+B4 694 X6OlSOURNIlwLzhkmwVsWdVv6dVSaN7d4yI/fJkvgfDB9+au+iBJb6Pcz8ULBfe6 695 D8HVvqKdORp6INzHz71z0sghxrQ0EAEkoWAZLh+kcn2ZHdcmZaBNUfjmGbyU6PRt 696 RjdqoP+owIaC1aktBN7zl4uO7cRjlYFdusINrh2kPP02KAx2W84xjxX1uyj6oS6e 697 7eBfvcwe8czW/N1rbE0CoR7h9+HnIrjnVG9RhBiZEiw3mUmF++Up26+4KTdRKbu3 698 +BL4yMpfd66z0+zzqu+HkvyLpFn5AgMBAAGjggL/MIIC+zAJBgNVHRMEAjAAMAsG 699 A1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUy04I5guM 700 drzfh2JQaXhgV86+4jUwHwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xkLu8OLEUw 701 LQYDVR0RBCYwJIISd3d3LmRuc3NlYy1leHAub3Jngg5kbnNzZWMtZXhwLm9yZzCC 702 AUIGA1UdIASCATkwggE1MIIBMQYLKwYBBAGBtTcBAgIwggEgMC4GCCsGAQUFBwIB 703 FiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMDQGCCsGAQUFBwIB 704 FihodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9pbnRlcm1lZGlhdGUucGRmMIG3Bggr 705 BgEFBQcCAjCBqjAUFg1TdGFydENvbSBMdGQuMAMCAQEagZFMaW1pdGVkIExpYWJp 706 bGl0eSwgc2VlIHNlY3Rpb24gKkxlZ2FsIExpbWl0YXRpb25zKiBvZiB0aGUgU3Rh 707 cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUG9saWN5IGF2YWlsYWJsZSBh 708 dCBodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMGEGA1UdHwRaMFgw 709 KqAooCaGJGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDAqoCig 710 JoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1jcmwuY3JsMIGOBggrBgEF 711 BQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFydHNzbC5jb20v 712 c3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKGNmh0dHA6Ly93d3cuc3Rh 713 cnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVyLmNhLmNydDAjBgNVHRIE 714 HDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQEFBQADggEB 715 ACXj6SB59KRJPenn6gUdGEqcta97U769SATyiQ87i9er64qLwvIGLMa3o2Rcgl2Y 716 kghUeyLdN/EXyFBYA8L8uvZREPoc7EZukpT/ZDLXy9i2S0jkOxvF2fD/XLbcjGjM 717 iEYG1/6ASw0ri9C0k4oDDoJLCoeH9++yqF7SFCCMcDkJqiAGXNb4euDpa8vCCtEQ 718 CSS+ObZbfkreRt3cNCf5LfCXe9OsTnCfc8Cuq81c0oLaG+SmaLUQNBuToq8e9/Zm 719 +b+/a3RVjxmkV5OCcGVBxsXNDn54Q6wsdw0TBMcjwoEndzpLS7yWgFbbkq5ZiGpw 720 Qibb2+CfKuQ+WFV1GkVQmVA= 721 -----END CERTIFICATE-----` 722 723 const startComIntermediate = `-----BEGIN CERTIFICATE----- 724 MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW 725 MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg 726 Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh 727 dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB 728 jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT 729 IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0 730 YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB 731 IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE 732 gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA 733 pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv 734 kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/ 735 ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5 736 xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID 737 AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD 738 VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul 739 F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov 740 L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0 741 YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3 742 dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0 743 c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu 744 BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0 745 BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl 746 LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp 747 tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen 748 xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw 749 xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X 750 t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI 751 RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi 752 YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L 753 WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN 754 SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD 755 wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L 756 p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un 757 0q6Dp6jOW6c= 758 -----END CERTIFICATE-----` 759 760 const startComRoot = `-----BEGIN CERTIFICATE----- 761 MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW 762 MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg 763 Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh 764 dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 765 MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi 766 U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh 767 cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA 768 A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk 769 pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf 770 OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C 771 Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT 772 Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi 773 HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM 774 Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w 775 +2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ 776 Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 777 Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B 778 26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID 779 AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE 780 FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j 781 ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js 782 LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM 783 BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 784 Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy 785 dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh 786 cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh 787 YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg 788 dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp 789 bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ 790 YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT 791 TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ 792 9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 793 jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW 794 FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz 795 ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 796 ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L 797 EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu 798 L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq 799 yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC 800 O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V 801 um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh 802 NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= 803 -----END CERTIFICATE-----` 804 805 const smimeLeaf = `-----BEGIN CERTIFICATE----- 806 MIIIPDCCBiSgAwIBAgIQaMDxFS0pOMxZZeOBxoTJtjANBgkqhkiG9w0BAQsFADCB 807 nTELMAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMTowOAYDVQQLDDFB 808 WlogWml1cnRhZ2lyaSBwdWJsaWtvYSAtIENlcnRpZmljYWRvIHB1YmxpY28gU0NB 809 MTwwOgYDVQQDDDNFQUVrbyBIZXJyaSBBZG1pbmlzdHJhemlvZW4gQ0EgLSBDQSBB 810 QVBQIFZhc2NhcyAoMikwHhcNMTcwNzEyMDg1MzIxWhcNMjEwNzEyMDg1MzIxWjCC 811 AQwxDzANBgNVBAoMBklaRU5QRTE4MDYGA1UECwwvWml1cnRhZ2lyaSBrb3Jwb3Jh 812 dGlib2EtQ2VydGlmaWNhZG8gY29ycG9yYXRpdm8xQzBBBgNVBAsMOkNvbmRpY2lv 813 bmVzIGRlIHVzbyBlbiB3d3cuaXplbnBlLmNvbSBub2xhIGVyYWJpbGkgamFraXRl 814 a28xFzAVBgNVBC4TDi1kbmkgOTk5OTk5ODlaMSQwIgYDVQQDDBtDT1JQT1JBVElW 815 TyBGSUNUSUNJTyBBQ1RJVk8xFDASBgNVBCoMC0NPUlBPUkFUSVZPMREwDwYDVQQE 816 DAhGSUNUSUNJTzESMBAGA1UEBRMJOTk5OTk5ODlaMIIBIjANBgkqhkiG9w0BAQEF 817 AAOCAQ8AMIIBCgKCAQEAwVOMwUDfBtsH0XuxYnb+v/L774jMH8valX7RPH8cl2Lb 818 SiqSo0RchW2RGA2d1yuYHlpChC9jGmt0X/g66/E/+q2hUJlfJtqVDJFwtFYV4u2S 819 yzA3J36V4PRkPQrKxAsbzZriFXAF10XgiHQz9aVeMMJ9GBhmh9+DK8Tm4cMF6i8l 820 +AuC35KdngPF1x0ealTYrYZplpEJFO7CiW42aLi6vQkDR2R7nmZA4AT69teqBWsK 821 0DZ93/f0G/3+vnWwNTBF0lB6dIXoaz8OMSyHLqGnmmAtMrzbjAr/O/WWgbB/BqhR 822 qjJQ7Ui16cuDldXaWQ/rkMzsxmsAox0UF+zdQNvXUQIDAQABo4IDBDCCAwAwgccG 823 A1UdEgSBvzCBvIYVaHR0cDovL3d3dy5pemVucGUuY29tgQ9pbmZvQGl6ZW5wZS5j 824 b22kgZEwgY4xRzBFBgNVBAoMPklaRU5QRSBTLkEuIC0gQ0lGIEEwMTMzNzI2MC1S 825 TWVyYy5WaXRvcmlhLUdhc3RlaXogVDEwNTUgRjYyIFM4MUMwQQYDVQQJDDpBdmRh 826 IGRlbCBNZWRpdGVycmFuZW8gRXRvcmJpZGVhIDE0IC0gMDEwMTAgVml0b3JpYS1H 827 YXN0ZWl6MB4GA1UdEQQXMBWBE2ZpY3RpY2lvQGl6ZW5wZS5ldXMwDgYDVR0PAQH/ 828 BAQDAgXgMCkGA1UdJQQiMCAGCCsGAQUFBwMCBggrBgEFBQcDBAYKKwYBBAGCNxQC 829 AjAdBgNVHQ4EFgQUyeoOD4cgcljKY0JvrNuX2waFQLAwHwYDVR0jBBgwFoAUwKlK 830 90clh/+8taaJzoLSRqiJ66MwggEnBgNVHSAEggEeMIIBGjCCARYGCisGAQQB8zkB 831 AQEwggEGMDMGCCsGAQUFBwIBFidodHRwOi8vd3d3Lml6ZW5wZS5jb20vcnBhc2Nh 832 Y29ycG9yYXRpdm8wgc4GCCsGAQUFBwICMIHBGoG+Wml1cnRhZ2lyaWEgRXVza2Fs 833 IEF1dG9ub21pYSBFcmtpZGVnb2tvIHNla3RvcmUgcHVibGlrb2tvIGVyYWt1bmRl 834 ZW4gYmFybmUtc2FyZWV0YW4gYmFrYXJyaWsgZXJhYmlsIGRhaXRla2UuIFVzbyBy 835 ZXN0cmluZ2lkbyBhbCBhbWJpdG8gZGUgcmVkZXMgaW50ZXJuYXMgZGUgRW50aWRh 836 ZGVzIGRlbCBTZWN0b3IgUHVibGljbyBWYXNjbzAyBggrBgEFBQcBAQQmMCQwIgYI 837 KwYBBQUHMAGGFmh0dHA6Ly9vY3NwLml6ZW5wZS5jb20wOgYDVR0fBDMwMTAvoC2g 838 K4YpaHR0cDovL2NybC5pemVucGUuY29tL2NnaS1iaW4vY3JsaW50ZXJuYTIwDQYJ 839 KoZIhvcNAQELBQADggIBAIy5PQ+UZlCRq6ig43vpHwlwuD9daAYeejV0Q+ZbgWAE 840 GtO0kT/ytw95ZEJMNiMw3fYfPRlh27ThqiT0VDXZJDlzmn7JZd6QFcdXkCsiuv4+ 841 ZoXAg/QwnA3SGUUO9aVaXyuOIIuvOfb9MzoGp9xk23SMV3eiLAaLMLqwB5DTfBdt 842 BGI7L1MnGJBv8RfP/TL67aJ5bgq2ri4S8vGHtXSjcZ0+rCEOLJtmDNMnTZxancg3 843 /H5edeNd+n6Z48LO+JHRxQufbC4mVNxVLMIP9EkGUejlq4E4w6zb5NwCQczJbSWL 844 i31rk2orsNsDlyaLGsWZp3JSNX6RmodU4KAUPor4jUJuUhrrm3Spb73gKlV/gcIw 845 bCE7mML1Kss3x1ySaXsis6SZtLpGWKkW2iguPWPs0ydV6RPhmsCxieMwPPIJ87vS 846 5IejfgyBae7RSuAIHyNFy4uI5xwvwUFf6OZ7az8qtW7ImFOgng3Ds+W9k1S2CNTx 847 d0cnKTfA6IpjGo8EeHcxnIXT8NPImWaRj0qqonvYady7ci6U4m3lkNSdXNn1afgw 848 mYust+gxVtOZs1gk2MUCgJ1V1X+g7r/Cg7viIn6TLkLrpS1kS1hvMqkl9M+7XqPo 849 Qd95nJKOkusQpy99X4dF/lfbYAQnnjnqh3DLD2gvYObXFaAYFaiBKTiMTV2X72F+ 850 -----END CERTIFICATE-----` 851 852 const smimeIntermediate = `-----BEGIN CERTIFICATE----- 853 MIIHNzCCBSGgAwIBAgIQJMXIqlZvjuhMvqcFXOFkpDALBgkqhkiG9w0BAQswODEL 854 MAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMRMwEQYDVQQDDApJemVu 855 cGUuY29tMB4XDTEwMTAyMDA4MjMzM1oXDTM3MTIxMjIzMDAwMFowgZ0xCzAJBgNV 856 BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjE6MDgGA1UECwwxQVpaIFppdXJ0 857 YWdpcmkgcHVibGlrb2EgLSBDZXJ0aWZpY2FkbyBwdWJsaWNvIFNDQTE8MDoGA1UE 858 AwwzRUFFa28gSGVycmkgQWRtaW5pc3RyYXppb2VuIENBIC0gQ0EgQUFQUCBWYXNj 859 YXMgKDIpMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoIM7nEdI0N1h 860 rR5T4xuV/usKDoMIasaiKvfLhbwxaNtTt+a7W/6wV5bv3svQFIy3sUXjjdzV1nG2 861 To2wo/YSPQiOt8exWvOapvL21ogiof+kelWnXFjWaKJI/vThHYLgIYEMj/y4HdtU 862 ojI646rZwqsb4YGAopwgmkDfUh5jOhV2IcYE3TgJAYWVkj6jku9PLaIsHiarAHjD 863 PY8dig8a4SRv0gm5Yk7FXLmW1d14oxQBDeHZ7zOEXfpafxdEDO2SNaRJjpkh8XRr 864 PGqkg2y1Q3gT6b4537jz+StyDIJ3omylmlJsGCwqT7p8mEqjGJ5kC5I2VnjXKuNn 865 soShc72khWZVUJiJo5SGuAkNE2ZXqltBVm5Jv6QweQKsX6bkcMc4IZok4a+hx8FM 866 8IBpGf/I94pU6HzGXqCyc1d46drJgDY9mXa+6YDAJFl3xeXOOW2iGCfwXqhiCrKL 867 MYvyMZzqF3QH5q4nb3ZnehYvraeMFXJXDn+Utqp8vd2r7ShfQJz01KtM4hgKdgSg 868 jtW+shkVVN5ng/fPN85ovfAH2BHXFfHmQn4zKsYnLitpwYM/7S1HxlT61cdQ7Nnk 869 3LZTYEgAoOmEmdheklT40WAYakksXGM5VrzG7x9S7s1Tm+Vb5LSThdHC8bxxwyTb 870 KsDRDNJ84N9fPDO6qHnzaL2upQ43PycCAwEAAaOCAdkwggHVMIHHBgNVHREEgb8w 871 gbyGFWh0dHA6Ly93d3cuaXplbnBlLmNvbYEPaW5mb0BpemVucGUuY29tpIGRMIGO 872 MUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBBMDEzMzcyNjAtUk1lcmMuVml0 873 b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEGA1UECQw6QXZkYSBkZWwgTWVk 874 aXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEwIFZpdG9yaWEtR2FzdGVpejAP 875 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUwKlK90cl 876 h/+8taaJzoLSRqiJ66MwHwYDVR0jBBgwFoAUHRxlDqjyJXu0kc/ksbHmvVV0bAUw 877 OgYDVR0gBDMwMTAvBgRVHSAAMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly93d3cuaXpl 878 bnBlLmNvbS9jcHMwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8v 879 b2NzcC5pemVucGUuY29tOjgwOTQwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2Ny 880 bC5pemVucGUuY29tL2NnaS1iaW4vYXJsMjALBgkqhkiG9w0BAQsDggIBAMbjc3HM 881 3DG9ubWPkzsF0QsktukpujbTTcGk4h20G7SPRy1DiiTxrRzdAMWGjZioOP3/fKCS 882 M539qH0M+gsySNie+iKlbSZJUyE635T1tKw+G7bDUapjlH1xyv55NC5I6wCXGC6E 883 3TEP5B/E7dZD0s9E4lS511ubVZivFgOzMYo1DO96diny/N/V1enaTCpRl1qH1OyL 884 xUYTijV4ph2gL6exwuG7pxfRcVNHYlrRaXWfTz3F6NBKyULxrI3P/y6JAtN1GqT4 885 VF/+vMygx22n0DufGepBwTQz6/rr1ulSZ+eMnuJiTXgh/BzQnkUsXTb8mHII25iR 886 0oYF2qAsk6ecWbLiDpkHKIDHmML21MZE13MS8NSvTHoqJO4LyAmDe6SaeNHtrPlK 887 b6mzE1BN2ug+ZaX8wLA5IMPFaf0jKhb/Cxu8INsxjt00brsErCc9ip1VNaH0M4bi 888 1tGxfiew2436FaeyUxW7Pl6G5GgkNbuUc7QIoRy06DdU/U38BxW3uyJMY60zwHvS 889 FlKAn0OvYp4niKhAJwaBVN3kowmJuOU5Rid+TUnfyxbJ9cttSgzaF3hP/N4zgMEM 890 5tikXUskeckt8LUK96EH0QyssavAMECUEb/xrupyRdYWwjQGvNLq6T5+fViDGyOw 891 k+lzD44wofy8paAy9uC9Owae0zMEzhcsyRm7 892 -----END CERTIFICATE-----` 893 894 const smimeRoot = `-----BEGIN CERTIFICATE----- 895 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 896 MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 897 ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD 898 VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j 899 b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq 900 scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO 901 xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H 902 LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX 903 uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD 904 yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ 905 JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q 906 rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN 907 BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L 908 hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB 909 QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ 910 HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu 911 Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg 912 QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB 913 BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx 914 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC 915 AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA 916 A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb 917 laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 918 awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo 919 JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw 920 LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT 921 VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk 922 LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb 923 UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ 924 QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ 925 naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls 926 QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== 927 -----END CERTIFICATE-----` 928 929 var nameConstraintsLeaf = `-----BEGIN CERTIFICATE----- 930 MIIHMTCCBRmgAwIBAgIIIZaV/3ezOJkwDQYJKoZIhvcNAQEFBQAwgcsxCzAJBgNV 931 BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEj 932 MCEGA1UECxMaR2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1Zp 933 cmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0 934 eTExMC8GA1UEAxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZl 935 ciBDQTAeFw0xMzA5MTkxNDM2NTVaFw0xNTA5MTkxNDM2NTVaMIHNMQswCQYDVQQG 936 EwJVUzERMA8GA1UECAwIVmlyZ2luaWExEzARBgNVBAcMCkJsYWNrc2J1cmcxPDA6 937 BgNVBAoMM1ZpcmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUg 938 VW5pdmVyc2l0eTE7MDkGA1UECwwyVGVjaG5vbG9neS1lbmhhbmNlZCBMZWFybmlu 939 ZyBhbmQgT25saW5lIFN0cmF0ZWdpZXMxGzAZBgNVBAMMEnNlY3VyZS5pZGRsLnZ0 940 LmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkOyPpsOK/6IuPG 941 WnIBlVwlHzeYf+cUlggqkLq0b0+vZbiTXgio9/VCuNQ8opSoss7J7o3ygV9to+9Y 942 YwJKVC5WDT/y5JWpQey0CWILymViJnpNSwnxBc8A+Q8w5NUGDd/UhtPx/U8/hqbd 943 WPDYj2hbOqyq8UlRhfS5pwtnv6BbCTaY11I6FhCLK7zttISyTuWCf9p9o/ggiipP 944 ii/5oh4dkl+r5SfuSp5GPNHlYO8lWqys5NAPoDD4fc/kuflcK7Exx7XJ+Oqu0W0/ 945 psjEY/tES1ZgDWU/ParcxxFpFmKHbD5DXsfPOObzkVWXIY6tGMutSlE1Froy/Nn0 946 OZsAOrcCAwEAAaOCAhMwggIPMIG4BggrBgEFBQcBAQSBqzCBqDBYBggrBgEFBQcw 947 AoZMaHR0cDovL3d3dy5wa2kudnQuZWR1L2dsb2JhbHF1YWxpZmllZHNlcnZlci9j 948 YWNlcnQvZ2xvYmFscXVhbGlmaWVkc2VydmVyLmNydDBMBggrBgEFBQcwAYZAaHR0 949 cDovL3Z0Y2EtcC5lcHJvdi5zZXRpLnZ0LmVkdTo4MDgwL2VqYmNhL3B1YmxpY3dl 950 Yi9zdGF0dXMvb2NzcDAdBgNVHQ4EFgQUp7xbO6iHkvtZbPE4jmndmnAbSEcwDAYD 951 VR0TAQH/BAIwADAfBgNVHSMEGDAWgBS8YmAn1eM1SBfpS6tFatDIqHdxjDBqBgNV 952 HSAEYzBhMA4GDCsGAQQBtGgFAgICATAOBgwrBgEEAbRoBQICAQEwPwYMKwYBBAG0 953 aAUCAgMBMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9i 954 YWwvY3BzLzBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vd3d3LnBraS52dC5lZHUv 955 Z2xvYmFscXVhbGlmaWVkc2VydmVyL2NybC9jYWNybC5jcmwwDgYDVR0PAQH/BAQD 956 AgTwMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHREEFjAUghJz 957 ZWN1cmUuaWRkbC52dC5lZHUwDQYJKoZIhvcNAQEFBQADggIBAEgoYo4aUtatY3gI 958 OyyKp7QlIOaLbTJZywESHqy+L5EGDdJW2DJV+mcE0LDGvqa2/1Lo+AR1ntsZwfOi 959 Y718JwgVVaX/RCd5+QKP25c5/x72xI8hb/L1bgS0ED9b0YAhd7Qm1K1ot82+6mqX 960 DW6WiGeDr8Z07MQ3143qQe2rBlq+QI69DYzm2GOqAIAnUIWv7tCyLUm31b4DwmrJ 961 TeudVreTKUbBNB1TWRFHEPkWhjjXKZnNGRO11wHXcyBu6YekIvVZ+vmx8ePee4jJ 962 3GFOi7lMuWOeq57jTVL7KOKaKLVXBb6gqo5aq+Wwt8RUD5MakrCAEeQZj7DKaFmZ 963 oQCO0Pxrsl3InCGvxnGzT+bFVO9nJ/BAMj7hknFdm9Jr6Bg5q33Z+gnf909AD9QF 964 ESqUSykaHu2LVdJx2MaCH1CyKnRgMw5tEwE15EXpUjCm24m8FMOYC+rNtf18pgrz 965 5D8Jhh+oxK9PjcBYqXNtnioIxiMCYcV0q5d4w4BYFEh71tk7/bYB0R55CsBUVPmp 966 timWNOdRd57Tfpk3USaVsumWZAf9MP3wPiC7gb4d5tYEEAG5BuDT8ruFw838wU8G 967 1VvAVutSiYBg7k3NYO7AUqZ+Ax4klQX3aM9lgonmJ78Qt94UPtbptrfZ4/lSqEf8 968 GBUwDrQNTb+gsXsDkjd5lcYxNx6l 969 -----END CERTIFICATE-----` 970 971 var nameConstraintsIntermediate1 = `-----BEGIN CERTIFICATE----- 972 MIINLjCCDBagAwIBAgIRIqpyf/YoGgvHc8HiDAxAI8owDQYJKoZIhvcNAQEFBQAw 973 XDELMAkGA1UEBhMCQkUxFTATBgNVBAsTDFRydXN0ZWQgUm9vdDEZMBcGA1UEChMQ 974 R2xvYmFsU2lnbiBudi1zYTEbMBkGA1UEAxMSVHJ1c3RlZCBSb290IENBIEcyMB4X 975 DTEyMTIxMzAwMDAwMFoXDTE3MTIxMzAwMDAwMFowgcsxCzAJBgNVBAYTAlVTMREw 976 DwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEjMCEGA1UECxMa 977 R2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1ZpcmdpbmlhIFBv 978 bHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0eTExMC8GA1UE 979 AxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTCCAiIw 980 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALgIZhEaptBWADBqdJ45ueFGzMXa 981 GHnzNxoxR1fQIaaRQNdCg4cw3A4dWKMeEgYLtsp65ai3Xfw62Qaus0+KJ3RhgV+r 982 ihqK81NUzkls78fJlADVDI4fCTlothsrE1CTOMiy97jKHai5mVTiWxmcxpmjv7fm 983 5Nhc+uHgh2hIz6npryq495mD51ZrUTIaqAQN6Pw/VHfAmR524vgriTOjtp1t4lA9 984 pXGWjF/vkhAKFFheOQSQ00rngo2wHgCqMla64UTN0oz70AsCYNZ3jDLx0kOP0YmM 985 R3Ih91VA63kLqPXA0R6yxmmhhxLZ5bcyAy1SLjr1N302MIxLM/pSy6aquEnbELhz 986 qyp9yGgRyGJay96QH7c4RJY6gtcoPDbldDcHI9nXngdAL4DrZkJ9OkDkJLyqG66W 987 ZTF5q4EIs6yMdrywz0x7QP+OXPJrjYpbeFs6tGZCFnWPFfmHCRJF8/unofYrheq+ 988 9J7Jx3U55S/k57NXbAM1RAJOuMTlfn9Etf9Dpoac9poI4Liav6rBoUQk3N3JWqnV 989 HNx/NdCyJ1/6UbKMJUZsStAVglsi6lVPo289HHOE4f7iwl3SyekizVOp01wUin3y 990 cnbZB/rXmZbwapSxTTSBf0EIOr9i4EGfnnhCAVA9U5uLrI5OEB69IY8PNX0071s3 991 Z2a2fio5c8m3JkdrAgMBAAGjggh5MIIIdTAOBgNVHQ8BAf8EBAMCAQYwTAYDVR0g 992 BEUwQzBBBgkrBgEEAaAyATwwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv 993 YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wEgYDVR0TAQH/BAgwBgEB/wIBADCCBtAG 994 A1UdHgSCBscwggbDoIIGvzASghAzZGJsYWNrc2J1cmcub3JnMBiCFmFjY2VsZXJh 995 dGV2aXJnaW5pYS5jb20wGIIWYWNjZWxlcmF0ZXZpcmdpbmlhLm9yZzALgglhY3Zj 996 cC5vcmcwCYIHYmV2Lm5ldDAJggdiZXYub3JnMAuCCWNsaWdzLm9yZzAMggpjbWl3 997 ZWIub3JnMBeCFWVhc3Rlcm5icm9va3Ryb3V0Lm5ldDAXghVlYXN0ZXJuYnJvb2t0 998 cm91dC5vcmcwEYIPZWNvcnJpZG9ycy5pbmZvMBOCEWVkZ2FycmVzZWFyY2gub3Jn 999 MBKCEGdldC1lZHVjYXRlZC5jb20wE4IRZ2V0LWVkdWNhdGVkLmluZm8wEYIPZ2V0 1000 ZWR1Y2F0ZWQubmV0MBKCEGdldC1lZHVjYXRlZC5uZXQwEYIPZ2V0ZWR1Y2F0ZWQu 1001 b3JnMBKCEGdldC1lZHVjYXRlZC5vcmcwD4INaG9raWVjbHViLmNvbTAQgg5ob2tp 1002 ZXBob3RvLmNvbTAPgg1ob2tpZXNob3AuY29tMBGCD2hva2llc3BvcnRzLmNvbTAS 1003 ghBob2tpZXRpY2tldHMuY29tMBKCEGhvdGVscm9hbm9rZS5jb20wE4IRaHVtYW53 1004 aWxkbGlmZS5vcmcwF4IVaW5uYXR2aXJnaW5pYXRlY2guY29tMA+CDWlzY2hwMjAx 1005 MS5vcmcwD4INbGFuZHJlaGFiLm9yZzAggh5uYXRpb25hbHRpcmVyZXNlYXJjaGNl 1006 bnRlci5jb20wFYITbmV0d29ya3ZpcmdpbmlhLm5ldDAMggpwZHJjdnQuY29tMBiC 1007 FnBldGVkeWVyaXZlcmNvdXJzZS5jb20wDYILcmFkaW9pcS5vcmcwFYITcml2ZXJj 1008 b3Vyc2Vnb2xmLmNvbTALgglzZGltaS5vcmcwEIIOc292YW1vdGlvbi5jb20wHoIc 1009 c3VzdGFpbmFibGUtYmlvbWF0ZXJpYWxzLmNvbTAeghxzdXN0YWluYWJsZS1iaW9t 1010 YXRlcmlhbHMub3JnMBWCE3RoaXNpc3RoZWZ1dHVyZS5jb20wGIIWdGhpcy1pcy10 1011 aGUtZnV0dXJlLmNvbTAVghN0aGlzaXN0aGVmdXR1cmUubmV0MBiCFnRoaXMtaXMt 1012 dGhlLWZ1dHVyZS5uZXQwCoIIdmFkcy5vcmcwDIIKdmFsZWFmLm9yZzANggt2YXRl 1013 Y2guaW5mbzANggt2YXRlY2gubW9iaTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5n 1014 LmNvbTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5nLm5ldDAcghp2YXRlY2hsaWZl 1015 bG9uZ2xlYXJuaW5nLm9yZzAKggh2Y29tLmVkdTASghB2aXJnaW5pYXZpZXcubmV0 1016 MDSCMnZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVuaXZlcnNp 1017 dHkuY29tMDWCM3ZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVu 1018 aXZlcnNpdHkuaW5mbzA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0dXRlYW5k 1019 c3RhdGV1bml2ZXJzaXR5Lm5ldDA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0 1020 dXRlYW5kc3RhdGV1bml2ZXJzaXR5Lm9yZzAZghd2aXJnaW5pYXB1YmxpY3JhZGlv 1021 Lm9yZzASghB2aXJnaW5pYXRlY2guZWR1MBOCEXZpcmdpbmlhdGVjaC5tb2JpMByC 1022 GnZpcmdpbmlhdGVjaGZvdW5kYXRpb24ub3JnMAiCBnZ0LmVkdTALggl2dGFyYy5v 1023 cmcwDIIKdnQtYXJjLm9yZzALggl2dGNyYy5jb20wCoIIdnRpcC5vcmcwDIIKdnRs 1024 ZWFuLm9yZzAWghR2dGtub3dsZWRnZXdvcmtzLmNvbTAYghZ2dGxpZmVsb25nbGVh 1025 cm5pbmcuY29tMBiCFnZ0bGlmZWxvbmdsZWFybmluZy5uZXQwGIIWdnRsaWZlbG9u 1026 Z2xlYXJuaW5nLm9yZzATghF2dHNwb3J0c21lZGlhLmNvbTALggl2dHdlaS5jb20w 1027 D4INd2l3YXR3ZXJjLmNvbTAKggh3dnRmLm9yZzAIgQZ2dC5lZHUwd6R1MHMxCzAJ 1028 BgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVy 1029 ZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFuZCBT 1030 dGF0ZSBVbml2ZXJzaXR5MCcGA1UdJQQgMB4GCCsGAQUFBwMCBggrBgEFBQcDAQYI 1031 KwYBBQUHAwkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2NybC5nbG9iYWxzaWdu 1032 LmNvbS9ncy90cnVzdHJvb3RnMi5jcmwwgYQGCCsGAQUFBwEBBHgwdjAzBggrBgEF 1033 BQcwAYYnaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3RydXN0cm9vdGcyMD8G 1034 CCsGAQUFBzAChjNodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC90 1035 cnVzdHJvb3RnMi5jcnQwHQYDVR0OBBYEFLxiYCfV4zVIF+lLq0Vq0Miod3GMMB8G 1036 A1UdIwQYMBaAFBT25YsxtkWASkxt/MKHico2w5BiMA0GCSqGSIb3DQEBBQUAA4IB 1037 AQAyJm/lOB2Er4tHXhc/+fSufSzgjohJgYfMkvG4LknkvnZ1BjliefR8tTXX49d2 1038 SCDFWfGjqyJZwavavkl/4p3oXPG/nAMDMvxh4YAT+CfEK9HH+6ICV087kD4BLegi 1039 +aFJMj8MMdReWCzn5sLnSR1rdse2mo2arX3Uod14SW+PGrbUmTuWNyvRbz3fVmxp 1040 UdbGmj3laknO9YPsBGgHfv73pVVsTJkW4ZfY/7KdD/yaVv6ophpOB3coXfjl2+kd 1041 Z4ypn2zK+cx9IL/LSewqd/7W9cD55PCUy4X9OTbEmAccwiz3LB66mQoUGfdHdkoB 1042 jUY+v9vLQXmaVwI0AYL7g9LN 1043 -----END CERTIFICATE-----` 1044 1045 var nameConstraintsIntermediate2 = `-----BEGIN CERTIFICATE----- 1046 MIIEXTCCA0WgAwIBAgILBAAAAAABNuk6OrMwDQYJKoZIhvcNAQEFBQAwVzELMAkG 1047 A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv 1048 b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMjA0MjUxMTAw 1049 MDBaFw0yNzA0MjUxMTAwMDBaMFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVz 1050 dGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRy 1051 dXN0ZWQgUm9vdCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB 1052 AKyuvqrtcMr7g7EuNbu4sKwxM127UsCmx1RxbxxgcArGS7rjiefpBH/w4LYrymjf 1053 vcw1ueyMNoqLo9nJMz/ORXupb35NNfE667prQYHa+tTjl1IiKpB7QUwt3wXPuTMF 1054 Ja1tXtjKzkqJyuJlNuPKT76HcjgNqgV1s9qG44MD5I2JvI12du8zI1bgdQ+l/KsX 1055 kTfbGjUvhOLOlVNWVQDpL+YMIrGqgBYxy5TUNgrAcRtwpNdS2KkF5otSmMweVb5k 1056 hoUVv3u8UxQH/WWbNhHq1RrIlg/0rBUfi/ziShYFSB7U+aLx5DxPphTFBiDquQGp 1057 tB+FC4JvnukDStFihZCZ1R8CAwEAAaOCASMwggEfMA4GA1UdDwEB/wQEAwIBBjAP 1058 BgNVHRMBAf8EBTADAQH/MEcGA1UdIARAMD4wPAYEVR0gADA0MDIGCCsGAQUFBwIB 1059 FiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAdBgNVHQ4E 1060 FgQUFPblizG2RYBKTG38woeJyjbDkGIwMwYDVR0fBCwwKjAooCagJIYiaHR0cDov 1061 L2NybC5nbG9iYWxzaWduLm5ldC9yb290LmNybDA+BggrBgEFBQcBAQQyMDAwLgYI 1062 KwYBBQUHMAGGImh0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9yb290cjEwHwYD 1063 VR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZIhvcNAQEFBQADggEB 1064 AL7IG0l+k4LkcpI+a/kvZsSRwSM4uA6zGX34e78A2oytr8RG8bJwVb8+AHMUD+Xe 1065 2kYdh/Uj/waQXfqR0OgxQXL9Ct4ZM+JlR1avsNKXWL5AwYXAXCOB3J5PW2XOck7H 1066 Zw0vRbGQhjWjQx+B4KOUFg1b3ov/z6Xkr3yaCfRQhXh7KC0Bc0RXPPG5Nv5lCW+z 1067 tbbg0zMm3kyfQITRusMSg6IBsDJqOnjaiaKQRcXiD0Sk43ZXb2bUKMxC7+Td3QL4 1068 RyHcWJbQ7YylLTS/x+jxWIcOQ0oO5/54t5PTQ14neYhOz9x4gUk2AYAW6d1vePwb 1069 hcC8roQwkHT7HvfYBoc74FM= 1070 -----END CERTIFICATE-----` 1071 1072 var globalSignRoot = `-----BEGIN CERTIFICATE----- 1073 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG 1074 A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv 1075 b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw 1076 MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i 1077 YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT 1078 aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ 1079 jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp 1080 xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp 1081 1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG 1082 snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ 1083 U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 1084 9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E 1085 BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B 1086 AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz 1087 yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE 1088 38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP 1089 AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad 1090 DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME 1091 HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== 1092 -----END CERTIFICATE-----` 1093 1094 var moipLeafCert = `-----BEGIN CERTIFICATE----- 1095 MIIGQDCCBSigAwIBAgIRAPe/cwh7CUWizo8mYSDavLIwDQYJKoZIhvcNAQELBQAw 1096 gZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO 1097 BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYD 1098 VQQDEy9DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl 1099 ciBDQTAeFw0xMzA4MTUwMDAwMDBaFw0xNDA4MTUyMzU5NTlaMIIBQjEXMBUGA1UE 1100 BRMOMDg3MTg0MzEwMDAxMDgxEzARBgsrBgEEAYI3PAIBAxMCQlIxGjAYBgsrBgEE 1101 AYI3PAIBAhMJU2FvIFBhdWxvMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlv 1102 bjELMAkGA1UEBhMCQlIxETAPBgNVBBETCDAxNDUyMDAwMRIwEAYDVQQIEwlTYW8g 1103 UGF1bG8xEjAQBgNVBAcTCVNhbyBQYXVsbzEtMCsGA1UECRMkQXZlbmlkYSBCcmln 1104 YWRlaXJvIEZhcmlhIExpbWEgLCAyOTI3MR0wGwYDVQQKExRNb2lwIFBhZ2FtZW50 1105 b3MgUy5BLjENMAsGA1UECxMETU9JUDEYMBYGA1UECxMPU1NMIEJsaW5kYWRvIEVW 1106 MRgwFgYDVQQDEw9hcGkubW9pcC5jb20uYnIwggEiMA0GCSqGSIb3DQEBAQUAA4IB 1107 DwAwggEKAoIBAQDN0b9x6TrXXA9hPCF8/NjqGJ++2D4LO4ZiMFTjs0VwpXy2Y1Oe 1108 s74/HuiLGnAHxTmAtV7IpZMibiOcTxcnDYp9oEWkf+gR+hZvwFZwyOBC7wyb3SR3 1109 UvV0N1ZbEVRYpN9kuX/3vjDghjDmzzBwu8a/T+y5JTym5uiJlngVAWyh/RjtIvYi 1110 +NVkQMbyVlPGkoCe6c30pH8DKYuUCZU6DHjUsPTX3jAskqbhDSAnclX9iX0p2bmw 1111 KVBc+5Vh/2geyzDuquF0w+mNIYdU5h7uXvlmJnf3d2Cext5dxdL8/jezD3U0dAqI 1112 pYSKERbyxSkJWxdvRlhdpM9YXMJcpc88xNp1AgMBAAGjggHcMIIB2DAfBgNVHSME 1113 GDAWgBQ52v/KKBSKqHQTCLnkDqnS+n6daTAdBgNVHQ4EFgQU/lXuOa7DMExzZjRj 1114 LQWcMWGZY7swDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw 1115 FAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQUB 1116 MCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMFYG 1117 A1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JT 1118 QUV4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCBhwYIKwYBBQUH 1119 AQEEezB5MFEGCCsGAQUFBzAChkVodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01P 1120 RE9SU0FFeHRlbmRlZFZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5jcnQwJAYIKwYB 1121 BQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAvBgNVHREEKDAmgg9hcGku 1122 bW9pcC5jb20uYnKCE3d3dy5hcGkubW9pcC5jb20uYnIwDQYJKoZIhvcNAQELBQAD 1123 ggEBAFoTmPlaDcf+nudhjXHwud8g7/LRyA8ucb+3/vfmgbn7FUc1eprF5sJS1mA+ 1124 pbiTyXw4IxcJq2KUj0Nw3IPOe9k84mzh+XMmdCKH+QK3NWkE9Udz+VpBOBc0dlqC 1125 1RH5umStYDmuZg/8/r652eeQ5kUDcJyADfpKWBgDPYaGtwzKVT4h3Aok9SLXRHx6 1126 z/gOaMjEDMarMCMw4VUIG1pvNraZrG5oTaALPaIXXpd8VqbQYPudYJ6fR5eY3FeW 1127 H/ofbYFdRcuD26MfBFWE9VGGral9Fgo8sEHffho+UWhgApuQV4/l5fMzxB5YBXyQ 1128 jhuy8PqqZS9OuLilTeLu4a8z2JI= 1129 -----END CERTIFICATE-----` 1130 1131 var comodoIntermediateSHA384 = `-----BEGIN CERTIFICATE----- 1132 MIIGDjCCA/agAwIBAgIQBqdDgNTr/tQ1taP34Wq92DANBgkqhkiG9w0BAQwFADCB 1133 hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G 1134 A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV 1135 BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTIwMjEy 1136 MDAwMDAwWhcNMjcwMjExMjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgT 1137 EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR 1138 Q09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBSU0EgRXh0ZW5kZWQg 1139 VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC 1140 AQ8AMIIBCgKCAQEAlVbeVLTf1QJJe9FbXKKyHo+cK2JMK40SKPMalaPGEP0p3uGf 1141 CzhAk9HvbpUQ/OGQF3cs7nU+e2PsYZJuTzurgElr3wDqAwB/L3XVKC/sVmePgIOj 1142 vdwDmZOLlJFWW6G4ajo/Br0OksxgnP214J9mMF/b5pTwlWqvyIqvgNnmiDkBfBzA 1143 xSr3e5Wg8narbZtyOTDr0VdVAZ1YEZ18bYSPSeidCfw8/QpKdhQhXBZzQCMZdMO6 1144 WAqmli7eNuWf0MLw4eDBYuPCGEUZUaoXHugjddTI0JYT/8ck0YwLJ66eetw6YWNg 1145 iJctXQUL5Tvrrs46R3N2qPos3cCHF+msMJn4HwIDAQABo4IBaTCCAWUwHwYDVR0j 1146 BBgwFoAUu69+Aj36pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFDna/8ooFIqodBMI 1147 ueQOqdL6fp1pMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMD4G 1148 A1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5j 1149 b21vZG8uY29tL0NQUzBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9k 1150 b2NhLmNvbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggr 1151 BgEFBQcBAQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29t 1152 L0NPTU9ET1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz 1153 cC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAERCnUFRK0iIXZebeV4R 1154 AUpSGXtBLMeJPNBy3IX6WK/VJeQT+FhlZ58N/1eLqYVeyqZLsKeyLeCMIs37/3mk 1155 jCuN/gI9JN6pXV/kD0fQ22YlPodHDK4ixVAihNftSlka9pOlk7DgG4HyVsTIEFPk 1156 1Hax0VtpS3ey4E/EhOfUoFDuPPpE/NBXueEoU/1Tzdy5H3pAvTA/2GzS8+cHnx8i 1157 teoiccsq8FZ8/qyo0QYPFBRSTP5kKwxpKrgNUG4+BAe/eiCL+O5lCeHHSQgyPQ0o 1158 fkkdt0rvAucNgBfIXOBhYsvss2B5JdoaZXOcOBCgJjqwyBZ9kzEi7nQLiMBciUEA 1159 KKlHMd99SUWa9eanRRrSjhMQ34Ovmw2tfn6dNVA0BM7pINae253UqNpktNEvWS5e 1160 ojZh1CSggjMziqHRbO9haKPl0latxf1eYusVqHQSTC8xjOnB3xBLAer2VBvNfzu9 1161 XJ/B288ByvK6YBIhMe2pZLiySVgXbVrXzYxtvp5/4gJYp9vDLVj2dAZqmvZh+fYA 1162 tmnYOosxWd2R5nwnI4fdAw+PKowegwFOAWEMUnNt/AiiuSpm5HZNMaBWm9lTjaK2 1163 jwLI5jqmBNFI+8NKAnb9L9K8E7bobTQk+p0pisehKxTxlgBzuRPpwLk6R1YCcYAn 1164 pLwltum95OmYdBbxN4SBB7SC 1165 -----END CERTIFICATE-----` 1166 1167 const comodoRSAAuthority = `-----BEGIN CERTIFICATE----- 1168 MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv 1169 MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk 1170 ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF 1171 eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow 1172 gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO 1173 BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD 1174 VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq 1175 hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw 1176 AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6 1177 2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr 1178 ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt 1179 4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq 1180 m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/ 1181 vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT 1182 8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE 1183 IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO 1184 KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO 1185 GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/ 1186 s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g 1187 JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD 1188 AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9 1189 MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy 1190 bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6 1191 Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ 1192 zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj 1193 Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY 1194 Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5 1195 B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx 1196 PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR 1197 pu/xO28QOG8= 1198 -----END CERTIFICATE-----` 1199 1200 const addTrustRoot = `-----BEGIN CERTIFICATE----- 1201 MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU 1202 MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs 1203 IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 1204 MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux 1205 FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h 1206 bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v 1207 dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt 1208 H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 1209 uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX 1210 mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX 1211 a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN 1212 E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 1213 WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD 1214 VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 1215 Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU 1216 cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx 1217 IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN 1218 AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH 1219 YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 1220 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC 1221 Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX 1222 c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a 1223 mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= 1224 -----END CERTIFICATE-----` 1225 1226 const selfSigned = `-----BEGIN CERTIFICATE----- 1227 MIIC/DCCAeSgAwIBAgIRAK0SWRVmi67xU3z0gkgY+PkwDQYJKoZIhvcNAQELBQAw 1228 EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MTkxNjMzNDdaFw0xNzA4MTkxNjMz 1229 NDdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 1230 ggEKAoIBAQDWkm1kdCwxyKEt6OTmZitkmLGH8cQu9z7rUdrhW8lWNm4kh2SuaUWP 1231 pscBjda5iqg51aoKuWJR2rw6ElDne+X5eit2FT8zJgAU8v39lMFjbaVZfS9TFOYF 1232 w0Tk0Luo/PyKJpZnwhsP++iiGQiteJbndy8aLKmJ2MpLfpDGIgxEIyNb5dgoDi0D 1233 WReDCpE6K9WDYqvKVGnQ2Jvqqra6Gfx0tFkuqJxQuqA8aUOlPHcCH4KBZdNEoXdY 1234 YL3E4dCAh0YiDs80wNZx4cHqEM3L8gTEFqW2Tn1TSuPZO6gjJ9QPsuUZVjaMZuuO 1235 NVxqLGujZkDzARhC3fBpptMuaAfi20+BAgMBAAGjTTBLMA4GA1UdDwEB/wQEAwIF 1236 oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBYGA1UdEQQPMA2C 1237 C2Zvby5leGFtcGxlMA0GCSqGSIb3DQEBCwUAA4IBAQBPvvfnDhsHWt+/cfwdAVim 1238 4EDn+hYOMkTQwU0pouYIvY8QXYkZ8MBxpBtBMK4JhFU+ewSWoBAEH2dCCvx/BDxN 1239 UGTSJHMbsvJHcFvdmsvvRxOqQ/cJz7behx0cfoeHMwcs0/vWv8ms5wHesb5Ek7L0 1240 pl01FCBGTcncVqr6RK1r4fTpeCCfRIERD+YRJz8TtPH6ydesfLL8jIV40H8NiDfG 1241 vRAvOtNiKtPzFeQVdbRPOskC4rcHyPeiDAMAMixeLi63+CFty4da3r5lRezeedCE 1242 cw3ESZzThBwWqvPOtJdpXdm+r57pDW8qD+/0lY8wfImMNkQAyCUCLg/1Lxt/hrBj 1243 -----END CERTIFICATE-----` 1244 1245 const issuerSubjectMatchRoot = `-----BEGIN CERTIFICATE----- 1246 MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE 1247 ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNhMB4XDTE1MDEwMTAwMDAwMFoXDTI1 1248 MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNh 1249 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1 1250 siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw 1251 +QzGj+mz36NqhGxDWb6dstB2m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQD 1252 JKcNKCEpqa6UW0r5nwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYw 1253 FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIE 1254 EEA31wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAb4TfSeCZ1HFmHTKG 1255 VsvqWmsOAGrRWm4fBiMH/8vRGnTkJEMLqiqgc3Ulgry/P6n4SIis7TqUOw3TiMhn 1256 RGEz33Fsxa/tFoy/gvlJu+MqB1M2NyV33pGkdwl/b7KRWMQFieqO+uE7Ge/49pS3 1257 eyfm5ITdK/WT9TzYhsU4AVZcn20= 1258 -----END CERTIFICATE-----` 1259 1260 const issuerSubjectMatchLeaf = `-----BEGIN CERTIFICATE----- 1261 MIICODCCAaGgAwIBAgIJAOjwnT/iW+qmMA0GCSqGSIb3DQEBCwUAMCMxDzANBgNV 1262 BAoTBkdvbGFuZzEQMA4GA1UEAxMHUm9vdCBDQTAeFw0xNTAxMDEwMDAwMDBaFw0y 1263 NTAxMDEwMDAwMDBaMCAxDzANBgNVBAoTBkdvbGFuZzENMAsGA1UEAxMETGVhZjCB 1264 nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA20Z9ky4SJwZIvAYoIat+xLaiXf4e 1265 UkWIejZHpQgNkkJbwoHAvpd5mED7T20U/SsTi8KlLmfY1Ame1iI4t0oLdHMrwjTx 1266 0ZPlltl0e/NYn2xhPMCwQdTZKyskI3dbHDu9dV3OIFTPoWOHHR4kxPMdGlCLqrYU 1267 Q+2Xp3Vi9BTIUtcCAwEAAaN3MHUwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG 1268 CCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBCfkRYf 1269 Q0M+SabebbaA159gMBsGA1UdIwQUMBKAEEA31wH7QC+4HH5UBCeMWQEwDQYJKoZI 1270 hvcNAQELBQADgYEAjYYF2on1HcUWFEG5NIcrXDiZ49laW3pb3gtcCEUJbxydMV8I 1271 ynqjmdqDCyK+TwI1kU5dXDe/iSJYfTB20i/QoO53nnfA1hnr7KBjNWqAm4AagN5k 1272 vEA4PCJprUYmoj3q9MKSSRYDlq5kIbl87mSRR4GqtAwJKxIasvOvULOxziQ= 1273 -----END CERTIFICATE-----` 1274 1275 const x509v1TestRoot = `-----BEGIN CERTIFICATE----- 1276 MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE 1277 ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENBMB4XDTE1MDEwMTAwMDAwMFoXDTI1 1278 MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENB 1279 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1 1280 siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw 1281 +QzGj+mz36NqhGxDWb6dstB2m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQD 1282 JKcNKCEpqa6UW0r5nwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYw 1283 FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIE 1284 EEA31wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAcIwqeNUpQr9cOcYm 1285 YjpGpYkQ6b248xijCK7zI+lOeWN89zfSXn1AvfsC9pSdTMeDklWktbF/Ad0IN8Md 1286 h2NtN34ard0hEfHc8qW8mkXdsysVmq6cPvFYaHz+dBtkHuHDoy8YQnC0zdN/WyYB 1287 /1JmacUUofl+HusHuLkDxmadogI= 1288 -----END CERTIFICATE-----` 1289 1290 const x509v1TestIntermediate = `-----BEGIN CERTIFICATE----- 1291 MIIByjCCATMCCQCCdEMsT8ykqTANBgkqhkiG9w0BAQsFADAjMQ8wDQYDVQQKEwZH 1292 b2xhbmcxEDAOBgNVBAMTB1Jvb3QgQ0EwHhcNMTUwMTAxMDAwMDAwWhcNMjUwMTAx 1293 MDAwMDAwWjAwMQ8wDQYDVQQKEwZHb2xhbmcxHTAbBgNVBAMTFFguNTA5djEgaW50 1294 ZXJtZWRpYXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ2QyniAOT+5YL 1295 jeinEBJr3NsC/Q2QJ/VKmgvp+xRxuKTHJiVmxVijmp0vWg8AWfkmuE4p3hXQbbqM 1296 k5yxrk1n60ONhim2L4VXriEvCE7X2OXhTmBls5Ufr7aqIgPMikwjScCXwz8E8qI8 1297 UxyAhnjeJwMYBU8TuwBImSd4LBHoQQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAIab 1298 DRG6FbF9kL9jb/TDHkbVBk+sl/Pxi4/XjuFyIALlARgAkeZcPmL5tNW1ImHkwsHR 1299 zWE77kJDibzd141u21ZbLsKvEdUJXjla43bdyMmEqf5VGpC3D4sFt3QVH7lGeRur 1300 x5Wlq1u3YDL/j6s1nU2dQ3ySB/oP7J+vQ9V4QeM+ 1301 -----END CERTIFICATE-----` 1302 1303 const x509v1TestLeaf = `-----BEGIN CERTIFICATE----- 1304 MIICMzCCAZygAwIBAgIJAPo99mqJJrpJMA0GCSqGSIb3DQEBCwUAMDAxDzANBgNV 1305 BAoTBkdvbGFuZzEdMBsGA1UEAxMUWC41MDl2MSBpbnRlcm1lZGlhdGUwHhcNMTUw 1306 MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjArMQ8wDQYDVQQKEwZHb2xhbmcxGDAW 1307 BgNVBAMTD2Zvby5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC 1308 gYEApUh60Z+a5/oKJxG//Dn8CihSo2CJHNIIO3zEJZ1EeNSMZCynaIR6D3IPZEIR 1309 +RG2oGt+f5EEukAPYxwasp6VeZEezoQWJ+97nPCT6DpwLlWp3i2MF8piK2R9vxkG 1310 Z5n0+HzYk1VM8epIrZFUXSMGTX8w1y041PX/yYLxbdEifdcCAwEAAaNaMFgwDgYD 1311 VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNV 1312 HRMBAf8EAjAAMBkGA1UdDgQSBBBFozXe0SnzAmjy+1U6M/cvMA0GCSqGSIb3DQEB 1313 CwUAA4GBADYzYUvaToO/ucBskPdqXV16AaakIhhSENswYVSl97/sODaxsjishKq9 1314 5R7siu+JnIFotA7IbBe633p75xEnLN88X626N/XRFG9iScLzpj0o0PWXBUiB+fxL 1315 /jt8qszOXCv2vYdUTPNuPqufXLWMoirpuXrr1liJDmedCcAHepY/ 1316 -----END CERTIFICATE-----` 1317 1318 const ignoreCNWithSANRoot = `-----BEGIN CERTIFICATE----- 1319 MIIDPzCCAiegAwIBAgIIJkzCwkNrPHMwDQYJKoZIhvcNAQELBQAwMDEQMA4GA1UE 1320 ChMHVEVTVElORzEcMBoGA1UEAxMTKipUZXN0aW5nKiogUm9vdCBDQTAeFw0xNTAx 1321 MDEwMDAwMDBaFw0yNTAxMDEwMDAwMDBaMDAxEDAOBgNVBAoTB1RFU1RJTkcxHDAa 1322 BgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB 1323 DwAwggEKAoIBAQC4YAf5YqlXGcikvbMWtVrNICt+V/NNWljwfvSKdg4Inm7k6BwW 1324 P6y4Y+n4qSYIWNU4iRkdpajufzctxQCO6ty13iw3qVktzcC5XBIiS6ymiRhhDgnY 1325 VQqyakVGw9MxrPwdRZVlssUv3Hmy6tU+v5Ok31SLY5z3wKgYWvSyYs0b8bKNU8kf 1326 2FmSHnBN16lxGdjhe3ji58F/zFMr0ds+HakrLIvVdFcQFAnQopM8FTHpoWNNzGU3 1327 KaiO0jBbMFkd6uVjVnuRJ+xjuiqi/NWwiwQA+CEr9HKzGkxOF8nAsHamdmO1wW+w 1328 OsCrC0qWQ/f5NTOVATTJe0vj88OMTvo3071VAgMBAAGjXTBbMA4GA1UdDwEB/wQE 1329 AwICpDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUw 1330 AwEB/zAZBgNVHQ4EEgQQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOC 1331 AQEAGOn3XjxHyHbXLKrRmpwV447B7iNBXR5VlhwOgt1kWaHDL2+8f/9/h0HMkB6j 1332 fC+/yyuYVqYuOeavqMGVrh33D2ODuTQcFlOx5lXukP46j3j+Lm0jjZ1qNX7vlP8I 1333 VlUXERhbelkw8O4oikakwIY9GE8syuSgYf+VeBW/lvuAZQrdnPfabxe05Tre6RXy 1334 nJHMB1q07YHpbwIkcV/lfCE9pig2nPXTLwYZz9cl46Ul5RCpPUi+IKURo3x8y0FU 1335 aSLjI/Ya0zwUARMmyZ3RRGCyhIarPb20mKSaMf1/Nb23pS3k1QgmZhk5pAnXYsWu 1336 BJ6bvwEAasFiLGP6Zbdmxb2hIA== 1337 -----END CERTIFICATE-----` 1338 1339 const ignoreCNWithSANLeaf = `-----BEGIN CERTIFICATE----- 1340 MIIDaTCCAlGgAwIBAgIJAONakvRTxgJhMA0GCSqGSIb3DQEBCwUAMDAxEDAOBgNV 1341 BAoTB1RFU1RJTkcxHDAaBgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwHhcNMTUw 1342 MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjAsMRAwDgYDVQQKEwdURVNUSU5HMRgw 1343 FgYDVQQDEw9mb28uZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 1344 ggEKAoIBAQDBqskp89V/JMIBBqcauKSOVLcMyIE/t0jgSWVrsI4sksBTabLsfMdS 1345 ui2n+dHQ1dRBuw3o4g4fPrWwS3nMnV3pZUHEn2TPi5N1xkjTaxObXgKIY2GKmFP3 1346 rJ9vYqHT6mT4K93kCHoRcmJWWySc7S3JAOhTcdB4G+tIdQJN63E+XRYQQfNrn5HZ 1347 hxQoOzaguHFx+ZGSD4Ntk6BSZz5NfjqCYqYxe+iCpTpEEYhIpi8joSPSmkTMTxBW 1348 S1W2gXbYNQ9KjNkGM6FnQsUJrSPMrWs4v3UB/U88N5LkZeF41SqD9ySFGwbGajFV 1349 nyzj12+4K4D8BLhlOc0Eo/F/8GwOwvmxAgMBAAGjgYkwgYYwDgYDVR0PAQH/BAQD 1350 AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAA 1351 MBkGA1UdDgQSBBCjeab27q+5pV43jBGANOJ1MBsGA1UdIwQUMBKAEEA31wH7QC+4 1352 HH5UBCeMWQEwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAGZfZ 1353 ErTVxxpIg64s22mQpXSk/72THVQsfsKHzlXmztM0CJzH8ccoN67ZqKxJCfdiE/FI 1354 Emb6BVV4cGPeIKpcxaM2dwX/Y+Y0JaxpQJvqLxs+EByRL0gPP3shgg86WWCjYLxv 1355 AgOn862d/JXGDrC9vIlQ/DDQcyL5g0JV5UjG2G9TUigbnrXxBw7BoWK6wmoSaHnR 1356 sZKEHSs3RUJvm7qqpA9Yfzm9jg+i9j32zh1xFacghAOmFRFXa9eCVeigZ/KK2mEY 1357 j2kBQyvnyKsXHLAKUoUOpd6t/1PHrfXnGj+HmzZNloJ/BZ1kiWb4eLvMljoLGkZn 1358 xZbqP3Krgjj4XNaXjg== 1359 -----END CERTIFICATE-----` 1360 1361 const excludedNamesLeaf = `-----BEGIN CERTIFICATE----- 1362 MIID4DCCAsigAwIBAgIHDUSFtJknhzANBgkqhkiG9w0BAQsFADCBnjELMAkGA1UE 1363 BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU 1364 MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5 1365 ICgzNzM0NTE1NTYyODA2Mzk3KTEhMB8GA1UEAwwYSW50ZXJtZWRpYXRlIENBIGZv 1366 ciAzMzkyMB4XDTE3MDIwODIxMTUwNFoXDTE4MDIwODIwMjQ1OFowgZAxCzAJBgNV 1367 BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlMb3MgR2F0b3Mx 1368 FDASBgNVBAoMC05ldGZsaXggSW5jMS0wKwYDVQQLDCRQbGF0Zm9ybSBTZWN1cml0 1369 eSAoMzczNDUxNTc0ODUwMjY5NikxEzARBgNVBAMMCjE3Mi4xNi4wLjEwggEiMA0G 1370 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZ0oP1bMv6bOeqcKbzinnGpNOpenhA 1371 zdFFsgea62znWsH3Wg4+1Md8uPCqlaQIsaJQKZHc50eKD3bg0Io7c6kxHkBQr1b8 1372 Q7cGeK3CjdqG3NwS/aizzrLKOwL693hFwwy7JY7GGCvogbhyQRKn6iV0U9zMm7bu 1373 /9pQVV/wx8u01u2uAlLttjyQ5LJkxo5t8cATFVqxdN5J9eY//VSDiTwXnlpQITBP 1374 /Ow+zYuZ3kFlzH3CtCOhOEvNG3Ar1NvP3Icq35PlHV+Eki4otnKfixwByoiGpqCB 1375 UEIY04VrZJjwBxk08y/3jY2B3VLYGgi+rryyCxIqkB7UpSNPMMWSG4UpAgMBAAGj 1376 LzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0RBBYwFIIMYmVuZGVyLmxvY2FshwSsEAAB 1377 MA0GCSqGSIb3DQEBCwUAA4IBAQCLW3JO8L7LKByjzj2RciPjCGH5XF87Wd20gYLq 1378 sNKcFwCIeyZhnQy5aZ164a5G9AIk2HLvH6HevBFPhA9Ivmyv/wYEfnPd1VcFkpgP 1379 hDt8MCFJ8eSjCyKdtZh1MPMLrLVymmJV+Rc9JUUYM9TIeERkpl0rskcO1YGewkYt 1380 qKlWE+0S16+pzsWvKn831uylqwIb8ANBPsCX4aM4muFBHavSWAHgRO+P+yXVw8Q+ 1381 VQDnMHUe5PbZd1/+1KKVs1K/CkBCtoHNHp1d/JT+2zUQJphwja9CcgfFdVhSnHL4 1382 oEEOFtqVMIuQfR2isi08qW/JGOHc4sFoLYB8hvdaxKWSE19A 1383 -----END CERTIFICATE-----` 1384 1385 const excludedNamesIntermediate = `-----BEGIN CERTIFICATE----- 1386 MIIDzTCCArWgAwIBAgIHDUSFqYeczDANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UE 1387 BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU 1388 MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5 1389 ICgzNzM0NTE1NDc5MDY0NjAyKTEcMBoGA1UEAwwTTG9jYWwgUm9vdCBmb3IgMzM5 1390 MjAeFw0xNzAyMDgyMTE1MDRaFw0xODAyMDgyMDI0NThaMIGeMQswCQYDVQQGEwJV 1391 UzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJTG9zIEdhdG9zMRQwEgYD 1392 VQQKDAtOZXRmbGl4IEluYzEtMCsGA1UECwwkUGxhdGZvcm0gU2VjdXJpdHkgKDM3 1393 MzQ1MTU1NjI4MDYzOTcpMSEwHwYDVQQDDBhJbnRlcm1lZGlhdGUgQ0EgZm9yIDMz 1394 OTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCOyEs6tJ/t9emQTvlx 1395 3FS7uJSou5rKkuqVxZdIuYQ+B2ZviBYUnMRT9bXDB0nsVdKZdp0hdchdiwNXDG/I 1396 CiWu48jkcv/BdynVyayOT+0pOJSYLaPYpzBx1Pb9M5651ct9GSbj6Tz0ChVonoIE 1397 1AIZ0kkebucZRRFHd0xbAKVRKyUzPN6HJ7WfgyauUp7RmlC35wTmrmARrFohQLlL 1398 7oICy+hIQePMy9x1LSFTbPxZ5AUUXVC3eUACU3vLClF/Xs8XGHebZpUXCdMQjOGS 1399 nq1eFguFHR1poSB8uSmmLqm4vqUH9CDhEgiBAC8yekJ8//kZQ7lUEqZj3YxVbk+Y 1400 E4H5AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB 1401 ADxrnmNX5gWChgX9K5fYwhFDj5ofxZXAKVQk+WjmkwMcmCx3dtWSm++Wdksj/ZlA 1402 V1cLW3ohWv1/OAZuOlw7sLf98aJpX+UUmIYYQxDubq+4/q7VA7HzEf2k/i/oN1NI 1403 JgtrhpPcZ/LMO6k7DYx0qlfYq8pTSfd6MI4LnWKgLc+JSPJJjmvspgio2ZFcnYr7 1404 A264BwLo6v1Mos1o1JUvFFcp4GANlw0XFiWh7JXYRl8WmS5DoouUC+aNJ3lmyF6z 1405 LbIjZCSfgZnk/LK1KU1j91FI2bc2ULYZvAC1PAg8/zvIgxn6YM2Q7ZsdEgWw0FpS 1406 zMBX1/lk4wkFckeUIlkD55Y= 1407 -----END CERTIFICATE-----` 1408 1409 const excludedNamesRoot = `-----BEGIN CERTIFICATE----- 1410 MIIEGTCCAwGgAwIBAgIHDUSFpInn/zANBgkqhkiG9w0BAQsFADCBozELMAkGA1UE 1411 BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU 1412 MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5 1413 ICgzNzMxNTA5NDM3NDYyNDg1KTEmMCQGA1UEAwwdTmFtZSBDb25zdHJhaW50cyBU 1414 ZXN0IFJvb3QgQ0EwHhcNMTcwMjA4MjExNTA0WhcNMTgwMjA4MjAyNDU4WjCBmTEL 1415 MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBH 1416 YXRvczEUMBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNl 1417 Y3VyaXR5ICgzNzM0NTE1NDc5MDY0NjAyKTEcMBoGA1UEAwwTTG9jYWwgUm9vdCBm 1418 b3IgMzM5MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJymcnX29ekc 1419 7+MLyr8QuAzoHWznmGdDd2sITwWRjM89/21cdlHCGKSpULUNdFp9HDLWvYECtxt+ 1420 8TuzKiQz7qAerzGUT1zI5McIjHy0e/i4xIkfiBiNeTCuB/N9QRbZlcfM80ErkaA4 1421 gCAFK8qZAcWkHIl6e+KaQFMPLKk9kckgAnVDHEJe8oLNCogCJ15558b65g05p9eb 1422 5Lg+E98hoPRTQaDwlz3CZPfTTA2EiEZInSi8qzodFCbTpJUVTbiVUH/JtVjlibbb 1423 smdcx5PORK+8ZJkhLEh54AjaWOX4tB/7Tkk8stg2VBmrIARt/j4UVj7cTrIWU3bV 1424 m8TwHJG+YgsCAwEAAaNaMFgwDwYDVR0TAQH/BAUwAwEB/zBFBgNVHR4EPjA8oBww 1425 CocICgEAAP//AAAwDoIMYmVuZGVyLmxvY2FsoRwwCocICgEAAP//AAAwDoIMYmVu 1426 ZGVyLmxvY2FsMA0GCSqGSIb3DQEBCwUAA4IBAQAMjbheffPxtSKSv9NySW+8qmHs 1427 n7Mb5GGyCFu+cMZSoSaabstbml+zHEFJvWz6/1E95K4F8jKhAcu/CwDf4IZrSD2+ 1428 Hee0DolVSQhZpnHgPyj7ZATz48e3aJaQPUlhCEOh0wwF4Y0N4FV0t7R6woLylYRZ 1429 yU1yRHUqUYpN0DWFpsPbBqgM6uUAVO2ayBFhPgWUaqkmSbZ/Nq7isGvknaTmcIwT 1430 6mOAFN0qFb4RGzfGJW7x6z7KCULS7qVDp6fU3tRoScHFEgRubks6jzQ1W5ooSm4o 1431 +NQCZDd5eFeU8PpNX7rgaYE4GPq+EEmLVCBYmdctr8QVdqJ//8Xu3+1phjDy 1432 -----END CERTIFICATE-----` 1433 1434 const invalidCNRoot = `-----BEGIN CERTIFICATE----- 1435 MIIBFjCBvgIJAIsu4r+jb70UMAoGCCqGSM49BAMCMBQxEjAQBgNVBAsMCVRlc3Qg 1436 cm9vdDAeFw0xODA3MTExODMyMzVaFw0yODA3MDgxODMyMzVaMBQxEjAQBgNVBAsM 1437 CVRlc3Qgcm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF6oDgMg0LV6YhPj 1438 QXaPXYCc2cIyCdqp0ROUksRz0pOLTc5iY2nraUheRUD1vRRneq7GeXOVNn7uXONg 1439 oCGMjNwwCgYIKoZIzj0EAwIDRwAwRAIgDSiwgIn8g1lpruYH0QD1GYeoWVunfmrI 1440 XzZZl0eW/ugCICgOfXeZ2GGy3wIC0352BaC3a8r5AAb2XSGNe+e9wNN6 1441 -----END CERTIFICATE-----` 1442 1443 const validCNWithoutSAN = `-----BEGIN CERTIFICATE----- 1444 MIIBJzCBzwIUB7q8t9mrDAL+UB1OFaMN5BEWFKQwCgYIKoZIzj0EAwIwFDESMBAG 1445 A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4NDcyNFoXDTI4MDcwODE4NDcyNFow 1446 GjEYMBYGA1UEAwwPZm9vLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D 1447 AQcDQgAEp6Z8IjOnR38Iky1fYTUu2kVndvKXcxiwARJKGtW3b0E8uwVp9AZd/+sr 1448 p4ULTPdFToFAeqnGHbu62bkms8pQkDAKBggqhkjOPQQDAgNHADBEAiBTbNe3WWFR 1449 cqUYo0sNUuoV+tCTMDJUS+0PWIW4qBqCOwIgFHdLDn5PCk9kJpfc0O2qZx03hdq0 1450 h7olHCpY9yMRiz0= 1451 -----END CERTIFICATE-----` 1452 1453 const rootWithoutSKID = `-----BEGIN CERTIFICATE----- 1454 MIIBbzCCARSgAwIBAgIQeCkq3C8SOX/JM5PqYTl9cDAKBggqhkjOPQQDAjASMRAw 1455 DgYDVQQKEwdBY21lIENvMB4XDTE5MDIwNDIyNTYzNFoXDTI5MDIwMTIyNTYzNFow 1456 EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABISm 1457 jGlTr4dLOWT+BCTm2PzWRjk1DpLcSAh+Al8eB1Nc2eBWxYIH9qPirfatvqBOA4c5 1458 ZwycRpFoaw6O+EmXnVujTDBKMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr 1459 BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBIGA1UdEQQLMAmCB2V4YW1wbGUwCgYI 1460 KoZIzj0EAwIDSQAwRgIhAMaBYWFCjTfn0MNyQ0QXvYT/iIFompkIqzw6wB7qjLrA 1461 AiEA3sn65V7G4tsjZEOpN0Jykn9uiTjqniqn/S/qmv8gIec= 1462 -----END CERTIFICATE-----` 1463 1464 const leafWithAKID = `-----BEGIN CERTIFICATE----- 1465 MIIBjTCCATSgAwIBAgIRAPCKYvADhKLPaWOtcTu2XYwwCgYIKoZIzj0EAwIwEjEQ 1466 MA4GA1UEChMHQWNtZSBDbzAeFw0xOTAyMDQyMzA2NTJaFw0yOTAyMDEyMzA2NTJa 1467 MBMxETAPBgNVBAoTCEFjbWUgTExDMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE 1468 Wk5N+/8X97YT6ClFNIE5/4yc2YwKn921l0wrIJEcT2u+Uydm7EqtCJNtZjYMAnBd 1469 Acp/wynpTwC6tBTsxcM0s6NqMGgwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoG 1470 CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUwitfkXg0JglCjW9R 1471 ssWvTAveakIwEgYDVR0RBAswCYIHZXhhbXBsZTAKBggqhkjOPQQDAgNHADBEAiBk 1472 4LpWiWPOIl5PIhX9PDVkmjpre5oyoH/3aYwG8ABYuAIgCeSfbYueOOG2AdXuMqSU 1473 ZZMqeJS7JldLx91sPUArY5A= 1474 -----END CERTIFICATE-----` 1475 1476 const rootMatchingSKIDMismatchingSubject = `-----BEGIN CERTIFICATE----- 1477 MIIBQjCB6aADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQTAe 1478 Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMBExDzANBgNVBAMTBlJvb3Qg 1479 QTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPK4p1uXq2aAeDtKDHIokg2rTcPM 1480 2gq3N9Y96wiW6/7puBK1+INEW//cO9x6FpzkcsHw/TriAqy4sck/iDAvf9WjMjAw 1481 MA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHQ4EBQQDAQID 1482 MAoGCCqGSM49BAMCA0gAMEUCIQDgtAp7iVHxMnKxZPaLQPC+Tv2r7+DJc88k2SKH 1483 MPs/wQIgFjjNvBoQEl7vSHTcRGCCcFMdlN4l0Dqc9YwGa9fyrQs= 1484 -----END CERTIFICATE-----` 1485 1486 const rootMismatchingSKIDMatchingSubject = `-----BEGIN CERTIFICATE----- 1487 MIIBNDCB26ADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQjAe 1488 Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMBExDzANBgNVBAMTBlJvb3Qg 1489 QjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABI1YRFcIlkWzm9BdEVrIsEQJ2dT6 1490 qiW8/WV9GoIhmDtX9SEDHospc0Cgm+TeD2QYW2iMrS5mvNe4GSw0Jezg/bOjJDAi 1491 MA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNI 1492 ADBFAiEAukWOiuellx8bugRiwCS5XQ6IOJ1SZcjuZxj76WojwxkCIHqa71qNw8FM 1493 DtA5yoL9M2pDFF6ovFWnaCe+KlzSwAW/ 1494 -----END CERTIFICATE-----` 1495 1496 const leafMatchingAKIDMatchingIssuer = `-----BEGIN CERTIFICATE----- 1497 MIIBNTCB26ADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQjAe 1498 Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMA8xDTALBgNVBAMTBExlYWYw 1499 WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASNWERXCJZFs5vQXRFayLBECdnU+qol 1500 vP1lfRqCIZg7V/UhAx6LKXNAoJvk3g9kGFtojK0uZrzXuBksNCXs4P2zoyYwJDAO 1501 BgNVHSMEBzAFgAMBAgMwEgYDVR0RBAswCYIHZXhhbXBsZTAKBggqhkjOPQQDAgNJ 1502 ADBGAiEAnV9XV7a4h0nfJB8pWv+pBUXRlRFA2uZz3mXEpee8NYACIQCWa+wL70GL 1503 ePBQCV1F9sE2q4ZrnsT9TZoNrSe/bMDjzA== 1504 -----END CERTIFICATE-----` 1505 1506 var unknownAuthorityErrorTests = []struct { 1507 cert string 1508 expected string 1509 }{ 1510 {selfSignedWithCommonName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"test\")"}, 1511 {selfSignedNoCommonNameWithOrgName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"ca\")"}, 1512 {selfSignedNoCommonNameNoOrgName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"serial:0\")"}, 1513 } 1514 1515 func TestUnknownAuthorityError(t *testing.T) { 1516 for i, tt := range unknownAuthorityErrorTests { 1517 der, _ := pem.Decode([]byte(tt.cert)) 1518 if der == nil { 1519 t.Fatalf("#%d: Unable to decode PEM block", i) 1520 } 1521 c, err := ParseCertificate(der.Bytes) 1522 if err != nil { 1523 t.Errorf("#%d: Unable to parse certificate -> %v", i, err) 1524 } 1525 uae := &UnknownAuthorityError{ 1526 Cert: c, 1527 hintErr: fmt.Errorf("empty"), 1528 hintCert: c, 1529 } 1530 actual := uae.Error() 1531 if actual != tt.expected { 1532 t.Errorf("#%d: UnknownAuthorityError.Error() response invalid actual: %s expected: %s", i, actual, tt.expected) 1533 } 1534 } 1535 } 1536 1537 var nameConstraintTests = []struct { 1538 constraint, domain string 1539 expectError bool 1540 shouldMatch bool 1541 }{ 1542 {"", "anything.com", false, true}, 1543 {"example.com", "example.com", false, true}, 1544 {"example.com.", "example.com", true, false}, 1545 {"example.com", "example.com.", true, false}, 1546 {"example.com", "ExAmPle.coM", false, true}, 1547 {"example.com", "exampl1.com", false, false}, 1548 {"example.com", "www.ExAmPle.coM", false, true}, 1549 {"example.com", "sub.www.ExAmPle.coM", false, true}, 1550 {"example.com", "notexample.com", false, false}, 1551 {".example.com", "example.com", false, false}, 1552 {".example.com", "www.example.com", false, true}, 1553 {".example.com", "www..example.com", true, false}, 1554 } 1555 1556 func TestNameConstraints(t *testing.T) { 1557 for i, test := range nameConstraintTests { 1558 result, err := matchDomainConstraint(test.domain, test.constraint) 1559 1560 if err != nil && !test.expectError { 1561 t.Errorf("unexpected error for test #%d: domain=%s, constraint=%s, err=%s", i, test.domain, test.constraint, err) 1562 continue 1563 } 1564 1565 if err == nil && test.expectError { 1566 t.Errorf("unexpected success for test #%d: domain=%s, constraint=%s", i, test.domain, test.constraint) 1567 continue 1568 } 1569 1570 if result != test.shouldMatch { 1571 t.Errorf("unexpected result for test #%d: domain=%s, constraint=%s, result=%t", i, test.domain, test.constraint, result) 1572 } 1573 } 1574 } 1575 1576 const selfSignedWithCommonName = `-----BEGIN CERTIFICATE----- 1577 MIIDCjCCAfKgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL 1578 MAkGA1UEAxMCY2EwHhcNMTYwODI4MTcwOTE4WhcNMjEwODI3MTcwOTE4WjAcMQsw 1579 CQYDVQQKEwJjYTENMAsGA1UEAxMEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEP 1580 ADCCAQoCggEBAOH55PfRsbvmcabfLLko1w/yuapY/hk13Cgmc3WE/Z1ZStxGiVxY 1581 gQVH9n4W/TbUsrep/TmcC4MV7xEm5252ArcgaH6BeQ4QOTFj/6Jx0RT7U/ix+79x 1582 8RRysf7OlzNpGIctwZEM7i/G+0ZfqX9ULxL/EW9tppSxMX1jlXZQarnU7BERL5cH 1583 +G2jcbU9H28FXYishqpVYE9L7xrXMm61BAwvGKB0jcVW6JdhoAOSfQbbgp7JjIlq 1584 czXqUsv1UdORO/horIoJptynTvuARjZzyWatya6as7wyOgEBllE6BjPK9zpn+lp3 1585 tQ8dwKVqm/qBPhIrVqYG/Ec7pIv8mJfYabMCAwEAAaNZMFcwDgYDVR0PAQH/BAQD 1586 AgOoMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA 1587 MAoGA1UdDgQDBAEAMAwGA1UdIwQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBAAAM 1588 XMFphzq4S5FBcRdB2fRrmcoz+jEROBWvIH/1QUJeBEBz3ZqBaJYfBtQTvqCA5Rjw 1589 dxyIwVd1W3q3aSulM0tO62UCU6L6YeeY/eq8FmpD7nMJo7kCrXUUAMjxbYvS3zkT 1590 v/NErK6SgWnkQiPJBZNX1Q9+aSbLT/sbaCTdbWqcGNRuLGJkmqfIyoxRt0Hhpqsx 1591 jP5cBaVl50t4qoCuVIE9cOucnxYXnI7X5HpXWvu8Pfxo4SwVjb1az8Fk5s8ZnxGe 1592 fPB6Q3L/pKBe0SEe5GywpwtokPLB3lAygcuHbxp/1FlQ1NQZqq+vgXRIla26bNJf 1593 IuYkJwt6w+LH/9HZgf8= 1594 -----END CERTIFICATE-----` 1595 const selfSignedNoCommonNameWithOrgName = `-----BEGIN CERTIFICATE----- 1596 MIIC+zCCAeOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL 1597 MAkGA1UEAxMCY2EwHhcNMTYwODI4MTgxMzQ4WhcNMjEwODI3MTgxMzQ4WjANMQsw 1598 CQYDVQQKEwJjYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL5EjrUa 1599 7EtOMxWiIgTzp2FlQvncPsG329O3l3uNGnbigb8TmNMw2M8UhoDjd84pnU5RAfqd 1600 8t5TJyw/ybnIKBN131Q2xX+gPQ0dFyMvcO+i1CUgCxmYZomKVA2MXO1RD1hLTYGS 1601 gOVjc3no3MBwd8uVQp0NStqJ1QvLtNG4Uy+B28qe+ZFGGbjGqx8/CU4A8Szlpf7/ 1602 xAZR8w5qFUUlpA2LQYeHHJ5fQVXw7kyL1diNrKNi0G3qcY0IrBh++hT+hnEEXyXu 1603 g8a0Ux18hoE8D6rAr34rCZl6AWfqW5wjwm+N5Ns2ugr9U4N8uCKJYMPHb2CtdubU 1604 46IzVucpTfGLdaMCAwEAAaNZMFcwDgYDVR0PAQH/BAQDAgOoMB0GA1UdJQQWMBQG 1605 CCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMAoGA1UdDgQDBAEAMAwG 1606 A1UdIwQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBAEn5SgVpJ3zjsdzPqK7Qd/sB 1607 bYd1qtPHlrszjhbHBg35C6mDgKhcv4o6N+fuC+FojZb8lIxWzJtvT9pQbfy/V6u3 1608 wOb816Hm71uiP89sioIOKCvSAstj/p9doKDOUaKOcZBTw0PS2m9eja8bnleZzBvK 1609 rD8cNkHf74v98KvBhcwBlDifVzmkWzMG6TL1EkRXUyLKiWgoTUFSkCDV927oXXMR 1610 DKnszq+AVw+K8hbeV2A7GqT7YfeqOAvSbatTDnDtKOPmlCnQui8A149VgZzXv7eU 1611 29ssJSqjUPyp58dlV6ZuynxPho1QVZUOQgnJToXIQ3/5vIvJRXy52GJCs4/Gh/w= 1612 -----END CERTIFICATE-----` 1613 const selfSignedNoCommonNameNoOrgName = `-----BEGIN CERTIFICATE----- 1614 MIIC7jCCAdagAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL 1615 MAkGA1UEAxMCY2EwHhcNMTYwODI4MTgxOTQ1WhcNMjEwODI3MTgxOTQ1WjAAMIIB 1616 IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp3E+Jl6DpgzogHUW/i/AAcCM 1617 fnNJLOamNVKFGmmxhb4XTHxRaWoTzrlsyzIMS0WzivvJeZVe6mWbvuP2kZanKgIz 1618 35YXRTR9HbqkNTMuvnpUESzWxbGWE2jmt2+a/Jnz89FS4WIYRhF7nI2z8PvZOfrI 1619 2gETTT2tEpoF2S4soaYfm0DBeT8K0/rogAaf+oeUS6V+v3miRcAooJgpNJGu9kqm 1620 S0xKPn1RCFVjpiRd6YNS0xZirjYQIBMFBvoSoHjaOdgJptNRBprYPOxVJ/ItzGf0 1621 kPmzPFCx2tKfxV9HLYBPgxi+fP3IIx8aIYuJn8yReWtYEMYU11hDPeAFN5Gm+wID 1622 AQABo1kwVzAOBgNVHQ8BAf8EBAMCA6gwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG 1623 AQUFBwMBMAwGA1UdEwEB/wQCMAAwCgYDVR0OBAMEAQAwDAYDVR0jBAUwA4ABADAN 1624 BgkqhkiG9w0BAQsFAAOCAQEATZVOFeiCpPM5QysToLv+8k7Rjoqt6L5IxMUJGEpq 1625 4ENmldmwkhEKr9VnYEJY3njydnnTm97d9vOfnLj9nA9wMBODeOO3KL2uJR2oDnmM 1626 9z1NSe2aQKnyBb++DM3ZdikpHn/xEpGV19pYKFQVn35x3lpPh2XijqRDO/erKemb 1627 w67CoNRb81dy+4Q1lGpA8ORoLWh5fIq2t2eNGc4qB8vlTIKiESzAwu7u3sRfuWQi 1628 4R+gnfLd37FWflMHwztFbVTuNtPOljCX0LN7KcuoXYlr05RhQrmoN7fQHsrZMNLs 1629 8FVjHdKKu+uPstwd04Uy4BR/H2y1yerN9j/L6ZkMl98iiA== 1630 -----END CERTIFICATE-----` 1631 1632 const criticalExtRoot = `-----BEGIN CERTIFICATE----- 1633 MIIBqzCCAVGgAwIBAgIJAJ+mI/85cXApMAoGCCqGSM49BAMCMB0xDDAKBgNVBAoT 1634 A09yZzENMAsGA1UEAxMEUm9vdDAeFw0xNTAxMDEwMDAwMDBaFw0yNTAxMDEwMDAw 1635 MDBaMB0xDDAKBgNVBAoTA09yZzENMAsGA1UEAxMEUm9vdDBZMBMGByqGSM49AgEG 1636 CCqGSM49AwEHA0IABJGp9joiG2QSQA+1FczEDAsWo84rFiP3GTL+n+ugcS6TyNib 1637 gzMsdbJgVi+a33y0SzLZxB+YvU3/4KTk8yKLC+2jejB4MA4GA1UdDwEB/wQEAwIC 1638 BDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB 1639 /zAZBgNVHQ4EEgQQQDfXAftAL7gcflQEJ4xZATAbBgNVHSMEFDASgBBAN9cB+0Av 1640 uBx+VAQnjFkBMAoGCCqGSM49BAMCA0gAMEUCIFeSV00fABFceWR52K+CfIgOHotY 1641 FizzGiLB47hGwjMuAiEA8e0um2Kr8FPQ4wmFKaTRKHMaZizCGl3m+RG5QsE1KWo= 1642 -----END CERTIFICATE-----` 1643 1644 const criticalExtIntermediate = `-----BEGIN CERTIFICATE----- 1645 MIIBszCCAVmgAwIBAgIJAL2kcGZKpzVqMAoGCCqGSM49BAMCMB0xDDAKBgNVBAoT 1646 A09yZzENMAsGA1UEAxMEUm9vdDAeFw0xNTAxMDEwMDAwMDBaFw0yNTAxMDEwMDAw 1647 MDBaMCUxDDAKBgNVBAoTA09yZzEVMBMGA1UEAxMMSW50ZXJtZWRpYXRlMFkwEwYH 1648 KoZIzj0CAQYIKoZIzj0DAQcDQgAESqVq92iPEq01cL4o99WiXDc5GZjpjNlzMS1n 1649 rk8oHcVDp4tQRRQG3F4A6dF1rn/L923ha3b0fhDLlAvXZB+7EKN6MHgwDgYDVR0P 1650 AQH/BAQDAgIEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMB 1651 Af8EBTADAQH/MBkGA1UdDgQSBBCMGmiotXbbXVd7H40UsgajMBsGA1UdIwQUMBKA 1652 EEA31wH7QC+4HH5UBCeMWQEwCgYIKoZIzj0EAwIDSAAwRQIhAOhhNRb6KV7h3wbE 1653 cdap8bojzvUcPD78fbsQPCNw1jPxAiBOeAJhlTwpKn9KHpeJphYSzydj9NqcS26Y 1654 xXbdbm27KQ== 1655 -----END CERTIFICATE-----` 1656 1657 const criticalExtLeafWithExt = `-----BEGIN CERTIFICATE----- 1658 MIIBxTCCAWugAwIBAgIJAJZAUtw5ccb1MAoGCCqGSM49BAMCMCUxDDAKBgNVBAoT 1659 A09yZzEVMBMGA1UEAxMMSW50ZXJtZWRpYXRlMB4XDTE1MDEwMTAwMDAwMFoXDTI1 1660 MDEwMTAwMDAwMFowJDEMMAoGA1UEChMDT3JnMRQwEgYDVQQDEwtleGFtcGxlLmNv 1661 bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF3ABa2+B6gUyg6ayCaRQWYY/+No 1662 6PceLqEavZNUeVNuz7bS74Toy8I7R3bGMkMgbKpLSPlPTroAATvebTXoBaijgYQw 1663 gYEwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD 1664 AjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBBRNtBL2vq8nCV3qVp7ycxMMBsGA1Ud 1665 IwQUMBKAEIwaaKi1dttdV3sfjRSyBqMwCgYDUQMEAQH/BAAwCgYIKoZIzj0EAwID 1666 SAAwRQIgVjy8GBgZFiagexEuDLqtGjIRJQtBcf7lYgf6XFPH1h4CIQCT6nHhGo6E 1667 I+crEm4P5q72AnA/Iy0m24l7OvLuXObAmg== 1668 -----END CERTIFICATE-----` 1669 1670 const criticalExtIntermediateWithExt = `-----BEGIN CERTIFICATE----- 1671 MIIB2TCCAX6gAwIBAgIIQD3NrSZtcUUwCgYIKoZIzj0EAwIwHTEMMAoGA1UEChMD 1672 T3JnMQ0wCwYDVQQDEwRSb290MB4XDTE1MDEwMTAwMDAwMFoXDTI1MDEwMTAwMDAw 1673 MFowPTEMMAoGA1UEChMDT3JnMS0wKwYDVQQDEyRJbnRlcm1lZGlhdGUgd2l0aCBD 1674 cml0aWNhbCBFeHRlbnNpb24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQtnmzH 1675 mcRm10bdDBnJE7xQEJ25cLCL5okuEphRR0Zneo6+nQZikoh+UBbtt5GV3Dms7LeP 1676 oF5HOplYDCd8wi/wo4GHMIGEMA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggr 1677 BgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQKxdv 1678 UuQZ6sO3XvBsxgNZ3zAbBgNVHSMEFDASgBBAN9cB+0AvuBx+VAQnjFkBMAoGA1ED 1679 BAEB/wQAMAoGCCqGSM49BAMCA0kAMEYCIQCQzTPd6XKex+OAPsKT/1DsoMsg8vcG 1680 c2qZ4Q0apT/kvgIhAKu2TnNQMIUdcO0BYQIl+Uhxc78dc9h4lO+YJB47pHGx 1681 -----END CERTIFICATE-----` 1682 1683 const criticalExtLeaf = `-----BEGIN CERTIFICATE----- 1684 MIIBzzCCAXWgAwIBAgIJANoWFIlhCI9MMAoGCCqGSM49BAMCMD0xDDAKBgNVBAoT 1685 A09yZzEtMCsGA1UEAxMkSW50ZXJtZWRpYXRlIHdpdGggQ3JpdGljYWwgRXh0ZW5z 1686 aW9uMB4XDTE1MDEwMTAwMDAwMFoXDTI1MDEwMTAwMDAwMFowJDEMMAoGA1UEChMD 1687 T3JnMRQwEgYDVQQDEwtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH 1688 A0IABG1Lfh8A0Ho2UvZN5H0+ONil9c8jwtC0y0xIZftyQE+Fwr9XwqG3rV2g4M1h 1689 GnJa9lV9MPHg8+b85Hixm0ZSw7SjdzB1MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE 1690 FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAZBgNVHQ4EEgQQ 1691 UNhY4JhezH9gQYqvDMWrWDAbBgNVHSMEFDASgBArF29S5Bnqw7de8GzGA1nfMAoG 1692 CCqGSM49BAMCA0gAMEUCIQClA3d4tdrDu9Eb5ZBpgyC+fU1xTZB0dKQHz6M5fPZA 1693 2AIgN96lM+CPGicwhN24uQI6flOsO3H0TJ5lNzBYLtnQtlc= 1694 -----END CERTIFICATE-----` 1695 1696 func TestValidHostname(t *testing.T) { 1697 tests := []struct { 1698 host string 1699 validInput, validPattern bool 1700 }{ 1701 {host: "example.com", validInput: true, validPattern: true}, 1702 {host: "eXample123-.com", validInput: true, validPattern: true}, 1703 {host: "-eXample123-.com"}, 1704 {host: ""}, 1705 {host: "."}, 1706 {host: "example..com"}, 1707 {host: ".example.com"}, 1708 {host: "example.com.", validInput: true}, 1709 {host: "*.example.com."}, 1710 {host: "*.example.com", validPattern: true}, 1711 {host: "*foo.example.com"}, 1712 {host: "foo.*.example.com"}, 1713 {host: "exa_mple.com", validInput: true, validPattern: true}, 1714 {host: "foo,bar"}, 1715 {host: "project-dev:us-central1:main"}, 1716 } 1717 for _, tt := range tests { 1718 if got := validHostnamePattern(tt.host); got != tt.validPattern { 1719 t.Errorf("validHostnamePattern(%q) = %v, want %v", tt.host, got, tt.validPattern) 1720 } 1721 if got := validHostnameInput(tt.host); got != tt.validInput { 1722 t.Errorf("validHostnameInput(%q) = %v, want %v", tt.host, got, tt.validInput) 1723 } 1724 } 1725 } 1726 1727 func generateCert(cn string, isCA bool, issuer *x509.Certificate, issuerKey crypto.PrivateKey) (*Certificate, crypto.PrivateKey, error) { 1728 priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 1729 if err != nil { 1730 return nil, nil, err 1731 } 1732 1733 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 1734 serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit) 1735 1736 template := &x509.Certificate{ 1737 SerialNumber: serialNumber, 1738 Subject: pkix.Name{CommonName: cn}, 1739 NotBefore: time.Now().Add(-1 * time.Hour), 1740 NotAfter: time.Now().Add(24 * time.Hour), 1741 1742 KeyUsage: KeyUsageKeyEncipherment | KeyUsageDigitalSignature | KeyUsageCertSign, 1743 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, 1744 BasicConstraintsValid: true, 1745 IsCA: isCA, 1746 } 1747 if issuer == nil { 1748 issuer = template 1749 issuerKey = priv 1750 } 1751 1752 derBytes, err := CreateCertificate(rand.Reader, template, issuer, priv.Public(), issuerKey) 1753 if err != nil { 1754 return nil, nil, err 1755 } 1756 cert, err := ParseCertificate(derBytes) 1757 if err != nil { 1758 return nil, nil, err 1759 } 1760 1761 return cert, priv, nil 1762 } 1763 1764 func TestPathologicalChain(t *testing.T) { 1765 if testing.Short() { 1766 t.Skip("skipping generation of a long chain of certificates in short mode") 1767 } 1768 1769 // Build a chain where all intermediates share the same subject, to hit the 1770 // path building worst behavior. 1771 roots, intermediates := NewCertPool(), NewCertPool() 1772 1773 parent, parentKey, err := generateCert("Root CA", true, nil, nil) 1774 if err != nil { 1775 t.Fatal(err) 1776 } 1777 roots.AddCert(parent) 1778 1779 for i := 1; i < 100; i++ { 1780 parent, parentKey, err = generateCert("Intermediate CA", true, parent.asX509(), parentKey) 1781 if err != nil { 1782 t.Fatal(err) 1783 } 1784 intermediates.AddCert(parent) 1785 } 1786 1787 leaf, _, err := generateCert("Leaf", false, parent.asX509(), parentKey) 1788 if err != nil { 1789 t.Fatal(err) 1790 } 1791 1792 start := time.Now() 1793 _, err = leaf.Verify(VerifyOptions{ 1794 Roots: roots, 1795 Intermediates: intermediates, 1796 }) 1797 t.Logf("verification took %v", time.Since(start)) 1798 1799 if err == nil || !strings.Contains(err.Error(), "signature check attempts limit") { 1800 t.Errorf("expected verification to fail with a signature checks limit error; got %v", err) 1801 } 1802 } 1803 1804 func TestLongChain(t *testing.T) { 1805 if testing.Short() { 1806 t.Skip("skipping generation of a long chain of certificates in short mode") 1807 } 1808 1809 roots, intermediates := NewCertPool(), NewCertPool() 1810 1811 parent, parentKey, err := generateCert("Root CA", true, nil, nil) 1812 if err != nil { 1813 t.Fatal(err) 1814 } 1815 roots.AddCert(parent) 1816 1817 for i := 1; i < 15; i++ { 1818 name := fmt.Sprintf("Intermediate CA #%d", i) 1819 parent, parentKey, err = generateCert(name, true, parent.asX509(), parentKey) 1820 if err != nil { 1821 t.Fatal(err) 1822 } 1823 intermediates.AddCert(parent) 1824 } 1825 1826 leaf, _, err := generateCert("Leaf", false, parent.asX509(), parentKey) 1827 if err != nil { 1828 t.Fatal(err) 1829 } 1830 1831 start := time.Now() 1832 if _, err := leaf.Verify(VerifyOptions{ 1833 Roots: roots, 1834 Intermediates: intermediates, 1835 }); err != nil { 1836 t.Error(err) 1837 } 1838 t.Logf("verification took %v", time.Since(start)) 1839 } 1840 1841 func TestSystemRootsError(t *testing.T) { 1842 if runtime.GOOS == "windows" { 1843 t.Skip("Windows and darwin do not use (or support) systemRoots") 1844 } 1845 1846 defer func(oldSystemRoots *CertPool) { systemRoots = oldSystemRoots }(systemRootsPool()) 1847 1848 opts := VerifyOptions{ 1849 Intermediates: NewCertPool(), 1850 DNSName: "www.google.com", 1851 CurrentTime: time.Unix(1395785200, 0), 1852 } 1853 1854 if ok := opts.Intermediates.AppendCertsFromPEM([]byte(giag2Intermediate)); !ok { 1855 t.Fatalf("failed to parse intermediate") 1856 } 1857 1858 leaf, err := certificateFromPEM(googleLeaf) 1859 if err != nil { 1860 t.Fatalf("failed to parse leaf: %v", err) 1861 } 1862 1863 systemRoots = nil 1864 1865 _, err = leaf.Verify(opts) 1866 if _, ok := err.(x509.SystemRootsError); !ok { 1867 t.Errorf("error was not SystemRootsError: %v", err) 1868 } 1869 } 1870 1871 func TestSystemRootsErrorUnwrap(t *testing.T) { 1872 var err1 = errors.New("err1") 1873 err := x509.SystemRootsError{Err: err1} 1874 if !errors.Is(err, err1) { 1875 t.Error("errors.Is failed, wanted success") 1876 } 1877 } 1878 1879 func TestIssue51759(t *testing.T) { 1880 // badCertData contains a cert that we parse as valid 1881 // but that macOS SecCertificateCreateWithData rejects. 1882 const badCertData = "0\x82\x01U0\x82\x01\a\xa0\x03\x02\x01\x02\x02\x01\x020\x05\x06\x03+ep0R1P0N\x06\x03U\x04\x03\x13Gderpkey8dc58100b2493614ee1692831a461f3f4dd3f9b3b088e244f887f81b4906ac260\x1e\x17\r220112235755Z\x17\r220313235755Z0R1P0N\x06\x03U\x04\x03\x13Gderpkey8dc58100b2493614ee1692831a461f3f4dd3f9b3b088e244f887f81b4906ac260*0\x05\x06\x03+ep\x03!\x00bA\xd8e\xadW\xcb\xefZ\x89\xb5\"\x1eR\x9d\xba\x0e:\x1042Q@\u007f\xbd\xfb{ks\x04\xd1£\x020\x000\x05\x06\x03+ep\x03A\x00[\xa7\x06y\x86(\x94\x97\x9eLwA\x00\x01x\xaa\xbc\xbd Ê]\n(΅!ف0\xf5\x9a%I\x19<\xffo\xf1\xeaaf@\xb1\xa7\xaf\xfd\xe9R\xc7\x0f\x8d&\xd5\xfc\x0f;Ϙ\x82\x84a\xbc\r" 1883 badCert, err := ParseCertificate([]byte(badCertData)) 1884 if err != nil { 1885 t.Fatal(err) 1886 } 1887 1888 t.Run("leaf", func(t *testing.T) { 1889 opts := VerifyOptions{} 1890 _, err = badCert.Verify(opts) 1891 if err == nil { 1892 t.Fatal("expected error") 1893 } 1894 }) 1895 1896 goodCert, err := certificateFromPEM(googleLeaf) 1897 if err != nil { 1898 t.Fatal(err) 1899 } 1900 1901 t.Run("intermediate", func(t *testing.T) { 1902 opts := VerifyOptions{ 1903 Intermediates: NewCertPool(), 1904 } 1905 opts.Intermediates.AddCert(badCert) 1906 _, err = goodCert.Verify(opts) 1907 if err == nil { 1908 t.Fatal("expected error") 1909 } 1910 }) 1911 } 1912 1913 type trustGraphEdge struct { 1914 Issuer string 1915 Subject string 1916 Type int 1917 MutateTemplate func(*Certificate) 1918 Constraint func([]*Certificate) error 1919 } 1920 1921 type rootDescription struct { 1922 Subject string 1923 MutateTemplate func(*Certificate) 1924 Constraint func([]*Certificate) error 1925 } 1926 1927 type trustGraphDescription struct { 1928 Roots []rootDescription 1929 Leaf string 1930 Graph []trustGraphEdge 1931 } 1932 1933 func genCertEdge(t *testing.T, subject string, key crypto.Signer, mutateTmpl func(*Certificate), certType int, issuer *Certificate, signer crypto.Signer) *Certificate { 1934 t.Helper() 1935 1936 serial, err := rand.Int(rand.Reader, big.NewInt(100)) 1937 if err != nil { 1938 t.Fatalf("failed to generate test serial: %s", err) 1939 } 1940 tmpl := &Certificate{ 1941 SerialNumber: serial, 1942 Subject: pkix.Name{CommonName: subject}, 1943 NotBefore: time.Now().Add(-time.Hour), 1944 NotAfter: time.Now().Add(time.Hour), 1945 } 1946 if certType == rootCertificate || certType == intermediateCertificate { 1947 tmpl.IsCA, tmpl.BasicConstraintsValid = true, true 1948 tmpl.KeyUsage = KeyUsageCertSign 1949 } else if certType == leafCertificate { 1950 tmpl.DNSNames = []string{"localhost"} 1951 } 1952 if mutateTmpl != nil { 1953 mutateTmpl(tmpl) 1954 } 1955 1956 if certType == rootCertificate { 1957 issuer = tmpl 1958 signer = key 1959 } 1960 1961 d, err := CreateCertificate(rand.Reader, tmpl, issuer, key.Public(), signer) 1962 if err != nil { 1963 t.Fatalf("failed to generate test cert: %s", err) 1964 } 1965 c, err := ParseCertificate(d) 1966 if err != nil { 1967 t.Fatalf("failed to parse test cert: %s", err) 1968 } 1969 return c 1970 } 1971 1972 func buildTrustGraph(t *testing.T, d trustGraphDescription) (*CertPool, *CertPool, *Certificate) { 1973 t.Helper() 1974 1975 certs := map[string]*Certificate{} 1976 keys := map[string]crypto.Signer{} 1977 rootPool := NewCertPool() 1978 for _, r := range d.Roots { 1979 k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 1980 if err != nil { 1981 t.Fatalf("failed to generate test key: %s", err) 1982 } 1983 root := genCertEdge(t, r.Subject, k, r.MutateTemplate, rootCertificate, nil, nil) 1984 if r.Constraint != nil { 1985 rootPool.AddCertWithConstraint(root, r.Constraint) 1986 } else { 1987 rootPool.AddCert(root) 1988 } 1989 certs[r.Subject] = root 1990 keys[r.Subject] = k 1991 } 1992 1993 intermediatePool := NewCertPool() 1994 var leaf *Certificate 1995 for _, e := range d.Graph { 1996 issuerCert, ok := certs[e.Issuer] 1997 if !ok { 1998 t.Fatalf("unknown issuer %s", e.Issuer) 1999 } 2000 issuerKey, ok := keys[e.Issuer] 2001 if !ok { 2002 t.Fatalf("unknown issuer %s", e.Issuer) 2003 } 2004 2005 k, ok := keys[e.Subject] 2006 if !ok { 2007 var err error 2008 k, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 2009 if err != nil { 2010 t.Fatalf("failed to generate test key: %s", err) 2011 } 2012 keys[e.Subject] = k 2013 } 2014 cert := genCertEdge(t, e.Subject, k, e.MutateTemplate, e.Type, issuerCert, issuerKey) 2015 certs[e.Subject] = cert 2016 if e.Subject == d.Leaf { 2017 leaf = cert 2018 } else { 2019 if e.Constraint != nil { 2020 intermediatePool.AddCertWithConstraint(cert, e.Constraint) 2021 } else { 2022 intermediatePool.AddCert(cert) 2023 } 2024 } 2025 } 2026 2027 return rootPool, intermediatePool, leaf 2028 } 2029 2030 func chainsToStrings(chains [][]*Certificate) []string { 2031 chainStrings := []string{} 2032 for _, chain := range chains { 2033 names := []string{} 2034 for _, c := range chain { 2035 names = append(names, c.Subject.String()) 2036 } 2037 chainStrings = append(chainStrings, strings.Join(names, " -> ")) 2038 } 2039 sort.Strings(chainStrings) 2040 return chainStrings 2041 } 2042 2043 func TestPathBuilding(t *testing.T) { 2044 tests := []struct { 2045 name string 2046 graph trustGraphDescription 2047 expectedChains []string 2048 expectedErr string 2049 }{ 2050 { 2051 // Build the following graph from RFC 4158, figure 7 (note that in this graph edges represent 2052 // certificates where the parent is the issuer and the child is the subject.) For the certificate 2053 // C->B, use an unsupported ExtKeyUsage (in this case ExtKeyUsageCodeSigning) which invalidates 2054 // the path Trust Anchor -> C -> B -> EE. The remaining valid paths should be: 2055 // * Trust Anchor -> A -> B -> EE 2056 // * Trust Anchor -> C -> A -> B -> EE 2057 // 2058 // +---------+ 2059 // | Trust | 2060 // | Anchor | 2061 // +---------+ 2062 // | | 2063 // v v 2064 // +---+ +---+ 2065 // | A |<-->| C | 2066 // +---+ +---+ 2067 // | | 2068 // | +---+ | 2069 // +->| B |<-+ 2070 // +---+ 2071 // | 2072 // v 2073 // +----+ 2074 // | EE | 2075 // +----+ 2076 name: "bad EKU 1", 2077 graph: trustGraphDescription{ 2078 Roots: []rootDescription{{Subject: "root"}}, 2079 Leaf: "leaf", 2080 Graph: []trustGraphEdge{ 2081 { 2082 Issuer: "root", 2083 Subject: "inter a", 2084 Type: intermediateCertificate, 2085 }, 2086 { 2087 Issuer: "root", 2088 Subject: "inter c", 2089 Type: intermediateCertificate, 2090 }, 2091 { 2092 Issuer: "inter c", 2093 Subject: "inter a", 2094 Type: intermediateCertificate, 2095 }, 2096 { 2097 Issuer: "inter a", 2098 Subject: "inter c", 2099 Type: intermediateCertificate, 2100 }, 2101 { 2102 Issuer: "inter c", 2103 Subject: "inter b", 2104 Type: intermediateCertificate, 2105 MutateTemplate: func(t *Certificate) { 2106 t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageCodeSigning} 2107 }, 2108 }, 2109 { 2110 Issuer: "inter a", 2111 Subject: "inter b", 2112 Type: intermediateCertificate, 2113 }, 2114 { 2115 Issuer: "inter b", 2116 Subject: "leaf", 2117 Type: leafCertificate, 2118 }, 2119 }, 2120 }, 2121 expectedChains: []string{ 2122 "CN=leaf -> CN=inter b -> CN=inter a -> CN=inter c -> CN=root", 2123 "CN=leaf -> CN=inter b -> CN=inter a -> CN=root", 2124 }, 2125 }, 2126 { 2127 // Build the following graph from RFC 4158, figure 7 (note that in this graph edges represent 2128 // certificates where the parent is the issuer and the child is the subject.) For the certificate 2129 // C->B, use a unconstrained SAN which invalidates the path Trust Anchor -> C -> B -> EE. The 2130 // remaining valid paths should be: 2131 // * Trust Anchor -> A -> B -> EE 2132 // * Trust Anchor -> C -> A -> B -> EE 2133 // 2134 // +---------+ 2135 // | Trust | 2136 // | Anchor | 2137 // +---------+ 2138 // | | 2139 // v v 2140 // +---+ +---+ 2141 // | A |<-->| C | 2142 // +---+ +---+ 2143 // | | 2144 // | +---+ | 2145 // +->| B |<-+ 2146 // +---+ 2147 // | 2148 // v 2149 // +----+ 2150 // | EE | 2151 // +----+ 2152 name: "bad EKU 2", 2153 graph: trustGraphDescription{ 2154 Roots: []rootDescription{{Subject: "root"}}, 2155 Leaf: "leaf", 2156 Graph: []trustGraphEdge{ 2157 { 2158 Issuer: "root", 2159 Subject: "inter a", 2160 Type: intermediateCertificate, 2161 }, 2162 { 2163 Issuer: "root", 2164 Subject: "inter c", 2165 Type: intermediateCertificate, 2166 }, 2167 { 2168 Issuer: "inter c", 2169 Subject: "inter a", 2170 Type: intermediateCertificate, 2171 }, 2172 { 2173 Issuer: "inter a", 2174 Subject: "inter c", 2175 Type: intermediateCertificate, 2176 }, 2177 { 2178 Issuer: "inter c", 2179 Subject: "inter b", 2180 Type: intermediateCertificate, 2181 MutateTemplate: func(t *Certificate) { 2182 t.PermittedDNSDomains = []string{"good"} 2183 t.DNSNames = []string{"bad"} 2184 }, 2185 }, 2186 { 2187 Issuer: "inter a", 2188 Subject: "inter b", 2189 Type: intermediateCertificate, 2190 }, 2191 { 2192 Issuer: "inter b", 2193 Subject: "leaf", 2194 Type: leafCertificate, 2195 }, 2196 }, 2197 }, 2198 expectedChains: []string{ 2199 "CN=leaf -> CN=inter b -> CN=inter a -> CN=inter c -> CN=root", 2200 "CN=leaf -> CN=inter b -> CN=inter a -> CN=root", 2201 }, 2202 }, 2203 { 2204 // Build the following graph, we should find both paths: 2205 // * Trust Anchor -> A -> C -> EE 2206 // * Trust Anchor -> A -> B -> C -> EE 2207 // 2208 // +---------+ 2209 // | Trust | 2210 // | Anchor | 2211 // +---------+ 2212 // | 2213 // v 2214 // +---+ 2215 // | A | 2216 // +---+ 2217 // | | 2218 // | +----+ 2219 // | v 2220 // | +---+ 2221 // | | B | 2222 // | +---+ 2223 // | | 2224 // | +---v 2225 // v v 2226 // +---+ 2227 // | C | 2228 // +---+ 2229 // | 2230 // v 2231 // +----+ 2232 // | EE | 2233 // +----+ 2234 name: "all paths", 2235 graph: trustGraphDescription{ 2236 Roots: []rootDescription{{Subject: "root"}}, 2237 Leaf: "leaf", 2238 Graph: []trustGraphEdge{ 2239 { 2240 Issuer: "root", 2241 Subject: "inter a", 2242 Type: intermediateCertificate, 2243 }, 2244 { 2245 Issuer: "inter a", 2246 Subject: "inter b", 2247 Type: intermediateCertificate, 2248 }, 2249 { 2250 Issuer: "inter a", 2251 Subject: "inter c", 2252 Type: intermediateCertificate, 2253 }, 2254 { 2255 Issuer: "inter b", 2256 Subject: "inter c", 2257 Type: intermediateCertificate, 2258 }, 2259 { 2260 Issuer: "inter c", 2261 Subject: "leaf", 2262 Type: leafCertificate, 2263 }, 2264 }, 2265 }, 2266 expectedChains: []string{ 2267 "CN=leaf -> CN=inter c -> CN=inter a -> CN=root", 2268 "CN=leaf -> CN=inter c -> CN=inter b -> CN=inter a -> CN=root", 2269 }, 2270 }, 2271 { 2272 // Build the following graph, which contains a cross-signature loop 2273 // (A and C cross sign each other). Paths that include the A -> C -> A 2274 // (and vice versa) loop should be ignored, resulting in the paths: 2275 // * Trust Anchor -> A -> B -> EE 2276 // * Trust Anchor -> C -> B -> EE 2277 // * Trust Anchor -> A -> C -> B -> EE 2278 // * Trust Anchor -> C -> A -> B -> EE 2279 // 2280 // +---------+ 2281 // | Trust | 2282 // | Anchor | 2283 // +---------+ 2284 // | | 2285 // v v 2286 // +---+ +---+ 2287 // | A |<-->| C | 2288 // +---+ +---+ 2289 // | | 2290 // | +---+ | 2291 // +->| B |<-+ 2292 // +---+ 2293 // | 2294 // v 2295 // +----+ 2296 // | EE | 2297 // +----+ 2298 name: "ignore cross-sig loops", 2299 graph: trustGraphDescription{ 2300 Roots: []rootDescription{{Subject: "root"}}, 2301 Leaf: "leaf", 2302 Graph: []trustGraphEdge{ 2303 { 2304 Issuer: "root", 2305 Subject: "inter a", 2306 Type: intermediateCertificate, 2307 }, 2308 { 2309 Issuer: "root", 2310 Subject: "inter c", 2311 Type: intermediateCertificate, 2312 }, 2313 { 2314 Issuer: "inter c", 2315 Subject: "inter a", 2316 Type: intermediateCertificate, 2317 }, 2318 { 2319 Issuer: "inter a", 2320 Subject: "inter c", 2321 Type: intermediateCertificate, 2322 }, 2323 { 2324 Issuer: "inter c", 2325 Subject: "inter b", 2326 Type: intermediateCertificate, 2327 }, 2328 { 2329 Issuer: "inter a", 2330 Subject: "inter b", 2331 Type: intermediateCertificate, 2332 }, 2333 { 2334 Issuer: "inter b", 2335 Subject: "leaf", 2336 Type: leafCertificate, 2337 }, 2338 }, 2339 }, 2340 expectedChains: []string{ 2341 "CN=leaf -> CN=inter b -> CN=inter a -> CN=inter c -> CN=root", 2342 "CN=leaf -> CN=inter b -> CN=inter a -> CN=root", 2343 "CN=leaf -> CN=inter b -> CN=inter c -> CN=inter a -> CN=root", 2344 "CN=leaf -> CN=inter b -> CN=inter c -> CN=root", 2345 }, 2346 }, 2347 { 2348 // Build a simple two node graph, where the leaf is directly issued from 2349 // the root and both certificates have matching subject and public key, but 2350 // the leaf has SANs. 2351 name: "leaf with same subject, key, as parent but with SAN", 2352 graph: trustGraphDescription{ 2353 Roots: []rootDescription{{Subject: "root"}}, 2354 Leaf: "root", 2355 Graph: []trustGraphEdge{ 2356 { 2357 Issuer: "root", 2358 Subject: "root", 2359 Type: leafCertificate, 2360 MutateTemplate: func(c *Certificate) { 2361 c.DNSNames = []string{"localhost"} 2362 }, 2363 }, 2364 }, 2365 }, 2366 expectedChains: []string{ 2367 "CN=root -> CN=root", 2368 }, 2369 }, 2370 { 2371 // Build a basic graph with two paths from leaf to root, but the path passing 2372 // through C should be ignored, because it has invalid EKU nesting. 2373 name: "ignore invalid EKU path", 2374 graph: trustGraphDescription{ 2375 Roots: []rootDescription{{Subject: "root"}}, 2376 Leaf: "leaf", 2377 Graph: []trustGraphEdge{ 2378 { 2379 Issuer: "root", 2380 Subject: "inter a", 2381 Type: intermediateCertificate, 2382 }, 2383 { 2384 Issuer: "root", 2385 Subject: "inter c", 2386 Type: intermediateCertificate, 2387 }, 2388 { 2389 Issuer: "inter c", 2390 Subject: "inter b", 2391 Type: intermediateCertificate, 2392 MutateTemplate: func(t *Certificate) { 2393 t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageCodeSigning} 2394 }, 2395 }, 2396 { 2397 Issuer: "inter a", 2398 Subject: "inter b", 2399 Type: intermediateCertificate, 2400 MutateTemplate: func(t *Certificate) { 2401 t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageServerAuth} 2402 }, 2403 }, 2404 { 2405 Issuer: "inter b", 2406 Subject: "leaf", 2407 Type: leafCertificate, 2408 MutateTemplate: func(t *Certificate) { 2409 t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageServerAuth} 2410 }, 2411 }, 2412 }, 2413 }, 2414 expectedChains: []string{ 2415 "CN=leaf -> CN=inter b -> CN=inter a -> CN=root", 2416 }, 2417 }, 2418 { 2419 // A name constraint on the root should apply to any names that appear 2420 // on the intermediate, meaning there is no valid chain. 2421 name: "contrained root, invalid intermediate", 2422 graph: trustGraphDescription{ 2423 Roots: []rootDescription{ 2424 { 2425 Subject: "root", 2426 MutateTemplate: func(t *Certificate) { 2427 t.PermittedDNSDomains = []string{"example.com"} 2428 }, 2429 }, 2430 }, 2431 Leaf: "leaf", 2432 Graph: []trustGraphEdge{ 2433 { 2434 Issuer: "root", 2435 Subject: "inter", 2436 Type: intermediateCertificate, 2437 MutateTemplate: func(t *Certificate) { 2438 t.DNSNames = []string{"beep.com"} 2439 }, 2440 }, 2441 { 2442 Issuer: "inter", 2443 Subject: "leaf", 2444 Type: leafCertificate, 2445 MutateTemplate: func(t *Certificate) { 2446 t.DNSNames = []string{"www.example.com"} 2447 }, 2448 }, 2449 }, 2450 }, 2451 expectedErr: "x509: a root or intermediate certificate is not authorized to sign for this name: DNS name \"beep.com\" is not permitted by any constraint", 2452 }, 2453 { 2454 // A name constraint on the intermediate does not apply to the intermediate 2455 // itself, so this is a valid chain. 2456 name: "contrained intermediate, non-matching SAN", 2457 graph: trustGraphDescription{ 2458 Roots: []rootDescription{{Subject: "root"}}, 2459 Leaf: "leaf", 2460 Graph: []trustGraphEdge{ 2461 { 2462 Issuer: "root", 2463 Subject: "inter", 2464 Type: intermediateCertificate, 2465 MutateTemplate: func(t *Certificate) { 2466 t.DNSNames = []string{"beep.com"} 2467 t.PermittedDNSDomains = []string{"example.com"} 2468 }, 2469 }, 2470 { 2471 Issuer: "inter", 2472 Subject: "leaf", 2473 Type: leafCertificate, 2474 MutateTemplate: func(t *Certificate) { 2475 t.DNSNames = []string{"www.example.com"} 2476 }, 2477 }, 2478 }, 2479 }, 2480 expectedChains: []string{"CN=leaf -> CN=inter -> CN=root"}, 2481 }, 2482 { 2483 // A code constraint on the root, applying to one of two intermediates in the graph, should 2484 // result in only one valid chain. 2485 name: "code constrained root, two paths, one valid", 2486 graph: trustGraphDescription{ 2487 Roots: []rootDescription{{Subject: "root", Constraint: func(chain []*Certificate) error { 2488 for _, c := range chain { 2489 if c.Subject.CommonName == "inter a" { 2490 return errors.New("bad") 2491 } 2492 } 2493 return nil 2494 }}}, 2495 Leaf: "leaf", 2496 Graph: []trustGraphEdge{ 2497 { 2498 Issuer: "root", 2499 Subject: "inter a", 2500 Type: intermediateCertificate, 2501 }, 2502 { 2503 Issuer: "root", 2504 Subject: "inter b", 2505 Type: intermediateCertificate, 2506 }, 2507 { 2508 Issuer: "inter a", 2509 Subject: "inter c", 2510 Type: intermediateCertificate, 2511 }, 2512 { 2513 Issuer: "inter b", 2514 Subject: "inter c", 2515 Type: intermediateCertificate, 2516 }, 2517 { 2518 Issuer: "inter c", 2519 Subject: "leaf", 2520 Type: leafCertificate, 2521 }, 2522 }, 2523 }, 2524 expectedChains: []string{"CN=leaf -> CN=inter c -> CN=inter b -> CN=root"}, 2525 }, 2526 { 2527 // A code constraint on the root, applying to the only path, should result in an error. 2528 name: "code constrained root, one invalid path", 2529 graph: trustGraphDescription{ 2530 Roots: []rootDescription{{Subject: "root", Constraint: func(chain []*Certificate) error { 2531 for _, c := range chain { 2532 if c.Subject.CommonName == "leaf" { 2533 return errors.New("bad") 2534 } 2535 } 2536 return nil 2537 }}}, 2538 Leaf: "leaf", 2539 Graph: []trustGraphEdge{ 2540 { 2541 Issuer: "root", 2542 Subject: "inter", 2543 Type: intermediateCertificate, 2544 }, 2545 { 2546 Issuer: "inter", 2547 Subject: "leaf", 2548 Type: leafCertificate, 2549 }, 2550 }, 2551 }, 2552 expectedErr: "x509: certificate signed by unknown authority (possibly because of \"bad\" while trying to verify candidate authority certificate \"root\")", 2553 }, 2554 } 2555 2556 for _, tc := range tests { 2557 t.Run(tc.name, func(t *testing.T) { 2558 roots, intermediates, leaf := buildTrustGraph(t, tc.graph) 2559 chains, err := leaf.Verify(VerifyOptions{ 2560 Roots: roots, 2561 Intermediates: intermediates, 2562 }) 2563 if err != nil && err.Error() != tc.expectedErr { 2564 t.Fatalf("unexpected error: got %q, want %q", err, tc.expectedErr) 2565 } 2566 if len(tc.expectedChains) == 0 { 2567 return 2568 } 2569 gotChains := chainsToStrings(chains) 2570 if !reflect.DeepEqual(gotChains, tc.expectedChains) { 2571 t.Errorf("%s unexpected chains returned:\ngot:\n\t%s\nwant:\n\t%s", tc.name, strings.Join(gotChains, "\n\t"), strings.Join(tc.expectedChains, "\n\t")) 2572 } 2573 }) 2574 } 2575 } 2576 2577 func TestEKUEnforcement(t *testing.T) { 2578 type ekuDescs struct { 2579 EKUs []ExtKeyUsage 2580 Unknown []asn1.ObjectIdentifier 2581 } 2582 tests := []struct { 2583 name string 2584 root ekuDescs 2585 inters []ekuDescs 2586 leaf ekuDescs 2587 verifyEKUs []ExtKeyUsage 2588 err string 2589 }{ 2590 { 2591 name: "valid, full chain", 2592 root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2593 inters: []ekuDescs{{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}}, 2594 leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2595 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2596 }, 2597 { 2598 name: "valid, only leaf has EKU", 2599 root: ekuDescs{}, 2600 inters: []ekuDescs{{}}, 2601 leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2602 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2603 }, 2604 { 2605 name: "invalid, serverAuth not nested", 2606 root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}}, 2607 inters: []ekuDescs{{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}}, 2608 leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}, 2609 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2610 err: "x509: certificate specifies an incompatible key usage", 2611 }, 2612 { 2613 name: "valid, two EKUs, one path", 2614 root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2615 inters: []ekuDescs{{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}}, 2616 leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}, 2617 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}, 2618 }, 2619 { 2620 name: "invalid, ladder", 2621 root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2622 inters: []ekuDescs{ 2623 {EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}, 2624 {EKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}}, 2625 {EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}, 2626 {EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2627 }, 2628 leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2629 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}, 2630 err: "x509: certificate specifies an incompatible key usage", 2631 }, 2632 { 2633 name: "valid, intermediate has no EKU", 2634 root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2635 inters: []ekuDescs{{}}, 2636 leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2637 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2638 }, 2639 { 2640 name: "invalid, intermediate has no EKU and no nested path", 2641 root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}}, 2642 inters: []ekuDescs{{}}, 2643 leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2644 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}, 2645 err: "x509: certificate specifies an incompatible key usage", 2646 }, 2647 { 2648 name: "invalid, intermediate has unknown EKU", 2649 root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2650 inters: []ekuDescs{{Unknown: []asn1.ObjectIdentifier{{1, 2, 3}}}}, 2651 leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, 2652 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2653 err: "x509: certificate specifies an incompatible key usage", 2654 }, 2655 } 2656 2657 k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 2658 if err != nil { 2659 t.Fatalf("failed to generate test key: %s", err) 2660 } 2661 2662 for _, tc := range tests { 2663 t.Run(tc.name, func(t *testing.T) { 2664 rootPool := NewCertPool() 2665 root := genCertEdge(t, "root", k, func(c *Certificate) { 2666 c.ExtKeyUsage = tc.root.EKUs 2667 c.UnknownExtKeyUsage = tc.root.Unknown 2668 }, rootCertificate, nil, k) 2669 rootPool.AddCert(root) 2670 2671 parent := root 2672 interPool := NewCertPool() 2673 for i, interEKUs := range tc.inters { 2674 inter := genCertEdge(t, fmt.Sprintf("inter %d", i), k, func(c *Certificate) { 2675 c.ExtKeyUsage = interEKUs.EKUs 2676 c.UnknownExtKeyUsage = interEKUs.Unknown 2677 }, intermediateCertificate, parent, k) 2678 interPool.AddCert(inter) 2679 parent = inter 2680 } 2681 2682 leaf := genCertEdge(t, "leaf", k, func(c *Certificate) { 2683 c.ExtKeyUsage = tc.leaf.EKUs 2684 c.UnknownExtKeyUsage = tc.leaf.Unknown 2685 }, intermediateCertificate, parent, k) 2686 2687 _, err := leaf.Verify(VerifyOptions{Roots: rootPool, Intermediates: interPool, KeyUsages: tc.verifyEKUs}) 2688 if err == nil && tc.err != "" { 2689 t.Errorf("expected error") 2690 } else if err != nil && err.Error() != tc.err { 2691 t.Errorf("unexpected error: want %q, got %q", err.Error(), tc.err) 2692 } 2693 }) 2694 } 2695 } 2696 2697 func TestVerifyEKURootAsLeaf(t *testing.T) { 2698 k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 2699 if err != nil { 2700 t.Fatalf("failed to generate key: %s", err) 2701 } 2702 2703 for _, tc := range []struct { 2704 rootEKUs []ExtKeyUsage 2705 verifyEKUs []ExtKeyUsage 2706 succeed bool 2707 }{ 2708 { 2709 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2710 succeed: true, 2711 }, 2712 { 2713 rootEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2714 succeed: true, 2715 }, 2716 { 2717 rootEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2718 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2719 succeed: true, 2720 }, 2721 { 2722 rootEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2723 verifyEKUs: []ExtKeyUsage{ExtKeyUsageAny}, 2724 succeed: true, 2725 }, 2726 { 2727 rootEKUs: []ExtKeyUsage{ExtKeyUsageAny}, 2728 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2729 succeed: true, 2730 }, 2731 { 2732 rootEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}, 2733 verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 2734 succeed: false, 2735 }, 2736 } { 2737 t.Run(fmt.Sprintf("root EKUs %#v, verify EKUs %#v", tc.rootEKUs, tc.verifyEKUs), func(t *testing.T) { 2738 tmpl := &Certificate{ 2739 SerialNumber: big.NewInt(1), 2740 Subject: pkix.Name{CommonName: "root"}, 2741 NotBefore: time.Now().Add(-time.Hour), 2742 NotAfter: time.Now().Add(time.Hour), 2743 DNSNames: []string{"localhost"}, 2744 ExtKeyUsage: tc.rootEKUs, 2745 } 2746 rootDER, err := CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k) 2747 if err != nil { 2748 t.Fatalf("failed to create certificate: %s", err) 2749 } 2750 root, err := ParseCertificate(rootDER) 2751 if err != nil { 2752 t.Fatalf("failed to parse certificate: %s", err) 2753 } 2754 roots := NewCertPool() 2755 roots.AddCert(root) 2756 2757 _, err = root.Verify(VerifyOptions{Roots: roots, KeyUsages: tc.verifyEKUs}) 2758 if err == nil && !tc.succeed { 2759 t.Error("verification succeed") 2760 } else if err != nil && tc.succeed { 2761 t.Errorf("verification failed: %q", err) 2762 } 2763 }) 2764 } 2765 2766 } 2767 2768 func TestVerifyNilPubKey(t *testing.T) { 2769 c := &Certificate{ 2770 RawIssuer: []byte{1, 2, 3}, 2771 AuthorityKeyId: []byte{1, 2, 3}, 2772 } 2773 opts := &VerifyOptions{} 2774 opts.Roots = NewCertPool() 2775 r := &Certificate{ 2776 RawSubject: []byte{1, 2, 3}, 2777 SubjectKeyId: []byte{1, 2, 3}, 2778 } 2779 opts.Roots.AddCert(r) 2780 2781 _, err := c.buildChains([]*Certificate{r}, nil, opts) 2782 if _, ok := err.(UnknownAuthorityError); !ok { 2783 t.Fatalf("buildChains returned unexpected error, got: %v, want %v", err, UnknownAuthorityError{}) 2784 } 2785 } 2786 2787 func TestVerifyBareWildcard(t *testing.T) { 2788 k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 2789 if err != nil { 2790 t.Fatalf("failed to generate key: %s", err) 2791 } 2792 tmpl := &Certificate{ 2793 SerialNumber: big.NewInt(1), 2794 Subject: pkix.Name{CommonName: "test"}, 2795 NotBefore: time.Now().Add(-time.Hour), 2796 NotAfter: time.Now().Add(time.Hour), 2797 DNSNames: []string{"*"}, 2798 } 2799 cDER, err := CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k) 2800 if err != nil { 2801 t.Fatalf("failed to create certificate: %s", err) 2802 } 2803 c, err := ParseCertificate(cDER) 2804 if err != nil { 2805 t.Fatalf("failed to parse certificate: %s", err) 2806 } 2807 2808 if err := c.VerifyHostname("label"); err == nil { 2809 t.Fatalf("VerifyHostname unexpected success with bare wildcard SAN") 2810 } 2811 }