...

Source file src/github.com/letsencrypt/boulder/cmd/ceremony/cert_test.go

Documentation: github.com/letsencrypt/boulder/cmd/ceremony

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"crypto/rsa"
     7  	"crypto/x509"
     8  	"crypto/x509/pkix"
     9  	"encoding/asn1"
    10  	"encoding/hex"
    11  	"errors"
    12  	"fmt"
    13  	"io/fs"
    14  	"math/big"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/letsencrypt/boulder/pkcs11helpers"
    19  	"github.com/letsencrypt/boulder/test"
    20  	"github.com/miekg/pkcs11"
    21  )
    22  
    23  // samplePubkey returns a slice of bytes containing an encoded
    24  // SubjectPublicKeyInfo for an example public key.
    25  func samplePubkey() []byte {
    26  	pubKey, err := hex.DecodeString("3059301306072a8648ce3d020106082a8648ce3d03010703420004b06745ef0375c9c54057098f077964e18d3bed0aacd54545b16eab8c539b5768cc1cea93ba56af1e22a7a01c33048c8885ed17c9c55ede70649b707072689f5e")
    27  	if err != nil {
    28  		panic(err)
    29  	}
    30  	return pubKey
    31  }
    32  
    33  func realRand(_ pkcs11.SessionHandle, length int) ([]byte, error) {
    34  	r := make([]byte, length)
    35  	_, err := rand.Read(r)
    36  	return r, err
    37  }
    38  
    39  func TestParseOID(t *testing.T) {
    40  	_, err := parseOID("")
    41  	test.AssertError(t, err, "parseOID accepted an empty OID")
    42  	_, err = parseOID("a.b.c")
    43  	test.AssertError(t, err, "parseOID accepted an OID containing non-ints")
    44  	_, err = parseOID("1.0.2")
    45  	test.AssertError(t, err, "parseOID accepted an OID containing zero")
    46  	oid, err := parseOID("1.2.3")
    47  	test.AssertNotError(t, err, "parseOID failed with a valid OID")
    48  	test.Assert(t, oid.Equal(asn1.ObjectIdentifier{1, 2, 3}), "parseOID returned incorrect OID")
    49  }
    50  
    51  func TestMakeSubject(t *testing.T) {
    52  	profile := &certProfile{
    53  		CommonName:   "common name",
    54  		Organization: "organization",
    55  		Country:      "country",
    56  	}
    57  	expectedSubject := pkix.Name{
    58  		CommonName:   "common name",
    59  		Organization: []string{"organization"},
    60  		Country:      []string{"country"},
    61  	}
    62  	test.AssertDeepEquals(t, profile.Subject(), expectedSubject)
    63  }
    64  
    65  func TestMakeTemplateRoot(t *testing.T) {
    66  	s, ctx := pkcs11helpers.NewSessionWithMock()
    67  	profile := &certProfile{}
    68  	randReader := newRandReader(s)
    69  	pubKey := samplePubkey()
    70  	ctx.GenerateRandomFunc = realRand
    71  
    72  	profile.NotBefore = "1234"
    73  	_, err := makeTemplate(randReader, profile, pubKey, nil, rootCert)
    74  	test.AssertError(t, err, "makeTemplate didn't fail with invalid not before")
    75  
    76  	profile.NotBefore = "2018-05-18 11:31:00"
    77  	profile.NotAfter = "1234"
    78  	_, err = makeTemplate(randReader, profile, pubKey, nil, rootCert)
    79  	test.AssertError(t, err, "makeTemplate didn't fail with invalid not after")
    80  
    81  	profile.NotAfter = "2018-05-18 11:31:00"
    82  	profile.SignatureAlgorithm = "nope"
    83  	_, err = makeTemplate(randReader, profile, pubKey, nil, rootCert)
    84  	test.AssertError(t, err, "makeTemplate didn't fail with invalid signature algorithm")
    85  
    86  	profile.SignatureAlgorithm = "SHA256WithRSA"
    87  	ctx.GenerateRandomFunc = func(pkcs11.SessionHandle, int) ([]byte, error) {
    88  		return nil, errors.New("bad")
    89  	}
    90  	_, err = makeTemplate(randReader, profile, pubKey, nil, rootCert)
    91  	test.AssertError(t, err, "makeTemplate didn't fail when GenerateRandom failed")
    92  
    93  	ctx.GenerateRandomFunc = realRand
    94  
    95  	_, err = makeTemplate(randReader, profile, pubKey, nil, rootCert)
    96  	test.AssertError(t, err, "makeTemplate didn't fail with empty key usages")
    97  
    98  	profile.KeyUsages = []string{"asd"}
    99  	_, err = makeTemplate(randReader, profile, pubKey, nil, rootCert)
   100  	test.AssertError(t, err, "makeTemplate didn't fail with invalid key usages")
   101  
   102  	profile.KeyUsages = []string{"Digital Signature", "CRL Sign"}
   103  	profile.Policies = []policyInfoConfig{{}}
   104  	_, err = makeTemplate(randReader, profile, pubKey, nil, rootCert)
   105  	test.AssertError(t, err, "makeTemplate didn't fail with invalid (empty) policy OID")
   106  
   107  	profile.Policies = []policyInfoConfig{{OID: "1.2.3"}, {OID: "1.2.3.4"}}
   108  	profile.CommonName = "common name"
   109  	profile.Organization = "organization"
   110  	profile.Country = "country"
   111  	profile.OCSPURL = "ocsp"
   112  	profile.CRLURL = "crl"
   113  	profile.IssuerURL = "issuer"
   114  	cert, err := makeTemplate(randReader, profile, pubKey, nil, rootCert)
   115  	test.AssertNotError(t, err, "makeTemplate failed when everything worked as expected")
   116  	test.AssertEquals(t, cert.Subject.CommonName, profile.CommonName)
   117  	test.AssertEquals(t, len(cert.Subject.Organization), 1)
   118  	test.AssertEquals(t, cert.Subject.Organization[0], profile.Organization)
   119  	test.AssertEquals(t, len(cert.Subject.Country), 1)
   120  	test.AssertEquals(t, cert.Subject.Country[0], profile.Country)
   121  	test.AssertEquals(t, len(cert.OCSPServer), 1)
   122  	test.AssertEquals(t, cert.OCSPServer[0], profile.OCSPURL)
   123  	test.AssertEquals(t, len(cert.CRLDistributionPoints), 1)
   124  	test.AssertEquals(t, cert.CRLDistributionPoints[0], profile.CRLURL)
   125  	test.AssertEquals(t, len(cert.IssuingCertificateURL), 1)
   126  	test.AssertEquals(t, cert.IssuingCertificateURL[0], profile.IssuerURL)
   127  	test.AssertEquals(t, cert.KeyUsage, x509.KeyUsageDigitalSignature|x509.KeyUsageCRLSign)
   128  	test.AssertEquals(t, len(cert.PolicyIdentifiers), 2)
   129  	test.AssertEquals(t, len(cert.ExtKeyUsage), 0)
   130  
   131  	cert, err = makeTemplate(randReader, profile, pubKey, nil, intermediateCert)
   132  	test.AssertNotError(t, err, "makeTemplate failed when everything worked as expected")
   133  	test.Assert(t, cert.MaxPathLenZero, "MaxPathLenZero not set in intermediate template")
   134  	test.AssertEquals(t, len(cert.ExtKeyUsage), 2)
   135  	test.AssertEquals(t, cert.ExtKeyUsage[0], x509.ExtKeyUsageClientAuth)
   136  	test.AssertEquals(t, cert.ExtKeyUsage[1], x509.ExtKeyUsageServerAuth)
   137  }
   138  
   139  func TestMakeTemplateRestrictedCrossCertificate(t *testing.T) {
   140  	s, ctx := pkcs11helpers.NewSessionWithMock()
   141  	ctx.GenerateRandomFunc = realRand
   142  	randReader := newRandReader(s)
   143  	pubKey := samplePubkey()
   144  	profile := &certProfile{
   145  		SignatureAlgorithm: "SHA256WithRSA",
   146  		CommonName:         "common name",
   147  		Organization:       "organization",
   148  		Country:            "country",
   149  		KeyUsages:          []string{"Digital Signature", "CRL Sign"},
   150  		OCSPURL:            "ocsp",
   151  		CRLURL:             "crl",
   152  		IssuerURL:          "issuer",
   153  		NotAfter:           "2020-10-10 11:31:00",
   154  		NotBefore:          "2020-10-10 11:31:00",
   155  	}
   156  
   157  	tbcsCert := x509.Certificate{
   158  		SerialNumber: big.NewInt(666),
   159  		Subject: pkix.Name{
   160  			Organization: []string{"While Eek Ayote"},
   161  		},
   162  		NotBefore:             time.Now(),
   163  		NotAfter:              time.Now().Add(365 * 24 * time.Hour),
   164  		KeyUsage:              x509.KeyUsageDigitalSignature,
   165  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   166  		BasicConstraintsValid: true,
   167  	}
   168  
   169  	cert, err := makeTemplate(randReader, profile, pubKey, &tbcsCert, crossCert)
   170  	test.AssertNotError(t, err, "makeTemplate failed when everything worked as expected")
   171  	test.Assert(t, !cert.MaxPathLenZero, "MaxPathLenZero was set in cross-sign")
   172  	test.AssertEquals(t, len(cert.ExtKeyUsage), 1)
   173  	test.AssertEquals(t, cert.ExtKeyUsage[0], x509.ExtKeyUsageServerAuth)
   174  }
   175  
   176  func TestMakeTemplateOCSP(t *testing.T) {
   177  	s, ctx := pkcs11helpers.NewSessionWithMock()
   178  	ctx.GenerateRandomFunc = realRand
   179  	randReader := newRandReader(s)
   180  	profile := &certProfile{
   181  		SignatureAlgorithm: "SHA256WithRSA",
   182  		CommonName:         "common name",
   183  		Organization:       "organization",
   184  		Country:            "country",
   185  		OCSPURL:            "ocsp",
   186  		CRLURL:             "crl",
   187  		IssuerURL:          "issuer",
   188  		NotAfter:           "2018-05-18 11:31:00",
   189  		NotBefore:          "2018-05-18 11:31:00",
   190  	}
   191  	pubKey := samplePubkey()
   192  
   193  	cert, err := makeTemplate(randReader, profile, pubKey, nil, ocspCert)
   194  	test.AssertNotError(t, err, "makeTemplate failed")
   195  
   196  	test.Assert(t, !cert.IsCA, "IsCA is set")
   197  	// Check KU is only KeyUsageDigitalSignature
   198  	test.AssertEquals(t, cert.KeyUsage, x509.KeyUsageDigitalSignature)
   199  	// Check there is a single EKU with id-kp-OCSPSigning
   200  	test.AssertEquals(t, len(cert.ExtKeyUsage), 1)
   201  	test.AssertEquals(t, cert.ExtKeyUsage[0], x509.ExtKeyUsageOCSPSigning)
   202  	// Check ExtraExtensions contains a single id-pkix-ocsp-nocheck
   203  	hasExt := false
   204  	asnNULL := []byte{5, 0}
   205  	for _, ext := range cert.ExtraExtensions {
   206  		if ext.Id.Equal(oidOCSPNoCheck) {
   207  			if hasExt {
   208  				t.Error("template contains multiple id-pkix-ocsp-nocheck extensions")
   209  			}
   210  			hasExt = true
   211  			if !bytes.Equal(ext.Value, asnNULL) {
   212  				t.Errorf("id-pkix-ocsp-nocheck has unexpected content: want %x, got %x", asnNULL, ext.Value)
   213  			}
   214  		}
   215  	}
   216  	test.Assert(t, hasExt, "template doesn't contain id-pkix-ocsp-nocheck extensions")
   217  }
   218  
   219  func TestMakeTemplateCRL(t *testing.T) {
   220  	s, ctx := pkcs11helpers.NewSessionWithMock()
   221  	ctx.GenerateRandomFunc = realRand
   222  	randReader := newRandReader(s)
   223  	profile := &certProfile{
   224  		SignatureAlgorithm: "SHA256WithRSA",
   225  		CommonName:         "common name",
   226  		Organization:       "organization",
   227  		Country:            "country",
   228  		OCSPURL:            "ocsp",
   229  		CRLURL:             "crl",
   230  		IssuerURL:          "issuer",
   231  		NotAfter:           "2018-05-18 11:31:00",
   232  		NotBefore:          "2018-05-18 11:31:00",
   233  	}
   234  	pubKey := samplePubkey()
   235  
   236  	cert, err := makeTemplate(randReader, profile, pubKey, nil, crlCert)
   237  	test.AssertNotError(t, err, "makeTemplate failed")
   238  
   239  	test.Assert(t, !cert.IsCA, "IsCA is set")
   240  	test.AssertEquals(t, cert.KeyUsage, x509.KeyUsageCRLSign)
   241  }
   242  
   243  func TestVerifyProfile(t *testing.T) {
   244  	for _, tc := range []struct {
   245  		profile     certProfile
   246  		certType    []certType
   247  		expectedErr string
   248  	}{
   249  		{
   250  			profile:     certProfile{},
   251  			certType:    []certType{intermediateCert, crossCert},
   252  			expectedErr: "not-before is required",
   253  		},
   254  		{
   255  			profile: certProfile{
   256  				NotBefore: "a",
   257  			},
   258  			certType:    []certType{intermediateCert, crossCert},
   259  			expectedErr: "not-after is required",
   260  		},
   261  		{
   262  			profile: certProfile{
   263  				NotBefore: "a",
   264  				NotAfter:  "b",
   265  			},
   266  			certType:    []certType{intermediateCert, crossCert},
   267  			expectedErr: "signature-algorithm is required",
   268  		},
   269  		{
   270  			profile: certProfile{
   271  				NotBefore:          "a",
   272  				NotAfter:           "b",
   273  				SignatureAlgorithm: "c",
   274  			},
   275  			certType:    []certType{intermediateCert, crossCert},
   276  			expectedErr: "common-name is required",
   277  		},
   278  		{
   279  			profile: certProfile{
   280  				NotBefore:          "a",
   281  				NotAfter:           "b",
   282  				SignatureAlgorithm: "c",
   283  				CommonName:         "d",
   284  			},
   285  			certType:    []certType{intermediateCert, crossCert},
   286  			expectedErr: "organization is required",
   287  		},
   288  		{
   289  			profile: certProfile{
   290  				NotBefore:          "a",
   291  				NotAfter:           "b",
   292  				SignatureAlgorithm: "c",
   293  				CommonName:         "d",
   294  				Organization:       "e",
   295  			},
   296  			certType:    []certType{intermediateCert, crossCert},
   297  			expectedErr: "country is required",
   298  		},
   299  		{
   300  			profile: certProfile{
   301  				NotBefore:          "a",
   302  				NotAfter:           "b",
   303  				SignatureAlgorithm: "c",
   304  				CommonName:         "d",
   305  				Organization:       "e",
   306  				Country:            "f",
   307  				OCSPURL:            "g",
   308  			},
   309  			certType:    []certType{intermediateCert, crossCert},
   310  			expectedErr: "crl-url is required for subordinate CAs",
   311  		},
   312  		{
   313  			profile: certProfile{
   314  				NotBefore:          "a",
   315  				NotAfter:           "b",
   316  				SignatureAlgorithm: "c",
   317  				CommonName:         "d",
   318  				Organization:       "e",
   319  				Country:            "f",
   320  				OCSPURL:            "g",
   321  				CRLURL:             "h",
   322  			},
   323  			certType:    []certType{intermediateCert, crossCert},
   324  			expectedErr: "issuer-url is required for subordinate CAs",
   325  		},
   326  		{
   327  			profile: certProfile{
   328  				NotBefore:          "a",
   329  				NotAfter:           "b",
   330  				SignatureAlgorithm: "c",
   331  				CommonName:         "d",
   332  				Organization:       "e",
   333  				Country:            "f",
   334  				OCSPURL:            "g",
   335  				CRLURL:             "h",
   336  				IssuerURL:          "i",
   337  			},
   338  			certType:    []certType{intermediateCert, crossCert},
   339  			expectedErr: "policy should be exactly BRs domain-validated for subordinate CAs",
   340  		},
   341  		{
   342  			profile: certProfile{
   343  				NotBefore:          "a",
   344  				NotAfter:           "b",
   345  				SignatureAlgorithm: "c",
   346  				CommonName:         "d",
   347  				Organization:       "e",
   348  				Country:            "f",
   349  				OCSPURL:            "g",
   350  				CRLURL:             "h",
   351  				IssuerURL:          "i",
   352  				Policies:           []policyInfoConfig{{OID: "1.2.3"}, {OID: "4.5.6"}},
   353  			},
   354  			certType:    []certType{intermediateCert, crossCert},
   355  			expectedErr: "policy should be exactly BRs domain-validated for subordinate CAs",
   356  		},
   357  		{
   358  			profile: certProfile{
   359  				NotBefore:          "a",
   360  				NotAfter:           "b",
   361  				SignatureAlgorithm: "c",
   362  				CommonName:         "d",
   363  				Organization:       "e",
   364  				Country:            "f",
   365  			},
   366  			certType: []certType{rootCert},
   367  		},
   368  		{
   369  			profile: certProfile{
   370  				NotBefore:          "a",
   371  				NotAfter:           "b",
   372  				SignatureAlgorithm: "c",
   373  				CommonName:         "d",
   374  				Organization:       "e",
   375  				Country:            "f",
   376  				IssuerURL:          "g",
   377  				KeyUsages:          []string{"j"},
   378  			},
   379  			certType:    []certType{ocspCert},
   380  			expectedErr: "key-usages cannot be set for a delegated signer",
   381  		},
   382  		{
   383  			profile: certProfile{
   384  				NotBefore:          "a",
   385  				NotAfter:           "b",
   386  				SignatureAlgorithm: "c",
   387  				CommonName:         "d",
   388  				Organization:       "e",
   389  				Country:            "f",
   390  				IssuerURL:          "g",
   391  				CRLURL:             "i",
   392  			},
   393  			certType:    []certType{ocspCert},
   394  			expectedErr: "crl-url cannot be set for a delegated signer",
   395  		},
   396  		{
   397  			profile: certProfile{
   398  				NotBefore:          "a",
   399  				NotAfter:           "b",
   400  				SignatureAlgorithm: "c",
   401  				CommonName:         "d",
   402  				Organization:       "e",
   403  				Country:            "f",
   404  				IssuerURL:          "g",
   405  				OCSPURL:            "h",
   406  			},
   407  			certType:    []certType{ocspCert},
   408  			expectedErr: "ocsp-url cannot be set for a delegated signer",
   409  		},
   410  		{
   411  			profile: certProfile{
   412  				NotBefore:          "a",
   413  				NotAfter:           "b",
   414  				SignatureAlgorithm: "c",
   415  				CommonName:         "d",
   416  				Organization:       "e",
   417  				Country:            "f",
   418  				IssuerURL:          "g",
   419  			},
   420  			certType: []certType{ocspCert},
   421  		},
   422  		{
   423  			profile: certProfile{
   424  				NotBefore:          "a",
   425  				NotAfter:           "b",
   426  				SignatureAlgorithm: "c",
   427  				CommonName:         "d",
   428  				Organization:       "e",
   429  				Country:            "f",
   430  				IssuerURL:          "g",
   431  				KeyUsages:          []string{"j"},
   432  			},
   433  			certType:    []certType{crlCert},
   434  			expectedErr: "key-usages cannot be set for a delegated signer",
   435  		},
   436  		{
   437  			profile: certProfile{
   438  				NotBefore:          "a",
   439  				NotAfter:           "b",
   440  				SignatureAlgorithm: "c",
   441  				CommonName:         "d",
   442  				Organization:       "e",
   443  				Country:            "f",
   444  				IssuerURL:          "g",
   445  				CRLURL:             "i",
   446  			},
   447  			certType:    []certType{crlCert},
   448  			expectedErr: "crl-url cannot be set for a delegated signer",
   449  		},
   450  		{
   451  			profile: certProfile{
   452  				NotBefore:          "a",
   453  				NotAfter:           "b",
   454  				SignatureAlgorithm: "c",
   455  				CommonName:         "d",
   456  				Organization:       "e",
   457  				Country:            "f",
   458  				IssuerURL:          "g",
   459  				OCSPURL:            "h",
   460  			},
   461  			certType:    []certType{crlCert},
   462  			expectedErr: "ocsp-url cannot be set for a delegated signer",
   463  		},
   464  		{
   465  			profile: certProfile{
   466  				NotBefore:          "a",
   467  				NotAfter:           "b",
   468  				SignatureAlgorithm: "c",
   469  				CommonName:         "d",
   470  				Organization:       "e",
   471  				Country:            "f",
   472  				IssuerURL:          "g",
   473  			},
   474  			certType: []certType{crlCert},
   475  		},
   476  		{
   477  			profile: certProfile{
   478  				NotBefore: "a",
   479  			},
   480  			certType:    []certType{requestCert},
   481  			expectedErr: "not-before cannot be set for a CSR",
   482  		},
   483  		{
   484  			profile: certProfile{
   485  				NotAfter: "a",
   486  			},
   487  			certType:    []certType{requestCert},
   488  			expectedErr: "not-after cannot be set for a CSR",
   489  		},
   490  		{
   491  			profile: certProfile{
   492  				SignatureAlgorithm: "a",
   493  			},
   494  			certType:    []certType{requestCert},
   495  			expectedErr: "signature-algorithm cannot be set for a CSR",
   496  		},
   497  		{
   498  			profile: certProfile{
   499  				OCSPURL: "a",
   500  			},
   501  			certType:    []certType{requestCert},
   502  			expectedErr: "ocsp-url cannot be set for a CSR",
   503  		},
   504  		{
   505  			profile: certProfile{
   506  				CRLURL: "a",
   507  			},
   508  			certType:    []certType{requestCert},
   509  			expectedErr: "crl-url cannot be set for a CSR",
   510  		},
   511  		{
   512  			profile: certProfile{
   513  				IssuerURL: "a",
   514  			},
   515  			certType:    []certType{requestCert},
   516  			expectedErr: "issuer-url cannot be set for a CSR",
   517  		},
   518  		{
   519  			profile: certProfile{
   520  				Policies: []policyInfoConfig{{OID: "1.2.3"}},
   521  			},
   522  			certType:    []certType{requestCert},
   523  			expectedErr: "policies cannot be set for a CSR",
   524  		},
   525  		{
   526  			profile: certProfile{
   527  				KeyUsages: []string{"a"},
   528  			},
   529  			certType:    []certType{requestCert},
   530  			expectedErr: "key-usages cannot be set for a CSR",
   531  		},
   532  	} {
   533  		for _, ct := range tc.certType {
   534  			err := tc.profile.verifyProfile(ct)
   535  			if err != nil {
   536  				if tc.expectedErr != err.Error() {
   537  					t.Fatalf("Expected %q, got %q", tc.expectedErr, err.Error())
   538  				}
   539  			} else if tc.expectedErr != "" {
   540  				t.Fatalf("verifyProfile didn't fail, expected %q", tc.expectedErr)
   541  			}
   542  		}
   543  	}
   544  }
   545  
   546  func TestGenerateCSR(t *testing.T) {
   547  	profile := &certProfile{
   548  		CommonName:   "common name",
   549  		Organization: "organization",
   550  		Country:      "country",
   551  	}
   552  
   553  	signer, err := rsa.GenerateKey(rand.Reader, 1024)
   554  	test.AssertNotError(t, err, "failed to generate test key")
   555  
   556  	csrBytes, err := generateCSR(profile, &wrappedSigner{signer})
   557  	test.AssertNotError(t, err, "failed to generate CSR")
   558  
   559  	csr, err := x509.ParseCertificateRequest(csrBytes)
   560  	test.AssertNotError(t, err, "failed to parse CSR")
   561  	test.AssertNotError(t, csr.CheckSignature(), "CSR signature check failed")
   562  	test.AssertEquals(t, len(csr.Extensions), 0)
   563  
   564  	test.AssertEquals(t, csr.Subject.String(), fmt.Sprintf("CN=%s,O=%s,C=%s",
   565  		profile.CommonName, profile.Organization, profile.Country))
   566  }
   567  
   568  func TestLoadCert(t *testing.T) {
   569  	_, err := loadCert("../../test/hierarchy/int-e1.cert.pem")
   570  	test.AssertNotError(t, err, "should not have errored")
   571  
   572  	_, err = loadCert("/path/that/will/not/ever/exist/ever")
   573  	test.AssertError(t, err, "should have failed opening certificate at non-existent path")
   574  	test.AssertErrorIs(t, err, fs.ErrNotExist)
   575  
   576  	_, err = loadCert("../../test/hierarchy/int-e1.key.pem")
   577  	test.AssertError(t, err, "should have failed when trying to parse a private key")
   578  
   579  	_, err = loadCert("../../test/test-root.pubkey.pem")
   580  	test.AssertError(t, err, "should have failed when trying to parse a public key")
   581  }
   582  

View as plain text