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