1// Copyright 2009 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
5package x509
6
7import (
8	"bytes"
9	"crypto"
10	"crypto/dsa"
11	"crypto/ecdsa"
12	"crypto/ed25519"
13	"crypto/elliptic"
14	"crypto/rand"
15	"crypto/rsa"
16	_ "crypto/sha256"
17	_ "crypto/sha512"
18	"crypto/x509/pkix"
19	"encoding/asn1"
20	"encoding/base64"
21	"encoding/hex"
22	"encoding/pem"
23	"fmt"
24	"internal/testenv"
25	"io"
26	"math/big"
27	"net"
28	"net/url"
29	"os/exec"
30	"reflect"
31	"runtime"
32	"strings"
33	"testing"
34	"time"
35)
36
37func TestParsePKCS1PrivateKey(t *testing.T) {
38	block, _ := pem.Decode([]byte(pemPrivateKey))
39	priv, err := ParsePKCS1PrivateKey(block.Bytes)
40	if err != nil {
41		t.Errorf("Failed to parse private key: %s", err)
42		return
43	}
44	if priv.PublicKey.N.Cmp(rsaPrivateKey.PublicKey.N) != 0 ||
45		priv.PublicKey.E != rsaPrivateKey.PublicKey.E ||
46		priv.D.Cmp(rsaPrivateKey.D) != 0 ||
47		priv.Primes[0].Cmp(rsaPrivateKey.Primes[0]) != 0 ||
48		priv.Primes[1].Cmp(rsaPrivateKey.Primes[1]) != 0 {
49		t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey)
50	}
51
52	// This private key includes an invalid prime that
53	// rsa.PrivateKey.Validate should reject.
54	data := []byte("0\x16\x02\x00\x02\x02\u007f\x00\x02\x0200\x02\x0200\x02\x02\x00\x01\x02\x02\u007f\x00")
55	if _, err := ParsePKCS1PrivateKey(data); err == nil {
56		t.Errorf("parsing invalid private key did not result in an error")
57	}
58}
59
60func TestPKCS1MismatchPublicKeyFormat(t *testing.T) {
61
62	const pkixPublicKey = "30820122300d06092a864886f70d01010105000382010f003082010a0282010100dd5a0f37d3ca5232852ccc0e81eebec270e2f2c6c44c6231d852971a0aad00aa7399e9b9de444611083c59ea919a9d76c20a7be131a99045ec19a7bb452d647a72429e66b87e28be9e8187ed1d2a2a01ef3eb2360706bd873b07f2d1f1a72337aab5ec94e983e39107f52c480d404915e84d75a3db2cfd601726a128cb1d7f11492d4bdb53272e652276667220795c709b8a9b4af6489cbf48bb8173b8fb607c834a71b6e8bf2d6aab82af3c8ad7ce16d8dcf58373a6edc427f7484d09744d4c08f4e19ed07adbf6cb31243bc5d0d1145e77a08a6fc5efd208eca67d6abf2d6f38f58b6fdd7c28774fb0cc03fc4935c6e074842d2e1479d3d8787249258719f90203010001"
63	const errorContains = "use ParsePKIXPublicKey instead"
64	derBytes, _ := hex.DecodeString(pkixPublicKey)
65	_, err := ParsePKCS1PublicKey(derBytes)
66	if !strings.Contains(err.Error(), errorContains) {
67		t.Errorf("expected error containing %q, got %s", errorContains, err)
68	}
69}
70
71func testParsePKIXPublicKey(t *testing.T, pemBytes string) (pub any) {
72	block, _ := pem.Decode([]byte(pemBytes))
73	pub, err := ParsePKIXPublicKey(block.Bytes)
74	if err != nil {
75		t.Fatalf("Failed to parse public key: %s", err)
76	}
77
78	pubBytes2, err := MarshalPKIXPublicKey(pub)
79	if err != nil {
80		t.Errorf("Failed to marshal public key for the second time: %s", err)
81		return
82	}
83	if !bytes.Equal(pubBytes2, block.Bytes) {
84		t.Errorf("Reserialization of public key didn't match. got %x, want %x", pubBytes2, block.Bytes)
85	}
86	return
87}
88
89func TestParsePKIXPublicKey(t *testing.T) {
90	t.Run("RSA", func(t *testing.T) {
91		pub := testParsePKIXPublicKey(t, pemPublicKey)
92		_, ok := pub.(*rsa.PublicKey)
93		if !ok {
94			t.Errorf("Value returned from ParsePKIXPublicKey was not an RSA public key")
95		}
96	})
97	t.Run("Ed25519", func(t *testing.T) {
98		pub := testParsePKIXPublicKey(t, pemEd25519Key)
99		_, ok := pub.(ed25519.PublicKey)
100		if !ok {
101			t.Errorf("Value returned from ParsePKIXPublicKey was not an Ed25519 public key")
102		}
103	})
104}
105
106var pemPublicKey = `-----BEGIN PUBLIC KEY-----
107MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3VoPN9PKUjKFLMwOge6+
108wnDi8sbETGIx2FKXGgqtAKpzmem53kRGEQg8WeqRmp12wgp74TGpkEXsGae7RS1k
109enJCnma4fii+noGH7R0qKgHvPrI2Bwa9hzsH8tHxpyM3qrXslOmD45EH9SxIDUBJ
110FehNdaPbLP1gFyahKMsdfxFJLUvbUycuZSJ2ZnIgeVxwm4qbSvZInL9Iu4FzuPtg
111fINKcbbovy1qq4KvPIrXzhbY3PWDc6btxCf3SE0JdE1MCPThntB62/bLMSQ7xdDR
112FF53oIpvxe/SCOymfWq/LW849Ytv3Xwod0+wzAP8STXG4HSELS4UedPYeHJJJYcZ
113+QIDAQAB
114-----END PUBLIC KEY-----
115`
116
117var pemPrivateKey = testingKey(`
118-----BEGIN RSA TESTING KEY-----
119MIICXAIBAAKBgQCxoeCUW5KJxNPxMp+KmCxKLc1Zv9Ny+4CFqcUXVUYH69L3mQ7v
120IWrJ9GBfcaA7BPQqUlWxWM+OCEQZH1EZNIuqRMNQVuIGCbz5UQ8w6tS0gcgdeGX7
121J7jgCQ4RK3F/PuCM38QBLaHx988qG8NMc6VKErBjctCXFHQt14lerd5KpQIDAQAB
122AoGAYrf6Hbk+mT5AI33k2Jt1kcweodBP7UkExkPxeuQzRVe0KVJw0EkcFhywKpr1
123V5eLMrILWcJnpyHE5slWwtFHBG6a5fLaNtsBBtcAIfqTQ0Vfj5c6SzVaJv0Z5rOd
1247gQF6isy3t3w9IF3We9wXQKzT6q5ypPGdm6fciKQ8RnzREkCQQDZwppKATqQ41/R
125vhSj90fFifrGE6aVKC1hgSpxGQa4oIdsYYHwMzyhBmWW9Xv/R+fPyr8ZwPxp2c12
12633QwOLPLAkEA0NNUb+z4ebVVHyvSwF5jhfJxigim+s49KuzJ1+A2RaSApGyBZiwS
127rWvWkB471POAKUYt5ykIWVZ83zcceQiNTwJBAMJUFQZX5GDqWFc/zwGoKkeR49Yi
128MTXIvf7Wmv6E++eFcnT461FlGAUHRV+bQQXGsItR/opIG7mGogIkVXa3E1MCQARX
129AAA7eoZ9AEHflUeuLn9QJI/r0hyQQLEtrpwv6rDT1GCWaLII5HJ6NUFVf4TTcqxo
1306vdM4QGKTJoO+SaCyP0CQFdpcxSAuzpFcKv0IlJ8XzS/cy+mweCMwyJ1PFEc4FX6
131wg/HcAJWY60xZTJDFN+Qfx8ZQvBEin6c2/h+zZi5IVY=
132-----END RSA TESTING KEY-----
133`)
134
135// pemEd25519Key is the example from RFC 8410, Secrion 4.
136var pemEd25519Key = `
137-----BEGIN PUBLIC KEY-----
138MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE=
139-----END PUBLIC KEY-----
140`
141
142func TestPKIXMismatchPublicKeyFormat(t *testing.T) {
143
144	const pkcs1PublicKey = "308201080282010100817cfed98bcaa2e2a57087451c7674e0c675686dc33ff1268b0c2a6ee0202dec710858ee1c31bdf5e7783582e8ca800be45f3275c6576adc35d98e26e95bb88ca5beb186f853b8745d88bc9102c5f38753bcda519fb05948d5c77ac429255ff8aaf27d9f45d1586e95e2e9ba8a7cb771b8a09dd8c8fed3f933fd9b439bc9f30c475953418ef25f71a2b6496f53d94d39ce850aa0cc75d445b5f5b4f4ee4db78ab197a9a8d8a852f44529a007ac0ac23d895928d60ba538b16b0b087a7f903ed29770e215019b77eaecc360f35f7ab11b6d735978795b2c4a74e5bdea4dc6594cd67ed752a108e666729a753ab36d6c4f606f8760f507e1765be8cd744007e629020103"
145	const errorContains = "use ParsePKCS1PublicKey instead"
146	derBytes, _ := hex.DecodeString(pkcs1PublicKey)
147	_, err := ParsePKIXPublicKey(derBytes)
148	if !strings.Contains(err.Error(), errorContains) {
149		t.Errorf("expected error containing %q, got %s", errorContains, err)
150	}
151}
152
153var testPrivateKey *rsa.PrivateKey
154
155func init() {
156	block, _ := pem.Decode([]byte(pemPrivateKey))
157
158	var err error
159	if testPrivateKey, err = ParsePKCS1PrivateKey(block.Bytes); err != nil {
160		panic("Failed to parse private key: " + err.Error())
161	}
162}
163
164func bigFromString(s string) *big.Int {
165	ret := new(big.Int)
166	ret.SetString(s, 10)
167	return ret
168}
169
170func fromBase10(base10 string) *big.Int {
171	i := new(big.Int)
172	i.SetString(base10, 10)
173	return i
174}
175
176func bigFromHexString(s string) *big.Int {
177	ret := new(big.Int)
178	ret.SetString(s, 16)
179	return ret
180}
181
182var rsaPrivateKey = &rsa.PrivateKey{
183	PublicKey: rsa.PublicKey{
184		N: bigFromString("124737666279038955318614287965056875799409043964547386061640914307192830334599556034328900586693254156136128122194531292927142396093148164407300419162827624945636708870992355233833321488652786796134504707628792159725681555822420087112284637501705261187690946267527866880072856272532711620639179596808018872997"),
185		E: 65537,
186	},
187	D: bigFromString("69322600686866301945688231018559005300304807960033948687567105312977055197015197977971637657636780793670599180105424702854759606794705928621125408040473426339714144598640466128488132656829419518221592374964225347786430566310906679585739468938549035854760501049443920822523780156843263434219450229353270690889"),
188	Primes: []*big.Int{
189		bigFromString("11405025354575369741595561190164746858706645478381139288033759331174478411254205003127028642766986913445391069745480057674348716675323735886284176682955723"),
190		bigFromString("10937079261204603443118731009201819560867324167189758120988909645641782263430128449826989846631183550578761324239709121189827307416350485191350050332642639"),
191	},
192}
193
194func TestMarshalRSAPrivateKey(t *testing.T) {
195	priv := &rsa.PrivateKey{
196		PublicKey: rsa.PublicKey{
197			N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
198			E: 3,
199		},
200		D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
201		Primes: []*big.Int{
202			fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
203			fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
204			fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
205		},
206	}
207
208	derBytes := MarshalPKCS1PrivateKey(priv)
209
210	priv2, err := ParsePKCS1PrivateKey(derBytes)
211	if err != nil {
212		t.Errorf("error parsing serialized key: %s", err)
213		return
214	}
215	if priv.PublicKey.N.Cmp(priv2.PublicKey.N) != 0 ||
216		priv.PublicKey.E != priv2.PublicKey.E ||
217		priv.D.Cmp(priv2.D) != 0 ||
218		len(priv2.Primes) != 3 ||
219		priv.Primes[0].Cmp(priv2.Primes[0]) != 0 ||
220		priv.Primes[1].Cmp(priv2.Primes[1]) != 0 ||
221		priv.Primes[2].Cmp(priv2.Primes[2]) != 0 {
222		t.Errorf("got:%+v want:%+v", priv, priv2)
223	}
224}
225
226func TestMarshalRSAPublicKey(t *testing.T) {
227	pub := &rsa.PublicKey{
228		N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
229		E: 3,
230	}
231	derBytes := MarshalPKCS1PublicKey(pub)
232	pub2, err := ParsePKCS1PublicKey(derBytes)
233	if err != nil {
234		t.Errorf("ParsePKCS1PublicKey: %s", err)
235	}
236	if pub.N.Cmp(pub2.N) != 0 || pub.E != pub2.E {
237		t.Errorf("ParsePKCS1PublicKey = %+v, want %+v", pub, pub2)
238	}
239
240	// It's never been documented that asn1.Marshal/Unmarshal on rsa.PublicKey works,
241	// but it does, and we know of code that depends on it.
242	// Lock that in, even though we'd prefer that people use MarshalPKCS1PublicKey and ParsePKCS1PublicKey.
243	derBytes2, err := asn1.Marshal(*pub)
244	if err != nil {
245		t.Errorf("Marshal(rsa.PublicKey): %v", err)
246	} else if !bytes.Equal(derBytes, derBytes2) {
247		t.Errorf("Marshal(rsa.PublicKey) = %x, want %x", derBytes2, derBytes)
248	}
249	pub3 := new(rsa.PublicKey)
250	rest, err := asn1.Unmarshal(derBytes, pub3)
251	if err != nil {
252		t.Errorf("Unmarshal(rsa.PublicKey): %v", err)
253	}
254	if len(rest) != 0 || pub.N.Cmp(pub3.N) != 0 || pub.E != pub3.E {
255		t.Errorf("Unmarshal(rsa.PublicKey) = %+v, %q want %+v, %q", pub, rest, pub2, []byte(nil))
256	}
257
258	publicKeys := []struct {
259		derBytes          []byte
260		expectedErrSubstr string
261	}{
262		{
263			derBytes: []byte{
264				0x30, 6, // SEQUENCE, 6 bytes
265				0x02, 1, // INTEGER, 1 byte
266				17,
267				0x02, 1, // INTEGER, 1 byte
268				3, // 3
269			},
270		}, {
271			derBytes: []byte{
272				0x30, 6, // SEQUENCE
273				0x02, 1, // INTEGER, 1 byte
274				0xff,    // -1
275				0x02, 1, // INTEGER, 1 byte
276				3,
277			},
278			expectedErrSubstr: "zero or negative",
279		}, {
280			derBytes: []byte{
281				0x30, 6, // SEQUENCE
282				0x02, 1, // INTEGER, 1 byte
283				17,
284				0x02, 1, // INTEGER, 1 byte
285				0xff, // -1
286			},
287			expectedErrSubstr: "zero or negative",
288		}, {
289			derBytes: []byte{
290				0x30, 6, // SEQUENCE
291				0x02, 1, // INTEGER, 1 byte
292				17,
293				0x02, 1, // INTEGER, 1 byte
294				3,
295				1,
296			},
297			expectedErrSubstr: "trailing data",
298		}, {
299			derBytes: []byte{
300				0x30, 9, // SEQUENCE
301				0x02, 1, // INTEGER, 1 byte
302				17,
303				0x02, 4, // INTEGER, 4 bytes
304				0x7f, 0xff, 0xff, 0xff,
305			},
306		}, {
307			derBytes: []byte{
308				0x30, 10, // SEQUENCE
309				0x02, 1, // INTEGER, 1 byte
310				17,
311				0x02, 5, // INTEGER, 5 bytes
312				0x00, 0x80, 0x00, 0x00, 0x00,
313			},
314			// On 64-bit systems, encoding/asn1 will accept the
315			// public exponent, but ParsePKCS1PublicKey will return
316			// an error. On 32-bit systems, encoding/asn1 will
317			// return the error. The common substring of both error
318			// is the word “large”.
319			expectedErrSubstr: "large",
320		},
321	}
322
323	for i, test := range publicKeys {
324		shouldFail := len(test.expectedErrSubstr) > 0
325		pub, err := ParsePKCS1PublicKey(test.derBytes)
326		if shouldFail {
327			if err == nil {
328				t.Errorf("#%d: unexpected success, got %#v", i, pub)
329			} else if !strings.Contains(err.Error(), test.expectedErrSubstr) {
330				t.Errorf("#%d: expected error containing %q, got %s", i, test.expectedErrSubstr, err)
331			}
332		} else {
333			if err != nil {
334				t.Errorf("#%d: unexpected failure: %s", i, err)
335				continue
336			}
337			reserialized := MarshalPKCS1PublicKey(pub)
338			if !bytes.Equal(reserialized, test.derBytes) {
339				t.Errorf("#%d: failed to reserialize: got %x, expected %x", i, reserialized, test.derBytes)
340			}
341		}
342	}
343}
344
345type matchHostnamesTest struct {
346	pattern, host string
347	ok            bool
348}
349
350var matchHostnamesTests = []matchHostnamesTest{
351	{"a.b.c", "a.b.c", true},
352	{"a.b.c", "b.b.c", false},
353	{"", "b.b.c", false},
354	{"a.b.c", "", false},
355	{"example.com", "example.com", true},
356	{"example.com", "www.example.com", false},
357	{"*.example.com", "example.com", false},
358	{"*.example.com", "www.example.com", true},
359	{"*.example.com", "www.example.com.", true},
360	{"*.example.com", "xyz.www.example.com", false},
361	{"*.example.com", "https://www.example.com", false}, // Issue 27591
362	{"*.example..com", "www.example..com", false},
363	{"www.example..com", "www.example..com", true},
364	{"*.*.example.com", "xyz.www.example.com", false},
365	{"*.www.*.com", "xyz.www.example.com", false},
366	{"*bar.example.com", "foobar.example.com", false},
367	{"f*.example.com", "foobar.example.com", false},
368	{"www.example.com", "*.example.com", false},
369	{"", ".", false},
370	{".", "", false},
371	{".", ".", false},
372	{"example.com", "example.com.", true},
373	{"example.com.", "example.com", false},
374	{"example.com.", "example.com.", true}, // perfect matches allow trailing dots in patterns
375	{"*.com.", "example.com.", false},
376	{"*.com.", "example.com", false},
377	{"*.com", "example.com", true},
378	{"*.com", "example.com.", true},
379	{"foo:bar", "foo:bar", true},
380	{"*.foo:bar", "xxx.foo:bar", false},
381	{"*.2.3.4", "1.2.3.4", false},
382	{"*.2.3.4", "[1.2.3.4]", false},
383	{"*:4860:4860::8888", "2001:4860:4860::8888", false},
384	{"*:4860:4860::8888", "[2001:4860:4860::8888]", false},
385	{"2001:4860:4860::8888", "2001:4860:4860::8888", false},
386	{"2001:4860:4860::8888", "[2001:4860:4860::8888]", false},
387	{"[2001:4860:4860::8888]", "2001:4860:4860::8888", false},
388	{"[2001:4860:4860::8888]", "[2001:4860:4860::8888]", false},
389}
390
391func TestMatchHostnames(t *testing.T) {
392	for i, test := range matchHostnamesTests {
393		c := &Certificate{DNSNames: []string{test.pattern}}
394		r := c.VerifyHostname(test.host) == nil
395		if r != test.ok {
396			t.Errorf("#%d mismatch got: %t want: %t when matching '%s' against '%s'", i, r, test.ok, test.host, test.pattern)
397		}
398	}
399}
400
401func TestMatchIP(t *testing.T) {
402	// Check that pattern matching is working.
403	c := &Certificate{
404		DNSNames: []string{"*.foo.bar.baz"},
405		Subject: pkix.Name{
406			CommonName: "*.foo.bar.baz",
407		},
408	}
409	err := c.VerifyHostname("quux.foo.bar.baz")
410	if err != nil {
411		t.Fatalf("VerifyHostname(quux.foo.bar.baz): %v", err)
412	}
413
414	// But check that if we change it to be matching against an IP address,
415	// it is rejected.
416	c = &Certificate{
417		DNSNames: []string{"*.2.3.4"},
418		Subject: pkix.Name{
419			CommonName: "*.2.3.4",
420		},
421	}
422	err = c.VerifyHostname("1.2.3.4")
423	if err == nil {
424		t.Fatalf("VerifyHostname(1.2.3.4) should have failed, did not")
425	}
426
427	c = &Certificate{
428		IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")},
429	}
430	err = c.VerifyHostname("127.0.0.1")
431	if err != nil {
432		t.Fatalf("VerifyHostname(127.0.0.1): %v", err)
433	}
434	err = c.VerifyHostname("::1")
435	if err != nil {
436		t.Fatalf("VerifyHostname(::1): %v", err)
437	}
438	err = c.VerifyHostname("[::1]")
439	if err != nil {
440		t.Fatalf("VerifyHostname([::1]): %v", err)
441	}
442}
443
444func TestCertificateParse(t *testing.T) {
445	s, _ := base64.StdEncoding.DecodeString(certBytes)
446	certs, err := ParseCertificates(s)
447	if err != nil {
448		t.Error(err)
449	}
450	if len(certs) != 2 {
451		t.Errorf("Wrong number of certs: got %d want 2", len(certs))
452		return
453	}
454
455	err = certs[0].CheckSignatureFrom(certs[1])
456	if err != nil {
457		t.Error(err)
458	}
459
460	if err := certs[0].VerifyHostname("mail.google.com"); err != nil {
461		t.Error(err)
462	}
463
464	const expectedExtensions = 10
465	if n := len(certs[0].Extensions); n != expectedExtensions {
466		t.Errorf("want %d extensions, got %d", expectedExtensions, n)
467	}
468}
469
470func TestCertificateEqualOnNil(t *testing.T) {
471	cNonNil := new(Certificate)
472	var cNil1, cNil2 *Certificate
473	if !cNil1.Equal(cNil2) {
474		t.Error("Nil certificates: cNil1 is not equal to cNil2")
475	}
476	if !cNil2.Equal(cNil1) {
477		t.Error("Nil certificates: cNil2 is not equal to cNil1")
478	}
479	if cNil1.Equal(cNonNil) {
480		t.Error("Unexpectedly cNil1 is equal to cNonNil")
481	}
482	if cNonNil.Equal(cNil1) {
483		t.Error("Unexpectedly cNonNil is equal to cNil1")
484	}
485}
486
487func TestMismatchedSignatureAlgorithm(t *testing.T) {
488	der, _ := pem.Decode([]byte(rsaPSSSelfSignedPEM))
489	if der == nil {
490		t.Fatal("Failed to find PEM block")
491	}
492
493	cert, err := ParseCertificate(der.Bytes)
494	if err != nil {
495		t.Fatal(err)
496	}
497
498	if err = cert.CheckSignature(ECDSAWithSHA256, nil, nil); err == nil {
499		t.Fatal("CheckSignature unexpectedly return no error")
500	}
501
502	const expectedSubstring = " but have public key of type "
503	if !strings.Contains(err.Error(), expectedSubstring) {
504		t.Errorf("Expected error containing %q, but got %q", expectedSubstring, err)
505	}
506}
507
508var certBytes = "MIIE0jCCA7qgAwIBAgIQWcvS+TTB3GwCAAAAAGEAWzANBgkqhkiG9w0BAQsFADBCMQswCQYD" +
509	"VQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMRMwEQYDVQQDEwpHVFMg" +
510	"Q0EgMU8xMB4XDTIwMDQwMTEyNTg1NloXDTIwMDYyNDEyNTg1NlowaTELMAkGA1UEBhMCVVMx" +
511	"EzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxEzARBgNVBAoT" +
512	"Ckdvb2dsZSBMTEMxGDAWBgNVBAMTD21haWwuZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqG" +
513	"SM49AwEHA0IABO+dYiPnkFl+cZVf6mrWeNp0RhQcJSBGH+sEJxjvc+cYlW3QJCnm57qlpFdd" +
514	"pz3MPyVejvXQdM6iI1mEWP4C2OujggJmMIICYjAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAww" +
515	"CgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUI6pZhnQ/lQgmPDwSKR2A54G7" +
516	"AS4wHwYDVR0jBBgwFoAUmNH4bhDrz5vsYJ8YkBug630J/SswZAYIKwYBBQUHAQEEWDBWMCcG" +
517	"CCsGAQUFBzABhhtodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHMxbzEwKwYIKwYBBQUHMAKGH2h0" +
518	"dHA6Ly9wa2kuZ29vZy9nc3IyL0dUUzFPMS5jcnQwLAYDVR0RBCUwI4IPbWFpbC5nb29nbGUu" +
519	"Y29tghBpbmJveC5nb29nbGUuY29tMCEGA1UdIAQaMBgwCAYGZ4EMAQICMAwGCisGAQQB1nkC" +
520	"BQMwLwYDVR0fBCgwJjAkoCKgIIYeaHR0cDovL2NybC5wa2kuZ29vZy9HVFMxTzEuY3JsMIIB" +
521	"AwYKKwYBBAHWeQIEAgSB9ASB8QDvAHYAsh4FzIuizYogTodm+Su5iiUgZ2va+nDnsklTLe+L" +
522	"kF4AAAFxNgmxKgAABAMARzBFAiEA12/OHdTGXQ3qHHC3NvYCyB8aEz/+ZFOLCAI7lhqj28sC" +
523	"IG2/7Yz2zK6S6ai+dH7cTMZmoFGo39gtaTqtZAqEQX7nAHUAXqdz+d9WwOe1Nkh90EngMnqR" +
524	"mgyEoRIShBh1loFxRVgAAAFxNgmxTAAABAMARjBEAiA7PNq+MFfv6O9mBkxFViS2TfU66yRB" +
525	"/njcebWglLQjZQIgOyRKhxlEizncFRml7yn4Bg48ktXKGjo+uiw6zXEINb0wDQYJKoZIhvcN" +
526	"AQELBQADggEBADM2Rh306Q10PScsolYMxH1B/K4Nb2WICvpY0yDPJFdnGjqCYym196TjiEvs" +
527	"R6etfeHdyzlZj6nh82B4TVyHjiWM02dQgPalOuWQcuSy0OvLh7F1E7CeHzKlczdFPBTOTdM1" +
528	"RDTxlvw1bAqc0zueM8QIAyEy3opd7FxAcGQd5WRIJhzLBL+dbbMOW/LTeW7cm/Xzq8cgCybN" +
529	"BSZAvhjseJ1L29OlCTZL97IfnX0IlFQzWuvvHy7V2B0E3DHlzM0kjwkkCKDUUp/wajv2NZKC" +
530	"TkhEyERacZRKc9U0ADxwsAzHrdz5+5zfD2usEV/MQ5V6d8swLXs+ko0X6swrd4YCiB8wggRK" +
531	"MIIDMqADAgECAg0B47SaoY2KqYElaVC4MA0GCSqGSIb3DQEBCwUAMEwxIDAeBgNVBAsTF0ds" +
532	"b2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpH" +
533	"bG9iYWxTaWduMB4XDTE3MDYxNTAwMDA0MloXDTIxMTIxNTAwMDA0MlowQjELMAkGA1UEBhMC" +
534	"VVMxHjAcBgNVBAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczETMBEGA1UEAxMKR1RTIENBIDFP" +
535	"MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAYz0XUi83TnORA73603WkhG8nP" +
536	"PI5MdbkPMRmEPZ48Ke9QDRCTbwWAgJ8qoL0SSwLhPZ9YFiT+MJ8LdHdVkx1L903hkoIQ9lGs" +
537	"DMOyIpQPNGuYEEnnC52DOd0gxhwt79EYYWXnI4MgqCMS/9Ikf9Qv50RqW03XUGawr55CYwX7" +
538	"4BzEY2Gvn2oz/2KXvUjZ03wUZ9x13C5p6PhteGnQtxAFuPExwjsk/RozdPgj4OxrGYoWxuPN" +
539	"pM0L27OkWWA4iDutHbnGjKdTG/y82aSrvN08YdeTFZjugb2P4mRHIEAGTtesl+i5wFkSoUkl" +
540	"I+TtcDQspbRjfPmjPYPRzW0krAcCAwEAAaOCATMwggEvMA4GA1UdDwEB/wQEAwIBhjAdBgNV" +
541	"HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4E" +
542	"FgQUmNH4bhDrz5vsYJ8YkBug630J/SswHwYDVR0jBBgwFoAUm+IHV2ccHsBqBt5ZtJot39wZ" +
543	"hi4wNQYIKwYBBQUHAQEEKTAnMCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5wa2kuZ29vZy9n" +
544	"c3IyMDIGA1UdHwQrMCkwJ6AloCOGIWh0dHA6Ly9jcmwucGtpLmdvb2cvZ3NyMi9nc3IyLmNy" +
545	"bDA/BgNVHSAEODA2MDQGBmeBDAECAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3BraS5nb29n" +
546	"L3JlcG9zaXRvcnkvMA0GCSqGSIb3DQEBCwUAA4IBAQAagD42efvzLqlGN31eVBY1rsdOCJn+" +
547	"vdE0aSZSZgc9CrpJy2L08RqO/BFPaJZMdCvTZ96yo6oFjYRNTCBlD6WW2g0W+Gw7228EI4hr" +
548	"OmzBYL1on3GO7i1YNAfw1VTphln9e14NIZT1jMmo+NjyrcwPGvOap6kEJ/mjybD/AnhrYbrH" +
549	"NSvoVvpPwxwM7bY8tEvq7czhPOzcDYzWPpvKQliLzBYhF0C8otZm79rEFVvNiaqbCSbnMtIN" +
550	"bmcgAlsQsJAJnAwfnq3YO+qh/GzoEFwIUhlRKnG7rHq13RXtK8kIKiyKtKYhq2P/11JJUNCJ" +
551	"t63yr/tQri/hlQ3zRq2dnPXK"
552
553func parseCIDR(s string) *net.IPNet {
554	_, net, err := net.ParseCIDR(s)
555	if err != nil {
556		panic(err)
557	}
558	return net
559}
560
561func parseURI(s string) *url.URL {
562	uri, err := url.Parse(s)
563	if err != nil {
564		panic(err)
565	}
566	return uri
567}
568
569func TestCreateSelfSignedCertificate(t *testing.T) {
570	random := rand.Reader
571
572	ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
573	if err != nil {
574		t.Fatalf("Failed to generate ECDSA key: %s", err)
575	}
576
577	ed25519Pub, ed25519Priv, err := ed25519.GenerateKey(random)
578	if err != nil {
579		t.Fatalf("Failed to generate Ed25519 key: %s", err)
580	}
581
582	tests := []struct {
583		name      string
584		pub, priv any
585		checkSig  bool
586		sigAlgo   SignatureAlgorithm
587	}{
588		{"RSA/RSA", &testPrivateKey.PublicKey, testPrivateKey, true, SHA384WithRSA},
589		{"RSA/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384},
590		{"ECDSA/RSA", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSA},
591		{"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA256},
592		{"RSAPSS/RSAPSS", &testPrivateKey.PublicKey, testPrivateKey, true, SHA256WithRSAPSS},
593		{"ECDSA/RSAPSS", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSAPSS},
594		{"RSAPSS/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384},
595		{"Ed25519", ed25519Pub, ed25519Priv, true, PureEd25519},
596	}
597
598	testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
599	testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}}
600	extraExtensionData := []byte("extra extension")
601
602	for _, test := range tests {
603		commonName := "test.example.com"
604		template := Certificate{
605			// SerialNumber is negative to ensure that negative
606			// values are parsed. This is due to the prevalence of
607			// buggy code that produces certificates with negative
608			// serial numbers.
609			SerialNumber: big.NewInt(-1),
610			Subject: pkix.Name{
611				CommonName:   commonName,
612				Organization: []string{"Σ Acme Co"},
613				Country:      []string{"US"},
614				ExtraNames: []pkix.AttributeTypeAndValue{
615					{
616						Type:  []int{2, 5, 4, 42},
617						Value: "Gopher",
618					},
619					// This should override the Country, above.
620					{
621						Type:  []int{2, 5, 4, 6},
622						Value: "NL",
623					},
624				},
625			},
626			NotBefore: time.Unix(1000, 0),
627			NotAfter:  time.Unix(100000, 0),
628
629			SignatureAlgorithm: test.sigAlgo,
630
631			SubjectKeyId: []byte{1, 2, 3, 4},
632			KeyUsage:     KeyUsageCertSign,
633
634			ExtKeyUsage:        testExtKeyUsage,
635			UnknownExtKeyUsage: testUnknownExtKeyUsage,
636
637			BasicConstraintsValid: true,
638			IsCA:                  true,
639
640			OCSPServer:            []string{"http://ocsp.example.com"},
641			IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"},
642
643			DNSNames:       []string{"test.example.com"},
644			EmailAddresses: []string{"gopher@golang.org"},
645			IPAddresses:    []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
646			URIs:           []*url.URL{parseURI("https://foo.com/wibble#foo")},
647
648			PolicyIdentifiers:       []asn1.ObjectIdentifier{[]int{1, 2, 3}},
649			PermittedDNSDomains:     []string{".example.com", "example.com"},
650			ExcludedDNSDomains:      []string{"bar.example.com"},
651			PermittedIPRanges:       []*net.IPNet{parseCIDR("192.168.1.1/16"), parseCIDR("1.2.3.4/8")},
652			ExcludedIPRanges:        []*net.IPNet{parseCIDR("2001:db8::/48")},
653			PermittedEmailAddresses: []string{"foo@example.com"},
654			ExcludedEmailAddresses:  []string{".example.com", "example.com"},
655			PermittedURIDomains:     []string{".bar.com", "bar.com"},
656			ExcludedURIDomains:      []string{".bar2.com", "bar2.com"},
657
658			CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
659
660			ExtraExtensions: []pkix.Extension{
661				{
662					Id:    []int{1, 2, 3, 4},
663					Value: extraExtensionData,
664				},
665				// This extension should override the SubjectKeyId, above.
666				{
667					Id:       oidExtensionSubjectKeyId,
668					Critical: false,
669					Value:    []byte{0x04, 0x04, 4, 3, 2, 1},
670				},
671			},
672		}
673
674		derBytes, err := CreateCertificate(random, &template, &template, test.pub, test.priv)
675		if err != nil {
676			t.Errorf("%s: failed to create certificate: %s", test.name, err)
677			continue
678		}
679
680		cert, err := ParseCertificate(derBytes)
681		if err != nil {
682			t.Errorf("%s: failed to parse certificate: %s", test.name, err)
683			continue
684		}
685
686		if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
687			t.Errorf("%s: failed to parse policy identifiers: got:%#v want:%#v", test.name, cert.PolicyIdentifiers, template.PolicyIdentifiers)
688		}
689
690		if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
691			t.Errorf("%s: failed to parse name constraints: %#v", test.name, cert.PermittedDNSDomains)
692		}
693
694		if len(cert.ExcludedDNSDomains) != 1 || cert.ExcludedDNSDomains[0] != "bar.example.com" {
695			t.Errorf("%s: failed to parse name constraint exclusions: %#v", test.name, cert.ExcludedDNSDomains)
696		}
697
698		if len(cert.PermittedIPRanges) != 2 || cert.PermittedIPRanges[0].String() != "192.168.0.0/16" || cert.PermittedIPRanges[1].String() != "1.0.0.0/8" {
699			t.Errorf("%s: failed to parse IP constraints: %#v", test.name, cert.PermittedIPRanges)
700		}
701
702		if len(cert.ExcludedIPRanges) != 1 || cert.ExcludedIPRanges[0].String() != "2001:db8::/48" {
703			t.Errorf("%s: failed to parse IP constraint exclusions: %#v", test.name, cert.ExcludedIPRanges)
704		}
705
706		if len(cert.PermittedEmailAddresses) != 1 || cert.PermittedEmailAddresses[0] != "foo@example.com" {
707			t.Errorf("%s: failed to parse permitted email addreses: %#v", test.name, cert.PermittedEmailAddresses)
708		}
709
710		if len(cert.ExcludedEmailAddresses) != 2 || cert.ExcludedEmailAddresses[0] != ".example.com" || cert.ExcludedEmailAddresses[1] != "example.com" {
711			t.Errorf("%s: failed to parse excluded email addreses: %#v", test.name, cert.ExcludedEmailAddresses)
712		}
713
714		if len(cert.PermittedURIDomains) != 2 || cert.PermittedURIDomains[0] != ".bar.com" || cert.PermittedURIDomains[1] != "bar.com" {
715			t.Errorf("%s: failed to parse permitted URIs: %#v", test.name, cert.PermittedURIDomains)
716		}
717
718		if len(cert.ExcludedURIDomains) != 2 || cert.ExcludedURIDomains[0] != ".bar2.com" || cert.ExcludedURIDomains[1] != "bar2.com" {
719			t.Errorf("%s: failed to parse excluded URIs: %#v", test.name, cert.ExcludedURIDomains)
720		}
721
722		if cert.Subject.CommonName != commonName {
723			t.Errorf("%s: subject wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Subject.CommonName, commonName)
724		}
725
726		if len(cert.Subject.Country) != 1 || cert.Subject.Country[0] != "NL" {
727			t.Errorf("%s: ExtraNames didn't override Country", test.name)
728		}
729
730		for _, ext := range cert.Extensions {
731			if ext.Id.Equal(oidExtensionSubjectAltName) {
732				if ext.Critical {
733					t.Fatal("SAN extension is marked critical")
734				}
735			}
736		}
737
738		found := false
739		for _, atv := range cert.Subject.Names {
740			if atv.Type.Equal([]int{2, 5, 4, 42}) {
741				found = true
742				break
743			}
744		}
745		if !found {
746			t.Errorf("%s: Names didn't contain oid 2.5.4.42 from ExtraNames", test.name)
747		}
748
749		if cert.Issuer.CommonName != commonName {
750			t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName)
751		}
752
753		if cert.SignatureAlgorithm != test.sigAlgo {
754			t.Errorf("%s: SignatureAlgorithm wasn't copied from template. Got %v, want %v", test.name, cert.SignatureAlgorithm, test.sigAlgo)
755		}
756
757		if !reflect.DeepEqual(cert.ExtKeyUsage, testExtKeyUsage) {
758			t.Errorf("%s: extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.ExtKeyUsage, testExtKeyUsage)
759		}
760
761		if !reflect.DeepEqual(cert.UnknownExtKeyUsage, testUnknownExtKeyUsage) {
762			t.Errorf("%s: unknown extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.UnknownExtKeyUsage, testUnknownExtKeyUsage)
763		}
764
765		if !reflect.DeepEqual(cert.OCSPServer, template.OCSPServer) {
766			t.Errorf("%s: OCSP servers differ from template. Got %v, want %v", test.name, cert.OCSPServer, template.OCSPServer)
767		}
768
769		if !reflect.DeepEqual(cert.IssuingCertificateURL, template.IssuingCertificateURL) {
770			t.Errorf("%s: Issuing certificate URLs differ from template. Got %v, want %v", test.name, cert.IssuingCertificateURL, template.IssuingCertificateURL)
771		}
772
773		if !reflect.DeepEqual(cert.DNSNames, template.DNSNames) {
774			t.Errorf("%s: SAN DNS names differ from template. Got %v, want %v", test.name, cert.DNSNames, template.DNSNames)
775		}
776
777		if !reflect.DeepEqual(cert.EmailAddresses, template.EmailAddresses) {
778			t.Errorf("%s: SAN emails differ from template. Got %v, want %v", test.name, cert.EmailAddresses, template.EmailAddresses)
779		}
780
781		if len(cert.URIs) != 1 || cert.URIs[0].String() != "https://foo.com/wibble#foo" {
782			t.Errorf("%s: URIs differ from template. Got %v, want %v", test.name, cert.URIs, template.URIs)
783		}
784
785		if !reflect.DeepEqual(cert.IPAddresses, template.IPAddresses) {
786			t.Errorf("%s: SAN IPs differ from template. Got %v, want %v", test.name, cert.IPAddresses, template.IPAddresses)
787		}
788
789		if !reflect.DeepEqual(cert.CRLDistributionPoints, template.CRLDistributionPoints) {
790			t.Errorf("%s: CRL distribution points differ from template. Got %v, want %v", test.name, cert.CRLDistributionPoints, template.CRLDistributionPoints)
791		}
792
793		if !bytes.Equal(cert.SubjectKeyId, []byte{4, 3, 2, 1}) {
794			t.Errorf("%s: ExtraExtensions didn't override SubjectKeyId", test.name)
795		}
796
797		if !bytes.Contains(derBytes, extraExtensionData) {
798			t.Errorf("%s: didn't find extra extension in DER output", test.name)
799		}
800
801		if test.checkSig {
802			err = cert.CheckSignatureFrom(cert)
803			if err != nil {
804				t.Errorf("%s: signature verification failed: %s", test.name, err)
805			}
806		}
807	}
808}
809
810// Self-signed certificate using ECDSA with SHA1 & secp256r1
811var ecdsaSHA1CertPem = `
812-----BEGIN CERTIFICATE-----
813MIICDjCCAbUCCQDF6SfN0nsnrjAJBgcqhkjOPQQBMIGPMQswCQYDVQQGEwJVUzET
814MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMG
815A1UECgwMR29vZ2xlLCBJbmMuMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
816CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIwMjAyMDUw
817WhcNMjIwNTE4MjAyMDUwWjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
818b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTATBgNVBAoMDEdvb2dsZSwg
819SW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAhBgkqhkiG9w0BCQEWFGdv
820bGFuZy1kZXZAZ21haWwuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/Wgn
821WQDo5+bz71T0327ERgd5SDDXFbXLpzIZDXTkjpe8QTEbsF+ezsQfrekrpDPC4Cd3
822P9LY0tG+aI8IyVKdUjAJBgcqhkjOPQQBA0gAMEUCIGlsqMcRqWVIWTD6wXwe6Jk2
823DKxL46r/FLgJYnzBEH99AiEA3fBouObsvV1R3oVkb4BQYnD4/4LeId6lAT43YvyV
824a/A=
825-----END CERTIFICATE-----
826`
827
828// Self-signed certificate using ECDSA with SHA256 & secp256r1
829var ecdsaSHA256p256CertPem = `
830-----BEGIN CERTIFICATE-----
831MIICDzCCAbYCCQDlsuMWvgQzhTAKBggqhkjOPQQDAjCBjzELMAkGA1UEBhMCVVMx
832EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
833BgNVBAoMDEdvb2dsZSwgSW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAh
834BgkqhkiG9w0BCQEWFGdvbGFuZy1kZXZAZ21haWwuY29tMB4XDTEyMDUyMTAwMTkx
835NloXDTIyMDUxOTAwMTkxNlowgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
836Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYDVQQKDAxHb29nbGUs
837IEluYy4xFzAVBgNVBAMMDnd3dy5nb29nbGUuY29tMSMwIQYJKoZIhvcNAQkBFhRn
838b2xhbmctZGV2QGdtYWlsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPMt
8392ErhxAty5EJRu9yM+MTy+hUXm3pdW1ensAv382KoGExSXAFWP7pjJnNtHO+XSwVm
840YNtqjcAGFKpweoN//kQwCgYIKoZIzj0EAwIDRwAwRAIgIYSaUA/IB81gjbIw/hUV
84170twxJr5EcgOo0hLp3Jm+EYCIFDO3NNcgmURbJ1kfoS3N/0O+irUtoPw38YoNkqJ
842h5wi
843-----END CERTIFICATE-----
844`
845
846// Self-signed certificate using ECDSA with SHA256 & secp384r1
847var ecdsaSHA256p384CertPem = `
848-----BEGIN CERTIFICATE-----
849MIICSjCCAdECCQDje/no7mXkVzAKBggqhkjOPQQDAjCBjjELMAkGA1UEBhMCVVMx
850EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
851BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
852CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMDYxMDM0
853WhcNMjIwNTE5MDYxMDM0WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
854b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
855SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
856YW5nLWRldkBnbWFpbC5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARRuzRNIKRK
857jIktEmXanNmrTR/q/FaHXLhWRZ6nHWe26Fw7Rsrbk+VjGy4vfWtNn7xSFKrOu5ze
858qxKnmE0h5E480MNgrUiRkaGO2GMJJVmxx20aqkXOk59U8yGA4CghE6MwCgYIKoZI
859zj0EAwIDZwAwZAIwBZEN8gvmRmfeP/9C1PRLzODIY4JqWub2PLRT4mv9GU+yw3Gr
860PU9A3CHMdEcdw/MEAjBBO1lId8KOCh9UZunsSMfqXiVurpzmhWd6VYZ/32G+M+Mh
8613yILeYQzllt/g0rKVRk=
862-----END CERTIFICATE-----
863`
864
865// Self-signed certificate using ECDSA with SHA384 & secp521r1
866var ecdsaSHA384p521CertPem = `
867-----BEGIN CERTIFICATE-----
868MIICljCCAfcCCQDhp1AFD/ahKjAKBggqhkjOPQQDAzCBjjELMAkGA1UEBhMCVVMx
869EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
870BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
871CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMTUwNDI5
872WhcNMjIwNTE5MTUwNDI5WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
873b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
874SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
875YW5nLWRldkBnbWFpbC5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACqx9Rv
876IssRs1LWYcNN+WffwlHw4Tv3y8/LIAA9MF1ZScIonU9nRMxt4a2uGJVCPDw6JHpz
877PaYc0E9puLoE9AfKpwFr59Jkot7dBg55SKPEFkddoip/rvmN7NPAWjMBirOwjOkm
8788FPthvPhGPqsu9AvgVuHu3PosWiHGNrhh379pva8MzAKBggqhkjOPQQDAwOBjAAw
879gYgCQgEHNmswkUdPpHqrVxp9PvLVl+xxPuHBkT+75z9JizyxtqykHQo9Uh6SWCYH
880BF9KLolo01wMt8DjoYP5Fb3j5MH7xwJCAbWZzTOp4l4DPkIvAh4LeC4VWbwPPyqh
881kBg71w/iEcSY3wUKgHGcJJrObZw7wys91I5kENljqw/Samdr3ka+jBJa
882-----END CERTIFICATE-----
883`
884
885var ecdsaTests = []struct {
886	sigAlgo SignatureAlgorithm
887	pemCert string
888}{
889	{ECDSAWithSHA256, ecdsaSHA256p256CertPem},
890	{ECDSAWithSHA256, ecdsaSHA256p384CertPem},
891	{ECDSAWithSHA384, ecdsaSHA384p521CertPem},
892}
893
894func TestECDSA(t *testing.T) {
895	for i, test := range ecdsaTests {
896		pemBlock, _ := pem.Decode([]byte(test.pemCert))
897		cert, err := ParseCertificate(pemBlock.Bytes)
898		if err != nil {
899			t.Errorf("%d: failed to parse certificate: %s", i, err)
900			continue
901		}
902		if sa := cert.SignatureAlgorithm; sa != test.sigAlgo {
903			t.Errorf("%d: signature algorithm is %v, want %v", i, sa, test.sigAlgo)
904		}
905		if parsedKey, ok := cert.PublicKey.(*ecdsa.PublicKey); !ok {
906			t.Errorf("%d: wanted an ECDSA public key but found: %#v", i, parsedKey)
907		}
908		if pka := cert.PublicKeyAlgorithm; pka != ECDSA {
909			t.Errorf("%d: public key algorithm is %v, want ECDSA", i, pka)
910		}
911		if err = cert.CheckSignatureFrom(cert); err != nil {
912			t.Errorf("%d: certificate verification failed: %s", i, err)
913		}
914	}
915}
916
917// Self-signed certificate using DSA with SHA1
918var dsaCertPem = `-----BEGIN CERTIFICATE-----
919MIIEDTCCA82gAwIBAgIJALHPghaoxeDhMAkGByqGSM44BAMweTELMAkGA1UEBhMC
920VVMxCzAJBgNVBAgTAk5DMQ8wDQYDVQQHEwZOZXd0b24xFDASBgNVBAoTC0dvb2ds
921ZSwgSW5jMRIwEAYDVQQDEwlKb24gQWxsaWUxIjAgBgkqhkiG9w0BCQEWE2pvbmFs
922bGllQGdvb2dsZS5jb20wHhcNMTEwNTE0MDMwMTQ1WhcNMTEwNjEzMDMwMTQ1WjB5
923MQswCQYDVQQGEwJVUzELMAkGA1UECBMCTkMxDzANBgNVBAcTBk5ld3RvbjEUMBIG
924A1UEChMLR29vZ2xlLCBJbmMxEjAQBgNVBAMTCUpvbiBBbGxpZTEiMCAGCSqGSIb3
925DQEJARYTam9uYWxsaWVAZ29vZ2xlLmNvbTCCAbcwggEsBgcqhkjOOAQBMIIBHwKB
926gQC8hLUnQ7FpFYu4WXTj6DKvXvz8QrJkNJCVMTpKAT7uBpobk32S5RrPKXocd4gN
9278lyGB9ggS03EVlEwXvSmO0DH2MQtke2jl9j1HLydClMf4sbx5V6TV9IFw505U1iW
928jL7awRMgxge+FsudtJK254FjMFo03ZnOQ8ZJJ9E6AEDrlwIVAJpnBn9moyP11Ox5
929Asc/5dnjb6dPAoGBAJFHd4KVv1iTVCvEG6gGiYop5DJh28hUQcN9kul+2A0yPUSC
930X93oN00P8Vh3eYgSaCWZsha7zDG53MrVJ0Zf6v/X/CoZNhLldeNOepivTRAzn+Rz
931kKUYy5l1sxYLHQKF0UGNCXfFKZT0PCmgU+PWhYNBBMn6/cIh44vp85ideo5CA4GE
932AAKBgFmifCafzeRaohYKXJgMGSEaggCVCRq5xdyDCat+wbOkjC4mfG01/um3G8u5
933LxasjlWRKTR/tcAL7t0QuokVyQaYdVypZXNaMtx1db7YBuHjj3aP+8JOQRI9xz8c
934bp5NDJ5pISiFOv4p3GZfqZPcqckDt78AtkQrmnal2txhhjF6o4HeMIHbMB0GA1Ud
935DgQWBBQVyyr7hO11ZFFpWX50298Sa3V+rzCBqwYDVR0jBIGjMIGggBQVyyr7hO11
936ZFFpWX50298Sa3V+r6F9pHsweTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk5DMQ8w
937DQYDVQQHEwZOZXd0b24xFDASBgNVBAoTC0dvb2dsZSwgSW5jMRIwEAYDVQQDEwlK
938b24gQWxsaWUxIjAgBgkqhkiG9w0BCQEWE2pvbmFsbGllQGdvb2dsZS5jb22CCQCx
939z4IWqMXg4TAMBgNVHRMEBTADAQH/MAkGByqGSM44BAMDLwAwLAIUPtn/5j8Q1jJI
9407ggOIsgrhgUdjGQCFCsmDq1H11q9+9Wp9IMeGrTSKHIM
941-----END CERTIFICATE-----
942`
943
944func TestParseCertificateWithDsaPublicKey(t *testing.T) {
945	expectedKey := &dsa.PublicKey{
946		Parameters: dsa.Parameters{
947			P: bigFromHexString("00BC84B52743B169158BB85974E3E832AF5EFCFC42B264349095313A4A013EEE069A1B937D92E51ACF297A1C77880DF25C8607D8204B4DC45651305EF4A63B40C7D8C42D91EDA397D8F51CBC9D0A531FE2C6F1E55E9357D205C39D395358968CBEDAC11320C607BE16CB9DB492B6E78163305A34DD99CE43C64927D13A0040EB97"),
948			Q: bigFromHexString("009A67067F66A323F5D4EC7902C73FE5D9E36FA74F"),
949			G: bigFromHexString("009147778295BF5893542BC41BA806898A29E43261DBC85441C37D92E97ED80D323D44825FDDE8374D0FF15877798812682599B216BBCC31B9DCCAD527465FEAFFD7FC2A193612E575E34E7A98AF4D10339FE47390A518CB9975B3160B1D0285D1418D0977C52994F43C29A053E3D685834104C9FAFDC221E38BE9F3989D7A8E42"),
950		},
951		Y: bigFromHexString("59A27C269FCDE45AA2160A5C980C19211A820095091AB9C5DC8309AB7EC1B3A48C2E267C6D35FEE9B71BCBB92F16AC8E559129347FB5C00BEEDD10BA8915C90698755CA965735A32DC7575BED806E1E38F768FFBC24E41123DC73F1C6E9E4D0C9E692128853AFE29DC665FA993DCA9C903B7BF00B6442B9A76A5DADC6186317A"),
952	}
953	pemBlock, _ := pem.Decode([]byte(dsaCertPem))
954	cert, err := ParseCertificate(pemBlock.Bytes)
955	if err != nil {
956		t.Fatalf("Failed to parse certificate: %s", err)
957	}
958	if cert.PublicKeyAlgorithm != DSA {
959		t.Errorf("Parsed key algorithm was not DSA")
960	}
961	parsedKey, ok := cert.PublicKey.(*dsa.PublicKey)
962	if !ok {
963		t.Fatalf("Parsed key was not a DSA key: %s", err)
964	}
965	if expectedKey.Y.Cmp(parsedKey.Y) != 0 ||
966		expectedKey.P.Cmp(parsedKey.P) != 0 ||
967		expectedKey.Q.Cmp(parsedKey.Q) != 0 ||
968		expectedKey.G.Cmp(parsedKey.G) != 0 {
969		t.Fatal("Parsed key differs from expected key")
970	}
971}
972
973func TestParseCertificateWithDSASignatureAlgorithm(t *testing.T) {
974	pemBlock, _ := pem.Decode([]byte(dsaCertPem))
975	cert, err := ParseCertificate(pemBlock.Bytes)
976	if err != nil {
977		t.Fatalf("Failed to parse certificate: %s", err)
978	}
979	if cert.SignatureAlgorithm != DSAWithSHA1 {
980		t.Errorf("Parsed signature algorithm was not DSAWithSHA1")
981	}
982}
983
984func TestVerifyCertificateWithDSASignature(t *testing.T) {
985	pemBlock, _ := pem.Decode([]byte(dsaCertPem))
986	cert, err := ParseCertificate(pemBlock.Bytes)
987	if err != nil {
988		t.Fatalf("Failed to parse certificate: %s", err)
989	}
990	// test cert is self-signed
991	if err = cert.CheckSignatureFrom(cert); err == nil {
992		t.Fatalf("Expected error verifying DSA certificate")
993	}
994}
995
996var rsaPSSSelfSignedPEM = `-----BEGIN CERTIFICATE-----
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
1030-----END CERTIFICATE-----`
1031
1032// openssl req -newkey rsa:2048 -keyout test.key -sha256 -sigopt \
1033// rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -sigopt rsa_mgf1_md:sha256 \
1034// -x509 -days 3650 -nodes -subj '/C=US/ST=CA/L=SF/O=Test/CN=Test' -out \
1035// test.pem
1036var rsaPSSSelfSignedOpenSSL110PEM = `-----BEGIN CERTIFICATE-----
1037MIIDwDCCAnigAwIBAgIJAM9LAMHTE5xpMD0GCSqGSIb3DQEBCjAwoA0wCwYJYIZI
1038AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIDAgEgMEUxCzAJBgNV
1039BAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDTALBgNVBAoMBFRlc3Qx
1040DTALBgNVBAMMBFRlc3QwHhcNMTgwMjIyMjIxMzE4WhcNMjgwMjIwMjIxMzE4WjBF
1041MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMQ0wCwYDVQQK
1042DARUZXN0MQ0wCwYDVQQDDARUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
1043CgKCAQEA4Zrsydod+GoTAJLLutWNF87qhhVPBsK1zB1Gj+NAAe4+VbrZ1E41H1wp
1044qITx7DA8DRtJEf+NqrTAnAdZWBG/tAOA5LfXVax0ZSQtLnYLSeylLoMtDyY3eFAj
1045TmuTOoyVy6raktowCnHCh01NsstqqTfrx6SbmzOmDmKTkq/I+7K0MCVsn41xRDVM
1046+ShD0WGFGioEGoiWnFSWupxJDA3Q6jIDEygVwNKHwnhv/2NgG2kqZzrZSQA67en0
1047iKAXtoDNPpmyD5oS9YbEJ+2Nbm7oLeON30i6kZvXKIzJXx+UWViazHZqnsi5rQ8G
1048RHF+iVFXsqd0MzDKmkKOT5FDhrsbKQIDAQABo1MwUTAdBgNVHQ4EFgQU9uFY/nlg
1049gLH00NBnr/o7QvpN9ugwHwYDVR0jBBgwFoAU9uFY/nlggLH00NBnr/o7QvpN9ugw
1050DwYDVR0TAQH/BAUwAwEB/zA9BgkqhkiG9w0BAQowMKANMAsGCWCGSAFlAwQCAaEa
1051MBgGCSqGSIb3DQEBCDALBglghkgBZQMEAgGiAwIBIAOCAQEAhJzpwxBNGKvzKWDe
1052WLqv6RMrl/q4GcH3b7M9wjxe0yOm4F+Tb2zJ7re4h+D39YkJf8cX1NV9UQVu6z4s
1053Fvo2kmlR0qZOXAg5augmCQ1xS0WHFoF6B52anNzHkZQbAIYJ3kGoFsUHzs7Sz7F/
1054656FsRpHA9UzJQ3avPPMrA4Y4aoJ7ANJ6XIwTrdWrhULOVuvYRLCl4CdTVztVFX6
1055wxX8nS1ISYd8jXPUMgsBKVbWufvLoIymMJW8CZbpprVZel5zFn0bmPrON8IHS30w
1056Gs+ITJjKEnZgXmAQ25SLKVzkZkBcGANs2GsdHNJ370Puisy0FIPD2NXR5uASAf7J
1057+w9fjQ==
1058-----END CERTIFICATE-----`
1059
1060func TestRSAPSSSelfSigned(t *testing.T) {
1061	for i, pemBlock := range []string{rsaPSSSelfSignedPEM, rsaPSSSelfSignedOpenSSL110PEM} {
1062		der, _ := pem.Decode([]byte(pemBlock))
1063		if der == nil {
1064			t.Errorf("#%d: failed to find PEM block", i)
1065			continue
1066		}
1067
1068		cert, err := ParseCertificate(der.Bytes)
1069		if err != nil {
1070			t.Errorf("#%d: failed to parse: %s", i, err)
1071			continue
1072		}
1073
1074		if err = cert.CheckSignatureFrom(cert); err != nil {
1075			t.Errorf("#%d: signature check failed: %s", i, err)
1076			continue
1077		}
1078	}
1079}
1080
1081const ed25519Certificate = `
1082Certificate:
1083    Data:
1084        Version: 3 (0x2)
1085        Serial Number:
1086            0c:83:d8:21:2b:82:cb:23:98:23:63:e2:f7:97:8a:43:5b:f3:bd:92
1087        Signature Algorithm: ED25519
1088        Issuer: CN = Ed25519 test certificate
1089        Validity
1090            Not Before: May  6 17:27:16 2019 GMT
1091            Not After : Jun  5 17:27:16 2019 GMT
1092        Subject: CN = Ed25519 test certificate
1093        Subject Public Key Info:
1094            Public Key Algorithm: ED25519
1095                ED25519 Public-Key:
1096                pub:
1097                    36:29:c5:6c:0d:4f:14:6c:81:d0:ff:75:d3:6a:70:
1098                    5f:69:cd:0f:4d:66:d5:da:98:7e:82:49:89:a3:8a:
1099                    3c:fa
1100        X509v3 extensions:
1101            X509v3 Subject Key Identifier:
1102                09:3B:3A:9D:4A:29:D8:95:FF:68:BE:7B:43:54:72:E0:AD:A2:E3:AE
1103            X509v3 Authority Key Identifier:
1104                keyid:09:3B:3A:9D:4A:29:D8:95:FF:68:BE:7B:43:54:72:E0:AD:A2:E3:AE
1105
1106            X509v3 Basic Constraints: critical
1107                CA:TRUE
1108    Signature Algorithm: ED25519
1109         53:a5:58:1c:2c:3b:2a:9e:ac:9d:4e:a5:1d:5f:5d:6d:a6:b5:
1110         08:de:12:82:f3:97:20:ae:fa:d8:98:f4:1a:83:32:6b:91:f5:
1111         24:1d:c4:20:7f:2c:e2:4d:da:13:3b:6d:54:1a:d2:a8:28:dc:
1112         60:b9:d4:f4:78:4b:3c:1c:91:00
1113-----BEGIN CERTIFICATE-----
1114MIIBWzCCAQ2gAwIBAgIUDIPYISuCyyOYI2Pi95eKQ1vzvZIwBQYDK2VwMCMxITAf
1115BgNVBAMMGEVkMjU1MTkgdGVzdCBjZXJ0aWZpY2F0ZTAeFw0xOTA1MDYxNzI3MTZa
1116Fw0xOTA2MDUxNzI3MTZaMCMxITAfBgNVBAMMGEVkMjU1MTkgdGVzdCBjZXJ0aWZp
1117Y2F0ZTAqMAUGAytlcAMhADYpxWwNTxRsgdD/ddNqcF9pzQ9NZtXamH6CSYmjijz6
1118o1MwUTAdBgNVHQ4EFgQUCTs6nUop2JX/aL57Q1Ry4K2i464wHwYDVR0jBBgwFoAU
1119CTs6nUop2JX/aL57Q1Ry4K2i464wDwYDVR0TAQH/BAUwAwEB/zAFBgMrZXADQQBT
1120pVgcLDsqnqydTqUdX11tprUI3hKC85cgrvrYmPQagzJrkfUkHcQgfyziTdoTO21U
1121GtKoKNxgudT0eEs8HJEA
1122-----END CERTIFICATE-----`
1123
1124func TestEd25519SelfSigned(t *testing.T) {
1125	der, _ := pem.Decode([]byte(ed25519Certificate))
1126	if der == nil {
1127		t.Fatalf("Failed to find PEM block")
1128	}
1129
1130	cert, err := ParseCertificate(der.Bytes)
1131	if err != nil {
1132		t.Fatalf("Failed to parse: %s", err)
1133	}
1134
1135	if cert.PublicKeyAlgorithm != Ed25519 {
1136		t.Fatalf("Parsed key algorithm was not Ed25519")
1137	}
1138	parsedKey, ok := cert.PublicKey.(ed25519.PublicKey)
1139	if !ok {
1140		t.Fatalf("Parsed key was not an Ed25519 key: %s", err)
1141	}
1142	if len(parsedKey) != ed25519.PublicKeySize {
1143		t.Fatalf("Invalid Ed25519 key")
1144	}
1145
1146	if err = cert.CheckSignatureFrom(cert); err != nil {
1147		t.Fatalf("Signature check failed: %s", err)
1148	}
1149}
1150
1151const pemCertificate = `-----BEGIN CERTIFICATE-----
1152MIIDATCCAemgAwIBAgIRAKQkkrFx1T/dgB/Go/xBM5swDQYJKoZIhvcNAQELBQAw
1153EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MTcyMDM2MDdaFw0xNzA4MTcyMDM2
1154MDdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
1155ggEKAoIBAQDAoJtjG7M6InsWwIo+l3qq9u+g2rKFXNu9/mZ24XQ8XhV6PUR+5HQ4
1156jUFWC58ExYhottqK5zQtKGkw5NuhjowFUgWB/VlNGAUBHtJcWR/062wYrHBYRxJH
1157qVXOpYKbIWwFKoXu3hcpg/CkdOlDWGKoZKBCwQwUBhWE7MDhpVdQ+ZljUJWL+FlK
1158yQK5iRsJd5TGJ6VUzLzdT4fmN2DzeK6GLeyMpVpU3sWV90JJbxWQ4YrzkKzYhMmB
1159EcpXTG2wm+ujiHU/k2p8zlf8Sm7VBM/scmnMFt0ynNXop4FWvJzEm1G0xD2t+e2I
11605Utr04dOZPCgkm++QJgYhtZvgW7ZZiGTAgMBAAGjUjBQMA4GA1UdDwEB/wQEAwIF
1161oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBsGA1UdEQQUMBKC
1162EHRlc3QuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBADpqKQxrthH5InC7
1163X96UP0OJCu/lLEMkrjoEWYIQaFl7uLPxKH5AmQPH4lYwF7u7gksR7owVG9QU9fs6
11641fK7II9CVgCd/4tZ0zm98FmU4D0lHGtPARrrzoZaqVZcAvRnFTlPX5pFkPhVjjai
1165/mkxX9LpD8oK1445DFHxK5UjLMmPIIWd8EOi+v5a+hgGwnJpoW7hntSl8kHMtTmy
1166fnnktsblSUV4lRCit0ymC7Ojhe+gzCCwkgs5kDzVVag+tnl/0e2DloIjASwOhpbH
1167KVcg7fBd484ht/sS+l0dsB4KDOSpd8JzVDMF8OZqlaydizoJO0yWr9GbCN1+OKq5
1168EhLrEqU=
1169-----END CERTIFICATE-----`
1170
1171const ed25519CRLCertificate = `
1172Certificate:
1173Data:
1174	Version: 3 (0x2)
1175	Serial Number:
1176		7a:07:a0:9d:14:04:16:fc:1f:d8:e5:fe:d1:1d:1f:8d
1177	Signature Algorithm: ED25519
1178	Issuer: CN = Ed25519 CRL Test CA
1179	Validity
1180		Not Before: Oct 30 01:20:20 2019 GMT
1181		Not After : Dec 31 23:59:59 9999 GMT
1182	Subject: CN = Ed25519 CRL Test CA
1183	Subject Public Key Info:
1184		Public Key Algorithm: ED25519
1185			ED25519 Public-Key:
1186			pub:
1187				95:73:3b:b0:06:2a:31:5a:b6:a7:a6:6e:ef:71:df:
1188				ac:6f:6b:39:03:85:5e:63:4b:f8:a6:0f:68:c6:6f:
1189				75:21
1190	X509v3 extensions:
1191		X509v3 Key Usage: critical
1192			Digital Signature, Certificate Sign, CRL Sign
1193		X509v3 Extended Key Usage:
1194			TLS Web Client Authentication, TLS Web Server Authentication, OCSP Signing
1195		X509v3 Basic Constraints: critical
1196			CA:TRUE
1197		X509v3 Subject Key Identifier:
1198			B7:17:DA:16:EA:C5:ED:1F:18:49:44:D3:D2:E3:A0:35:0A:81:93:60
1199		X509v3 Authority Key Identifier:
1200			keyid:B7:17:DA:16:EA:C5:ED:1F:18:49:44:D3:D2:E3:A0:35:0A:81:93:60
1201
1202Signature Algorithm: ED25519
1203	 fc:3e:14:ea:bb:70:c2:6f:38:34:70:bc:c8:a7:f4:7c:0d:1e:
1204	 28:d7:2a:9f:22:8a:45:e8:02:76:84:1e:2d:64:2d:1e:09:b5:
1205	 29:71:1f:95:8a:4e:79:87:51:60:9a:e7:86:40:f6:60:c7:d1:
1206	 ee:68:76:17:1d:90:cc:92:93:07
1207-----BEGIN CERTIFICATE-----
1208MIIBijCCATygAwIBAgIQegegnRQEFvwf2OX+0R0fjTAFBgMrZXAwHjEcMBoGA1UE
1209AxMTRWQyNTUxOSBDUkwgVGVzdCBDQTAgFw0xOTEwMzAwMTIwMjBaGA85OTk5MTIz
1210MTIzNTk1OVowHjEcMBoGA1UEAxMTRWQyNTUxOSBDUkwgVGVzdCBDQTAqMAUGAytl
1211cAMhAJVzO7AGKjFatqembu9x36xvazkDhV5jS/imD2jGb3Uho4GNMIGKMA4GA1Ud
1212DwEB/wQEAwIBhjAnBgNVHSUEIDAeBggrBgEFBQcDAgYIKwYBBQUHAwEGCCsGAQUF
1213BwMJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLcX2hbqxe0fGElE09LjoDUK
1214gZNgMB8GA1UdIwQYMBaAFLcX2hbqxe0fGElE09LjoDUKgZNgMAUGAytlcANBAPw+
1215FOq7cMJvODRwvMin9HwNHijXKp8iikXoAnaEHi1kLR4JtSlxH5WKTnmHUWCa54ZA
12169mDH0e5odhcdkMySkwc=
1217-----END CERTIFICATE-----`
1218
1219var ed25519CRLKey = testingKey(`-----BEGIN TEST KEY-----
1220MC4CAQAwBQYDK2VwBCIEINdKh2096vUBYu4EIFpjShsUSh3vimKya1sQ1YTT4RZG
1221-----END TEST KEY-----`)
1222
1223func TestCRLCreation(t *testing.T) {
1224	block, _ := pem.Decode([]byte(pemPrivateKey))
1225	privRSA, _ := ParsePKCS1PrivateKey(block.Bytes)
1226	block, _ = pem.Decode([]byte(pemCertificate))
1227	certRSA, _ := ParseCertificate(block.Bytes)
1228
1229	block, _ = pem.Decode([]byte(ed25519CRLKey))
1230	privEd25519, _ := ParsePKCS8PrivateKey(block.Bytes)
1231	block, _ = pem.Decode([]byte(ed25519CRLCertificate))
1232	certEd25519, _ := ParseCertificate(block.Bytes)
1233
1234	tests := []struct {
1235		name string
1236		priv any
1237		cert *Certificate
1238	}{
1239		{"RSA CA", privRSA, certRSA},
1240		{"Ed25519 CA", privEd25519, certEd25519},
1241	}
1242
1243	loc := time.FixedZone("Oz/Atlantis", int((2 * time.Hour).Seconds()))
1244
1245	now := time.Unix(1000, 0).In(loc)
1246	nowUTC := now.UTC()
1247	expiry := time.Unix(10000, 0)
1248
1249	revokedCerts := []pkix.RevokedCertificate{
1250		{
1251			SerialNumber:   big.NewInt(1),
1252			RevocationTime: nowUTC,
1253		},
1254		{
1255			SerialNumber: big.NewInt(42),
1256			// RevocationTime should be converted to UTC before marshaling.
1257			RevocationTime: now,
1258		},
1259	}
1260	expectedCerts := []pkix.RevokedCertificate{
1261		{
1262			SerialNumber:   big.NewInt(1),
1263			RevocationTime: nowUTC,
1264		},
1265		{
1266			SerialNumber:   big.NewInt(42),
1267			RevocationTime: nowUTC,
1268		},
1269	}
1270
1271	for _, test := range tests {
1272		crlBytes, err := test.cert.CreateCRL(rand.Reader, test.priv, revokedCerts, now, expiry)
1273		if err != nil {
1274			t.Errorf("%s: error creating CRL: %s", test.name, err)
1275		}
1276
1277		parsedCRL, err := ParseDERCRL(crlBytes)
1278		if err != nil {
1279			t.Errorf("%s: error reparsing CRL: %s", test.name, err)
1280		}
1281		if !reflect.DeepEqual(parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) {
1282			t.Errorf("%s: RevokedCertificates mismatch: got %v; want %v.", test.name,
1283				parsedCRL.TBSCertList.RevokedCertificates, expectedCerts)
1284		}
1285	}
1286}
1287
1288func fromBase64(in string) []byte {
1289	out := make([]byte, base64.StdEncoding.DecodedLen(len(in)))
1290	n, err := base64.StdEncoding.Decode(out, []byte(in))
1291	if err != nil {
1292		panic("failed to base64 decode")
1293	}
1294	return out[:n]
1295}
1296
1297func TestParseDERCRL(t *testing.T) {
1298	derBytes := fromBase64(derCRLBase64)
1299	certList, err := ParseDERCRL(derBytes)
1300	if err != nil {
1301		t.Errorf("error parsing: %s", err)
1302		return
1303	}
1304	numCerts := len(certList.TBSCertList.RevokedCertificates)
1305	expected := 88
1306	if numCerts != expected {
1307		t.Errorf("bad number of revoked certificates. got: %d want: %d", numCerts, expected)
1308	}
1309
1310	if certList.HasExpired(time.Unix(1302517272, 0)) {
1311		t.Errorf("CRL has expired (but shouldn't have)")
1312	}
1313
1314	// Can't check the signature here without a package cycle.
1315}
1316
1317func TestCRLWithoutExpiry(t *testing.T) {
1318	derBytes := fromBase64("MIHYMIGZMAkGByqGSM44BAMwEjEQMA4GA1UEAxMHQ2FybERTUxcNOTkwODI3MDcwMDAwWjBpMBMCAgDIFw05OTA4MjIwNzAwMDBaMBMCAgDJFw05OTA4MjIwNzAwMDBaMBMCAgDTFw05OTA4MjIwNzAwMDBaMBMCAgDSFw05OTA4MjIwNzAwMDBaMBMCAgDUFw05OTA4MjQwNzAwMDBaMAkGByqGSM44BAMDLwAwLAIUfmVSdjP+NHMX0feW+aDU2G1cfT0CFAJ6W7fVWxjBz4fvftok8yqDnDWh")
1319	certList, err := ParseDERCRL(derBytes)
1320	if err != nil {
1321		t.Fatal(err)
1322	}
1323	if !certList.TBSCertList.NextUpdate.IsZero() {
1324		t.Errorf("NextUpdate is not the zero value")
1325	}
1326}
1327
1328func TestParsePEMCRL(t *testing.T) {
1329	pemBytes := fromBase64(pemCRLBase64)
1330	certList, err := ParseCRL(pemBytes)
1331	if err != nil {
1332		t.Errorf("error parsing: %s", err)
1333		return
1334	}
1335	numCerts := len(certList.TBSCertList.RevokedCertificates)
1336	expected := 2
1337	if numCerts != expected {
1338		t.Errorf("bad number of revoked certificates. got: %d want: %d", numCerts, expected)
1339	}
1340
1341	if certList.HasExpired(time.Unix(1302517272, 0)) {
1342		t.Errorf("CRL has expired (but shouldn't have)")
1343	}
1344
1345	// Can't check the signature here without a package cycle.
1346}
1347
1348func TestImports(t *testing.T) {
1349	if testing.Short() {
1350		t.Skip("skipping in -short mode")
1351	}
1352	testenv.MustHaveGoRun(t)
1353
1354	if out, err := exec.Command(testenv.GoToolPath(t), "run", "x509_test_import.go").CombinedOutput(); err != nil {
1355		t.Errorf("failed to run x509_test_import.go: %s\n%s", err, out)
1356	}
1357}
1358
1359const derCRLBase64 = "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"
1360
1361const pemCRLBase64 = "LS0tLS1CRUdJTiBYNTA5IENSTC0tLS0tDQpNSUlCOWpDQ0FWOENBUUV3RFFZSktvWklodmNOQVFFRkJRQXdiREVhTUJnR0ExVUVDaE1SVWxOQklGTmxZM1Z5DQphWFI1SUVsdVl5NHhIakFjQmdOVkJBTVRGVkpUUVNCUWRXSnNhV01nVW05dmRDQkRRU0IyTVRFdU1Dd0dDU3FHDQpTSWIzRFFFSkFSWWZjbk5oYTJWdmJuSnZiM1J6YVdkdVFISnpZWE5sWTNWeWFYUjVMbU52YlJjTk1URXdNakl6DQpNVGt5T0RNd1doY05NVEV3T0RJeU1Ua3lPRE13V2pDQmpEQktBaEVBckRxb2g5RkhKSFhUN09QZ3V1bjQrQmNODQpNRGt4TVRBeU1UUXlOekE1V2pBbU1Bb0dBMVVkRlFRRENnRUpNQmdHQTFVZEdBUVJHQTh5TURBNU1URXdNakUwDQpNalExTlZvd1BnSVJBTEd6blowOTVQQjVhQU9MUGc1N2ZNTVhEVEF5TVRBeU16RTBOVEF4TkZvd0dqQVlCZ05WDQpIUmdFRVJnUE1qQXdNakV3TWpNeE5EVXdNVFJhb0RBd0xqQWZCZ05WSFNNRUdEQVdnQlQxVERGNlVRTS9MTmVMDQpsNWx2cUhHUXEzZzltekFMQmdOVkhSUUVCQUlDQUlRd0RRWUpLb1pJaHZjTkFRRUZCUUFEZ1lFQUZVNUFzNk16DQpxNVBSc2lmYW9iUVBHaDFhSkx5QytNczVBZ2MwYld5QTNHQWR4dXI1U3BQWmVSV0NCamlQL01FSEJXSkNsQkhQDQpHUmNxNXlJZDNFakRrYUV5eFJhK2k2N0x6dmhJNmMyOUVlNks5cFNZd2ppLzdSVWhtbW5Qclh0VHhsTDBsckxyDQptUVFKNnhoRFJhNUczUUE0Q21VZHNITnZicnpnbUNZcHZWRT0NCi0tLS0tRU5EIFg1MDkgQ1JMLS0tLS0NCg0K"
1362
1363func TestCreateCertificateRequest(t *testing.T) {
1364	random := rand.Reader
1365
1366	ecdsa256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
1367	if err != nil {
1368		t.Fatalf("Failed to generate ECDSA key: %s", err)
1369	}
1370
1371	ecdsa384Priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
1372	if err != nil {
1373		t.Fatalf("Failed to generate ECDSA key: %s", err)
1374	}
1375
1376	ecdsa521Priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
1377	if err != nil {
1378		t.Fatalf("Failed to generate ECDSA key: %s", err)
1379	}
1380
1381	_, ed25519Priv, err := ed25519.GenerateKey(random)
1382	if err != nil {
1383		t.Fatalf("Failed to generate Ed25519 key: %s", err)
1384	}
1385
1386	tests := []struct {
1387		name    string
1388		priv    any
1389		sigAlgo SignatureAlgorithm
1390	}{
1391		{"RSA", testPrivateKey, SHA256WithRSA},
1392		{"ECDSA-256", ecdsa256Priv, ECDSAWithSHA256},
1393		{"ECDSA-384", ecdsa384Priv, ECDSAWithSHA256},
1394		{"ECDSA-521", ecdsa521Priv, ECDSAWithSHA256},
1395		{"Ed25519", ed25519Priv, PureEd25519},
1396	}
1397
1398	for _, test := range tests {
1399		template := CertificateRequest{
1400			Subject: pkix.Name{
1401				CommonName:   "test.example.com",
1402				Organization: []string{"Σ Acme Co"},
1403			},
1404			SignatureAlgorithm: test.sigAlgo,
1405			DNSNames:           []string{"test.example.com"},
1406			EmailAddresses:     []string{"gopher@golang.org"},
1407			IPAddresses:        []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
1408		}
1409
1410		derBytes, err := CreateCertificateRequest(random, &template, test.priv)
1411		if err != nil {
1412			t.Errorf("%s: failed to create certificate request: %s", test.name, err)
1413			continue
1414		}
1415
1416		out, err := ParseCertificateRequest(derBytes)
1417		if err != nil {
1418			t.Errorf("%s: failed to create certificate request: %s", test.name, err)
1419			continue
1420		}
1421
1422		err = out.CheckSignature()
1423		if err != nil {
1424			t.Errorf("%s: failed to check certificate request signature: %s", test.name, err)
1425			continue
1426		}
1427
1428		if out.Subject.CommonName != template.Subject.CommonName {
1429			t.Errorf("%s: output subject common name and template subject common name don't match", test.name)
1430		} else if len(out.Subject.Organization) != len(template.Subject.Organization) {
1431			t.Errorf("%s: output subject organisation and template subject organisation don't match", test.name)
1432		} else if len(out.DNSNames) != len(template.DNSNames) {
1433			t.Errorf("%s: output DNS names and template DNS names don't match", test.name)
1434		} else if len(out.EmailAddresses) != len(template.EmailAddresses) {
1435			t.Errorf("%s: output email addresses and template email addresses don't match", test.name)
1436		} else if len(out.IPAddresses) != len(template.IPAddresses) {
1437			t.Errorf("%s: output IP addresses and template IP addresses names don't match", test.name)
1438		}
1439	}
1440}
1441
1442func marshalAndParseCSR(t *testing.T, template *CertificateRequest) *CertificateRequest {
1443	derBytes, err := CreateCertificateRequest(rand.Reader, template, testPrivateKey)
1444	if err != nil {
1445		t.Fatal(err)
1446	}
1447
1448	csr, err := ParseCertificateRequest(derBytes)
1449	if err != nil {
1450		t.Fatal(err)
1451	}
1452
1453	return csr
1454}
1455
1456func TestCertificateRequestOverrides(t *testing.T) {
1457	sanContents, err := marshalSANs([]string{"foo.example.com"}, nil, nil, nil)
1458	if err != nil {
1459		t.Fatal(err)
1460	}
1461
1462	template := CertificateRequest{
1463		Subject: pkix.Name{
1464			CommonName:   "test.example.com",
1465			Organization: []string{"Σ Acme Co"},
1466		},
1467		DNSNames: []string{"test.example.com"},
1468
1469		// An explicit extension should override the DNSNames from the
1470		// template.
1471		ExtraExtensions: []pkix.Extension{
1472			{
1473				Id:       oidExtensionSubjectAltName,
1474				Value:    sanContents,
1475				Critical: true,
1476			},
1477		},
1478	}
1479
1480	csr := marshalAndParseCSR(t, &template)
1481
1482	if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "foo.example.com" {
1483		t.Errorf("Extension did not override template. Got %v\n", csr.DNSNames)
1484	}
1485
1486	if len(csr.Extensions) != 1 || !csr.Extensions[0].Id.Equal(oidExtensionSubjectAltName) || !csr.Extensions[0].Critical {
1487		t.Errorf("SAN extension was not faithfully copied, got %#v", csr.Extensions)
1488	}
1489
1490	// If there is already an attribute with X.509 extensions then the
1491	// extra extensions should be added to it rather than creating a CSR
1492	// with two extension attributes.
1493
1494	template.Attributes = []pkix.AttributeTypeAndValueSET{
1495		{
1496			Type: oidExtensionRequest,
1497			Value: [][]pkix.AttributeTypeAndValue{
1498				{
1499					{
1500						Type:  oidExtensionAuthorityInfoAccess,
1501						Value: []byte("foo"),
1502					},
1503				},
1504			},
1505		},
1506	}
1507
1508	csr = marshalAndParseCSR(t, &template)
1509	if l := len(csr.Attributes); l != 1 {
1510		t.Errorf("incorrect number of attributes: %d\n", l)
1511	}
1512
1513	if !csr.Attributes[0].Type.Equal(oidExtensionRequest) ||
1514		len(csr.Attributes[0].Value) != 1 ||
1515		len(csr.Attributes[0].Value[0]) != 2 {
1516		t.Errorf("bad attributes: %#v\n", csr.Attributes)
1517	}
1518
1519	sanContents2, err := marshalSANs([]string{"foo2.example.com"}, nil, nil, nil)
1520	if err != nil {
1521		t.Fatal(err)
1522	}
1523
1524	// Extensions in Attributes should override those in ExtraExtensions.
1525	template.Attributes[0].Value[0] = append(template.Attributes[0].Value[0], pkix.AttributeTypeAndValue{
1526		Type:  oidExtensionSubjectAltName,
1527		Value: sanContents2,
1528	})
1529
1530	csr = marshalAndParseCSR(t, &template)
1531
1532	if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "foo2.example.com" {
1533		t.Errorf("Attributes did not override ExtraExtensions. Got %v\n", csr.DNSNames)
1534	}
1535}
1536
1537func TestParseCertificateRequest(t *testing.T) {
1538	for _, csrBase64 := range csrBase64Array {
1539		csrBytes := fromBase64(csrBase64)
1540		csr, err := ParseCertificateRequest(csrBytes)
1541		if err != nil {
1542			t.Fatalf("failed to parse CSR: %s", err)
1543		}
1544
1545		if len(csr.EmailAddresses) != 1 || csr.EmailAddresses[0] != "gopher@golang.org" {
1546			t.Errorf("incorrect email addresses found: %v", csr.EmailAddresses)
1547		}
1548
1549		if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "test.example.com" {
1550			t.Errorf("incorrect DNS names found: %v", csr.DNSNames)
1551		}
1552
1553		if len(csr.Subject.Country) != 1 || csr.Subject.Country[0] != "AU" {
1554			t.Errorf("incorrect Subject name: %v", csr.Subject)
1555		}
1556
1557		found := false
1558		for _, e := range csr.Extensions {
1559			if e.Id.Equal(oidExtensionBasicConstraints) {
1560				found = true
1561				break
1562			}
1563		}
1564		if !found {
1565			t.Errorf("basic constraints extension not found in CSR")
1566		}
1567	}
1568}
1569
1570func TestCriticalFlagInCSRRequestedExtensions(t *testing.T) {
1571	// This CSR contains an extension request where the extensions have a
1572	// critical flag in them. In the past we failed to handle this.
1573	const csrBase64 = "MIICrTCCAZUCAQIwMzEgMB4GA1UEAwwXU0NFUCBDQSBmb3IgRGV2ZWxlciBTcmwxDzANBgNVBAsMBjQzNTk3MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALFMAJ7Zy9YyfgbNlbUWAW0LalNRMPs7aXmLANsCpjhnw3lLlfDPaLeWyKh1nK5I5ojaJOW6KIOSAcJkDUe3rrE0wR0RVt3UxArqs0R/ND3u5Q+bDQY2X1HAFUHzUzcdm5JRAIA355v90teMckaWAIlkRQjDE22Lzc6NAl64KOd1rqOUNj8+PfX6fSo20jm94Pp1+a6mfk3G/RUWVuSm7owO5DZI/Fsi2ijdmb4NUar6K/bDKYTrDFkzcqAyMfP3TitUtBp19Mp3B1yAlHjlbp/r5fSSXfOGHZdgIvp0WkLuK2u5eQrX5l7HMB/5epgUs3HQxKY6ljhh5wAjDwz//LsCAwEAAaA1MDMGCSqGSIb3DQEJDjEmMCQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQEFBQADggEBAAMq3bxJSPQEgzLYR/yaVvgjCDrc3zUbIwdOis6Go06Q4RnjH5yRaSZAqZQTDsPurQcnz2I39VMGEiSkFJFavf4QHIZ7QFLkyXadMtALc87tm17Ej719SbHcBSSZayR9VYJUNXRLayI6HvyUrmqcMKh+iX3WY3ICr59/wlM0tYa8DYN4yzmOa2Onb29gy3YlaF5A2AKAMmk003cRT9gY26mjpv7d21czOSSeNyVIoZ04IR9ee71vWTMdv0hu/af5kSjQ+ZG5/Qgc0+mnECLz/1gtxt1srLYbtYQ/qAY8oX1DCSGFS61tN/vl+4cxGMD/VGcGzADRLRHSlVqy2Qgss6Q="
1574
1575	csrBytes := fromBase64(csrBase64)
1576	csr, err := ParseCertificateRequest(csrBytes)
1577	if err != nil {
1578		t.Fatalf("failed to parse CSR: %s", err)
1579	}
1580
1581	expected := []struct {
1582		Id    asn1.ObjectIdentifier
1583		Value []byte
1584	}{
1585		{oidExtensionBasicConstraints, fromBase64("MAYBAf8CAQA=")},
1586		{oidExtensionKeyUsage, fromBase64("AwIChA==")},
1587	}
1588
1589	if n := len(csr.Extensions); n != len(expected) {
1590		t.Fatalf("expected to find %d extensions but found %d", len(expected), n)
1591	}
1592
1593	for i, extension := range csr.Extensions {
1594		if !extension.Id.Equal(expected[i].Id) {
1595			t.Fatalf("extension #%d has unexpected type %v (expected %v)", i, extension.Id, expected[i].Id)
1596		}
1597
1598		if !bytes.Equal(extension.Value, expected[i].Value) {
1599			t.Fatalf("extension #%d has unexpected contents %x (expected %x)", i, extension.Value, expected[i].Value)
1600		}
1601	}
1602}
1603
1604// serialiseAndParse generates a self-signed certificate from template and
1605// returns a parsed version of it.
1606func serialiseAndParse(t *testing.T, template *Certificate) *Certificate {
1607	derBytes, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey)
1608	if err != nil {
1609		t.Fatalf("failed to create certificate: %s", err)
1610		return nil
1611	}
1612
1613	cert, err := ParseCertificate(derBytes)
1614	if err != nil {
1615		t.Fatalf("failed to parse certificate: %s", err)
1616		return nil
1617	}
1618
1619	return cert
1620}
1621
1622func TestMaxPathLenNotCA(t *testing.T) {
1623	template := &Certificate{
1624		SerialNumber: big.NewInt(1),
1625		Subject: pkix.Name{
1626			CommonName: "Σ Acme Co",
1627		},
1628		NotBefore: time.Unix(1000, 0),
1629		NotAfter:  time.Unix(100000, 0),
1630
1631		BasicConstraintsValid: true,
1632		IsCA:                  false,
1633	}
1634	if m := serialiseAndParse(t, template).MaxPathLen; m != -1 {
1635		t.Errorf("MaxPathLen should be -1 when IsCa is false, got %d", m)
1636	}
1637
1638	template.MaxPathLen = -1
1639	if m := serialiseAndParse(t, template).MaxPathLen; m != -1 {
1640		t.Errorf("MaxPathLen should be -1 when IsCa is false and MaxPathLen set to -1, got %d", m)
1641	}
1642
1643	template.MaxPathLen = 5
1644	if _, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey); err == nil {
1645		t.Error("specifying a MaxPathLen when IsCA is false should fail")
1646	}
1647
1648	template.MaxPathLen = 0
1649	template.MaxPathLenZero = true
1650	if _, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey); err == nil {
1651		t.Error("setting MaxPathLenZero when IsCA is false should fail")
1652	}
1653
1654	template.BasicConstraintsValid = false
1655	if m := serialiseAndParse(t, template).MaxPathLen; m != 0 {
1656		t.Errorf("Bad MaxPathLen should be ignored if BasicConstraintsValid is false, got %d", m)
1657	}
1658}
1659
1660func TestMaxPathLen(t *testing.T) {
1661	template := &Certificate{
1662		SerialNumber: big.NewInt(1),
1663		Subject: pkix.Name{
1664			CommonName: "Σ Acme Co",
1665		},
1666		NotBefore: time.Unix(1000, 0),
1667		NotAfter:  time.Unix(100000, 0),
1668
1669		BasicConstraintsValid: true,
1670		IsCA:                  true,
1671	}
1672
1673	cert1 := serialiseAndParse(t, template)
1674	if m := cert1.MaxPathLen; m != -1 {
1675		t.Errorf("Omitting MaxPathLen didn't turn into -1, got %d", m)
1676	}
1677	if cert1.MaxPathLenZero {
1678		t.Errorf("Omitting MaxPathLen resulted in MaxPathLenZero")
1679	}
1680
1681	template.MaxPathLen = 1
1682	cert2 := serialiseAndParse(t, template)
1683	if m := cert2.MaxPathLen; m != 1 {
1684		t.Errorf("Setting MaxPathLen didn't work. Got %d but set 1", m)
1685	}
1686	if cert2.MaxPathLenZero {
1687		t.Errorf("Setting MaxPathLen resulted in MaxPathLenZero")
1688	}
1689
1690	template.MaxPathLen = 0
1691	template.MaxPathLenZero = true
1692	cert3 := serialiseAndParse(t, template)
1693	if m := cert3.MaxPathLen; m != 0 {
1694		t.Errorf("Setting MaxPathLenZero didn't work, got %d", m)
1695	}
1696	if !cert3.MaxPathLenZero {
1697		t.Errorf("Setting MaxPathLen to zero didn't result in MaxPathLenZero")
1698	}
1699}
1700
1701func TestNoAuthorityKeyIdInSelfSignedCert(t *testing.T) {
1702	template := &Certificate{
1703		SerialNumber: big.NewInt(1),
1704		Subject: pkix.Name{
1705			CommonName: "Σ Acme Co",
1706		},
1707		NotBefore: time.Unix(1000, 0),
1708		NotAfter:  time.Unix(100000, 0),
1709
1710		BasicConstraintsValid: true,
1711		IsCA:                  true,
1712		SubjectKeyId:          []byte{1, 2, 3, 4},
1713	}
1714
1715	if cert := serialiseAndParse(t, template); len(cert.AuthorityKeyId) != 0 {
1716		t.Fatalf("self-signed certificate contained default authority key id")
1717	}
1718
1719	template.AuthorityKeyId = []byte{1, 2, 3, 4}
1720	if cert := serialiseAndParse(t, template); len(cert.AuthorityKeyId) == 0 {
1721		t.Fatalf("self-signed certificate erased explicit authority key id")
1722	}
1723}
1724
1725func TestNoSubjectKeyIdInCert(t *testing.T) {
1726	template := &Certificate{
1727		SerialNumber: big.NewInt(1),
1728		Subject: pkix.Name{
1729			CommonName: "Σ Acme Co",
1730		},
1731		NotBefore: time.Unix(1000, 0),
1732		NotAfter:  time.Unix(100000, 0),
1733
1734		BasicConstraintsValid: true,
1735		IsCA:                  true,
1736	}
1737	if cert := serialiseAndParse(t, template); len(cert.SubjectKeyId) == 0 {
1738		t.Fatalf("self-signed certificate did not generate subject key id using the public key")
1739	}
1740
1741	template.IsCA = false
1742	if cert := serialiseAndParse(t, template); len(cert.SubjectKeyId) != 0 {
1743		t.Fatalf("self-signed certificate generated subject key id when it isn't a CA")
1744	}
1745
1746	template.SubjectKeyId = []byte{1, 2, 3, 4}
1747	if cert := serialiseAndParse(t, template); len(cert.SubjectKeyId) == 0 {
1748		t.Fatalf("self-signed certificate erased explicit subject key id")
1749	}
1750}
1751
1752func TestASN1BitLength(t *testing.T) {
1753	tests := []struct {
1754		bytes  []byte
1755		bitLen int
1756	}{
1757		{nil, 0},
1758		{[]byte{0x00}, 0},
1759		{[]byte{0x00, 0x00}, 0},
1760		{[]byte{0xf0}, 4},
1761		{[]byte{0x88}, 5},
1762		{[]byte{0xff}, 8},
1763		{[]byte{0xff, 0x80}, 9},
1764		{[]byte{0xff, 0x81}, 16},
1765	}
1766
1767	for i, test := range tests {
1768		if got := asn1BitLength(test.bytes); got != test.bitLen {
1769			t.Errorf("#%d: calculated bit-length of %d for %x, wanted %d", i, got, test.bytes, test.bitLen)
1770		}
1771	}
1772}
1773
1774func TestVerifyEmptyCertificate(t *testing.T) {
1775	if _, err := new(Certificate).Verify(VerifyOptions{}); err != errNotParsed {
1776		t.Errorf("Verifying empty certificate resulted in unexpected error: %q (wanted %q)", err, errNotParsed)
1777	}
1778}
1779
1780func TestInsecureAlgorithmErrorString(t *testing.T) {
1781	tests := []struct {
1782		sa   SignatureAlgorithm
1783		want string
1784	}{
1785		{MD5WithRSA, "x509: cannot verify signature: insecure algorithm MD5-RSA"},
1786		{SHA1WithRSA, "x509: cannot verify signature: insecure algorithm SHA1-RSA (temporarily override with GODEBUG=x509sha1=1)"},
1787		{ECDSAWithSHA1, "x509: cannot verify signature: insecure algorithm ECDSA-SHA1 (temporarily override with GODEBUG=x509sha1=1)"},
1788		{MD2WithRSA, "x509: cannot verify signature: insecure algorithm MD2-RSA"},
1789		{-1, "x509: cannot verify signature: insecure algorithm -1"},
1790		{0, "x509: cannot verify signature: insecure algorithm 0"},
1791		{9999, "x509: cannot verify signature: insecure algorithm 9999"},
1792	}
1793	for i, tt := range tests {
1794		if got := fmt.Sprint(InsecureAlgorithmError(tt.sa)); got != tt.want {
1795			t.Errorf("%d. mismatch.\n got: %s\nwant: %s\n", i, got, tt.want)
1796		}
1797	}
1798}
1799
1800// These CSR was generated with OpenSSL:
1801//  openssl req -out CSR.csr -new -sha256 -nodes -keyout privateKey.key -config openssl.cnf
1802//
1803// With openssl.cnf containing the following sections:
1804//   [ v3_req ]
1805//   basicConstraints = CA:FALSE
1806//   keyUsage = nonRepudiation, digitalSignature, keyEncipherment
1807//   subjectAltName = email:gopher@golang.org,DNS:test.example.com
1808//   [ req_attributes ]
1809//   challengePassword = ignored challenge
1810//   unstructuredName  = ignored unstructured name
1811var csrBase64Array = [...]string{
1812	// Just [ v3_req ]
1813	"MIIDHDCCAgQCAQAwfjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLQ29tbW9uIE5hbWUxITAfBgkqhkiG9w0BCQEWEnRlc3RAZW1haWwuYWRkcmVzczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK1GY4YFx2ujlZEOJxQVYmsjUnLsd5nFVnNpLE4cV+77sgv9NPNlB8uhn3MXt5leD34rm/2BisCHOifPucYlSrszo2beuKhvwn4+2FxDmWtBEMu/QA16L5IvoOfYZm/gJTsPwKDqvaR0tTU67a9OtxwNTBMI56YKtmwd/o8d3hYv9cg+9ZGAZ/gKONcg/OWYx/XRh6bd0g8DMbCikpWgXKDsvvK1Nk+VtkDO1JxuBaj4Lz/p/MifTfnHoqHxWOWl4EaTs4Ychxsv34/rSj1KD1tJqorIv5Xv2aqv4sjxfbrYzX4kvS5SC1goIovLnhj5UjmQ3Qy8u65eow/LLWw+YFcCAwEAAaBZMFcGCSqGSIb3DQEJDjFKMEgwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwLgYDVR0RBCcwJYERZ29waGVyQGdvbGFuZy5vcmeCEHRlc3QuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBAB6VPMRrchvNW61Tokyq3ZvO6/NoGIbuwUn54q6l5VZW0Ep5Nq8juhegSSnaJ0jrovmUgKDN9vEo2KxuAtwG6udS6Ami3zP+hRd4k9Q8djJPb78nrjzWiindLK5Fps9U5mMoi1ER8ViveyAOTfnZt/jsKUaRsscY2FzE9t9/o5moE6LTcHUS4Ap1eheR+J72WOnQYn3cifYaemsA9MJuLko+kQ6xseqttbh9zjqd9fiCSh/LNkzos9c+mg2yMADitaZinAh+HZi50ooEbjaT3erNq9O6RqwJlgD00g6MQdoz9bTAryCUhCQfkIaepmQ7BxS0pqWNW3MMwfDwx/Snz6g=",
1814	// Both [ v3_req ] and [ req_attributes ]
1815	"MIIDaTCCAlECAQAwfjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLQ29tbW9uIE5hbWUxITAfBgkqhkiG9w0BCQEWEnRlc3RAZW1haWwuYWRkcmVzczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK1GY4YFx2ujlZEOJxQVYmsjUnLsd5nFVnNpLE4cV+77sgv9NPNlB8uhn3MXt5leD34rm/2BisCHOifPucYlSrszo2beuKhvwn4+2FxDmWtBEMu/QA16L5IvoOfYZm/gJTsPwKDqvaR0tTU67a9OtxwNTBMI56YKtmwd/o8d3hYv9cg+9ZGAZ/gKONcg/OWYx/XRh6bd0g8DMbCikpWgXKDsvvK1Nk+VtkDO1JxuBaj4Lz/p/MifTfnHoqHxWOWl4EaTs4Ychxsv34/rSj1KD1tJqorIv5Xv2aqv4sjxfbrYzX4kvS5SC1goIovLnhj5UjmQ3Qy8u65eow/LLWw+YFcCAwEAAaCBpTAgBgkqhkiG9w0BCQcxEwwRaWdub3JlZCBjaGFsbGVuZ2UwKAYJKoZIhvcNAQkCMRsMGWlnbm9yZWQgdW5zdHJ1Y3R1cmVkIG5hbWUwVwYJKoZIhvcNAQkOMUowSDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAuBgNVHREEJzAlgRFnb3BoZXJAZ29sYW5nLm9yZ4IQdGVzdC5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAgxe2N5O48EMsYE7o0rZBB0wi3Ov5/yYfnmmVI22Y3sP6VXbLDW0+UWIeSccOhzUCcZ/G4qcrfhhx6gTZTeA01nP7TdTJURvWAH5iFqj9sQ0qnLq6nEcVHij3sG6M5+BxAIVClQBk6lTCzgphc835Fjj6qSLuJ20XHdL5UfUbiJxx299CHgyBRL+hBUIPfz8p+ZgamyAuDLfnj54zzcRVyLlrmMLNPZNll1Q70RxoU6uWvLH8wB8vQe3Q/guSGubLyLRTUQVPh+dw1L4t8MKFWfX/48jwRM4gIRHFHPeAAE9D9YAoqdIvj/iFm/eQ++7DP8MDwOZWsXeB6jjwHuLmkQ==",
1816}
1817
1818var md5cert = `
1819-----BEGIN CERTIFICATE-----
1820MIIB4TCCAUoCCQCfmw3vMgPS5TANBgkqhkiG9w0BAQQFADA1MQswCQYDVQQGEwJB
1821VTETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMITUQ1IEluYy4wHhcNMTUx
1822MjAzMTkyOTMyWhcNMjkwODEyMTkyOTMyWjA1MQswCQYDVQQGEwJBVTETMBEGA1UE
1823CBMKU29tZS1TdGF0ZTERMA8GA1UEChMITUQ1IEluYy4wgZ8wDQYJKoZIhvcNAQEB
1824BQADgY0AMIGJAoGBANrq2nhLQj5mlXbpVX3QUPhfEm/vdEqPkoWtR/jRZIWm4WGf
1825Wpq/LKHJx2Pqwn+t117syN8l4U5unyAi1BJSXjBwPZNd7dXjcuJ+bRLV7FZ/iuvs
1826cfYyQQFTxan4TaJMd0x1HoNDbNbjHa02IyjjYE/r3mb/PIg+J2t5AZEh80lPAgMB
1827AAEwDQYJKoZIhvcNAQEEBQADgYEAjGzp3K3ey/YfKHohf33yHHWd695HQxDAP+wY
1828cs9/TAyLR+gJzJP7d18EcDDLJWVi7bhfa4EAD86di05azOh9kWSn4b3o9QYRGCSw
1829GNnI3Zk0cwNKA49hZntKKiy22DhRk7JAHF01d6Bu3KkHkmENrtJ+zj/+159WAnUa
1830qViorq4=
1831-----END CERTIFICATE-----
1832`
1833
1834func TestMD5(t *testing.T) {
1835	pemBlock, _ := pem.Decode([]byte(md5cert))
1836	cert, err := ParseCertificate(pemBlock.Bytes)
1837	if err != nil {
1838		t.Fatalf("failed to parse certificate: %s", err)
1839	}
1840	if sa := cert.SignatureAlgorithm; sa != MD5WithRSA {
1841		t.Errorf("signature algorithm is %v, want %v", sa, MD5WithRSA)
1842	}
1843	if err = cert.CheckSignatureFrom(cert); err == nil {
1844		t.Fatalf("certificate verification succeeded incorrectly")
1845	}
1846	if _, ok := err.(InsecureAlgorithmError); !ok {
1847		t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err)
1848	}
1849}
1850
1851func TestSHA1(t *testing.T) {
1852	pemBlock, _ := pem.Decode([]byte(ecdsaSHA1CertPem))
1853	cert, err := ParseCertificate(pemBlock.Bytes)
1854	if err != nil {
1855		t.Fatalf("failed to parse certificate: %s", err)
1856	}
1857	if sa := cert.SignatureAlgorithm; sa != ECDSAWithSHA1 {
1858		t.Errorf("signature algorithm is %v, want %v", sa, ECDSAWithSHA1)
1859	}
1860	if err = cert.CheckSignatureFrom(cert); err == nil {
1861		t.Fatalf("certificate verification succeeded incorrectly")
1862	}
1863	if _, ok := err.(InsecureAlgorithmError); !ok {
1864		t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err)
1865	}
1866
1867	defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1)
1868	debugAllowSHA1 = true
1869
1870	if err = cert.CheckSignatureFrom(cert); err != nil {
1871		t.Fatalf("SHA-1 certificate did not verify with GODEBUG=x509sha1=1: %v", err)
1872	}
1873}
1874
1875// certMissingRSANULL contains an RSA public key where the AlgorithmIdentifier
1876// parameters are omitted rather than being an ASN.1 NULL.
1877const certMissingRSANULL = `
1878-----BEGIN CERTIFICATE-----
1879MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
1880bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4
1881MDAxMlowJjEQMA4GA1UEChMHQWNtZSBDbzESMBAGA1UEAxMJMTI3LjAuMC4xMIGc
1882MAsGCSqGSIb3DQEBAQOBjAAwgYgCgYBO0Hsx44Jk2VnAwoekXh6LczPHY1PfZpIG
1883hPZk1Y/kNqcdK+izIDZFI7Xjla7t4PUgnI2V339aEu+H5Fto5OkOdOwEin/ekyfE
1884ARl6vfLcPRSr0FTKIQzQTW6HLlzF0rtNS0/Otiz3fojsfNcCkXSmHgwa2uNKWi7e
1885E5xMQIhZkwIDAQABozIwMDAOBgNVHQ8BAf8EBAMCAKAwDQYDVR0OBAYEBAECAwQw
1886DwYDVR0jBAgwBoAEAQIDBDALBgkqhkiG9w0BAQUDgYEANh+zegx1yW43RmEr1b3A
1887p0vMRpqBWHyFeSnIyMZn3TJWRSt1tukkqVCavh9a+hoV2cxVlXIWg7nCto/9iIw4
1888hB2rXZIxE0/9gzvGnfERYraL7KtnvshksBFQRlgXa5kc0x38BvEO5ZaoDPl4ILdE
1889GFGNEH5PlGffo05wc46QkYU=
1890-----END CERTIFICATE-----`
1891
1892func TestRSAMissingNULLParameters(t *testing.T) {
1893	block, _ := pem.Decode([]byte(certMissingRSANULL))
1894	if _, err := ParseCertificate(block.Bytes); err == nil {
1895		t.Error("unexpected success when parsing certificate with missing RSA NULL parameter")
1896	} else if !strings.Contains(err.Error(), "missing NULL") {
1897		t.Errorf("unrecognised error when parsing certificate with missing RSA NULL parameter: %s", err)
1898	}
1899}
1900
1901const certISOOID = `
1902-----BEGIN CERTIFICATE-----
1903MIIB5TCCAVKgAwIBAgIQtwyL3RPWV7dJQp34HwZG9DAJBgUrDgMCHQUAMBExDzAN
1904BgNVBAMTBm15dGVzdDAeFw0xNjA4MDkyMjExMDVaFw0zOTEyMzEyMzU5NTlaMBEx
1905DzANBgNVBAMTBm15dGVzdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArzIH
1906GsyDB3ohIGkkvijF2PTRUX1bvOtY1eUUpjwHyu0twpAKSuaQv2Ha+/63+aHe8O86
1907BT+98wjXFX6RFSagtAujo80rIF2dSm33BGt18pDN8v6zp93dnAm0jRaSQrHJ75xw
19085O+S1oEYR1LtUoFJy6qB104j6aINBAgOiLIKiMkCAwEAAaNGMEQwQgYDVR0BBDsw
1909OYAQVuYVQ/WDjdGSkZRlTtJDNKETMBExDzANBgNVBAMTBm15dGVzdIIQtwyL3RPW
1910V7dJQp34HwZG9DAJBgUrDgMCHQUAA4GBABngrSkH7vG5lY4sa4AZF59lAAXqBVJE
1911J4TBiKC62hCdZv18rBleP6ETfhbPg7pTs8p4ebQbpmtNxRS9Lw3MzQ8Ya5Ybwzj2
1912NwBSyCtCQl7mrEg4nJqJl4A2EUhnET/oVxU0oTV/SZ3ziGXcY1oG1s6vidV7TZTu
1913MCRtdSdaM7g3
1914-----END CERTIFICATE-----`
1915
1916func TestISOOIDInCertificate(t *testing.T) {
1917	block, _ := pem.Decode([]byte(certISOOID))
1918	if cert, err := ParseCertificate(block.Bytes); err != nil {
1919		t.Errorf("certificate with ISO OID failed to parse: %s", err)
1920	} else if cert.SignatureAlgorithm == UnknownSignatureAlgorithm {
1921		t.Errorf("ISO OID not recognised in certificate")
1922	}
1923}
1924
1925// certMultipleRDN contains a RelativeDistinguishedName with two elements (the
1926// common name and serial number). This particular certificate was the first
1927// such certificate in the “Pilot” Certificate Transparency log.
1928const certMultipleRDN = `
1929-----BEGIN CERTIFICATE-----
1930MIIFRzCCBC+gAwIBAgIEOl59NTANBgkqhkiG9w0BAQUFADA9MQswCQYDVQQGEwJz
1931aTEbMBkGA1UEChMSc3RhdGUtaW5zdGl0dXRpb25zMREwDwYDVQQLEwhzaWdvdi1j
1932YTAeFw0xMjExMTYxMDUyNTdaFw0xNzExMTYxMjQ5MDVaMIGLMQswCQYDVQQGEwJz
1933aTEbMBkGA1UEChMSc3RhdGUtaW5zdGl0dXRpb25zMRkwFwYDVQQLExB3ZWItY2Vy
1934dGlmaWNhdGVzMRAwDgYDVQQLEwdTZXJ2ZXJzMTIwFAYDVQQFEw0xMjM2NDg0MDEw
1935MDEwMBoGA1UEAxMTZXBvcnRhbC5tc3MuZWR1cy5zaTCCASIwDQYJKoZIhvcNAQEB
1936BQADggEPADCCAQoCggEBAMrNkZH9MPuBTjMGNk3sJX8V+CkFx/4ru7RTlLS6dlYM
1937098dtSfJ3s2w0p/1NB9UmR8j0yS0Kg6yoZ3ShsSO4DWBtcQD8820a6BYwqxxQTNf
1938HSRZOc+N/4TQrvmK6t4k9Aw+YEYTMrWOU4UTeyhDeCcUsBdh7HjfWsVaqNky+2sv
1939oic3zP5gF+2QfPkvOoHT3FLR8olNhViIE6Kk3eFIEs4dkq/ZzlYdLb8pHQoj/sGI
1940zFmA5AFvm1HURqOmJriFjBwaCtn8AVEYOtQrnUCzJYu1ex8azyS2ZgYMX0u8A5Z/
1941y2aMS/B2W+H79WcgLpK28vPwe7vam0oFrVytAd+u65ECAwEAAaOCAf4wggH6MA4G
1942A1UdDwEB/wQEAwIFoDBABgNVHSAEOTA3MDUGCisGAQQBr1kBAwMwJzAlBggrBgEF
1943BQcCARYZaHR0cDovL3d3dy5jYS5nb3Yuc2kvY3BzLzAfBgNVHREEGDAWgRRwb2Rw
1944b3JhLm1pemtzQGdvdi5zaTCB8QYDVR0fBIHpMIHmMFWgU6BRpE8wTTELMAkGA1UE
1945BhMCc2kxGzAZBgNVBAoTEnN0YXRlLWluc3RpdHV0aW9uczERMA8GA1UECxMIc2ln
1946b3YtY2ExDjAMBgNVBAMTBUNSTDM5MIGMoIGJoIGGhldsZGFwOi8veDUwMC5nb3Yu
1947c2kvb3U9c2lnb3YtY2Esbz1zdGF0ZS1pbnN0aXR1dGlvbnMsYz1zaT9jZXJ0aWZp
1948Y2F0ZVJldm9jYXRpb25MaXN0P2Jhc2WGK2h0dHA6Ly93d3cuc2lnb3YtY2EuZ292
1949LnNpL2NybC9zaWdvdi1jYS5jcmwwKwYDVR0QBCQwIoAPMjAxMjExMTYxMDUyNTda
1950gQ8yMDE3MTExNjEyNDkwNVowHwYDVR0jBBgwFoAUHvjUU2uzgwbpBAZXAvmlv8ZY
1951PHIwHQYDVR0OBBYEFGI1Duuu+wTGDZka/xHNbwcbM69ZMAkGA1UdEwQCMAAwGQYJ
1952KoZIhvZ9B0EABAwwChsEVjcuMQMCA6gwDQYJKoZIhvcNAQEFBQADggEBAHny0K1y
1953BQznrzDu3DDpBcGYguKU0dvU9rqsV1ua4nxkriSMWjgsX6XJFDdDW60I3P4VWab5
1954ag5fZzbGqi8kva/CzGgZh+CES0aWCPy+4Gb8lwOTt+854/laaJvd6kgKTER7z7U9
19559C86Ch2y4sXNwwwPJ1A9dmrZJZOcJjS/WYZgwaafY2Hdxub5jqPE5nehwYUPVu9R
1956uH6/skk4OEKcfOtN0hCnISOVuKYyS4ANARWRG5VGHIH06z3lGUVARFRJ61gtAprd
1957La+fgSS+LVZ+kU2TkeoWAKvGq8MAgDq4D4Xqwekg7WKFeuyusi/NI5rm40XgjBMF
1958DF72IUofoVt7wo0=
1959-----END CERTIFICATE-----`
1960
1961func TestMultipleRDN(t *testing.T) {
1962	block, _ := pem.Decode([]byte(certMultipleRDN))
1963	cert, err := ParseCertificate(block.Bytes)
1964	if err != nil {
1965		t.Fatalf("certificate with two elements in an RDN failed to parse: %v", err)
1966	}
1967
1968	if want := "eportal.mss.edus.si"; cert.Subject.CommonName != want {
1969		t.Errorf("got common name of %q, but want %q", cert.Subject.CommonName, want)
1970	}
1971
1972	if want := "1236484010010"; cert.Subject.SerialNumber != want {
1973		t.Errorf("got serial number of %q, but want %q", cert.Subject.SerialNumber, want)
1974	}
1975}
1976
1977func TestSystemCertPool(t *testing.T) {
1978	if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
1979		t.Skip("not implemented on Windows (Issue 16736, 18609) or darwin (Issue 46287)")
1980	}
1981	a, err := SystemCertPool()
1982	if err != nil {
1983		t.Fatal(err)
1984	}
1985	b, err := SystemCertPool()
1986	if err != nil {
1987		t.Fatal(err)
1988	}
1989	if !certPoolEqual(a, b) {
1990		t.Fatal("two calls to SystemCertPool had different results")
1991	}
1992	if ok := b.AppendCertsFromPEM([]byte(`
1993-----BEGIN CERTIFICATE-----
1994MIIDBjCCAe6gAwIBAgIRANXM5I3gjuqDfTp/PYrs+u8wDQYJKoZIhvcNAQELBQAw
1995EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xODAzMjcxOTU2MjFaFw0xOTAzMjcxOTU2
1996MjFaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
1997ggEKAoIBAQDK+9m3rjsO2Djes6bIYQZ3eV29JF09ZrjOrEHLtaKrD6/acsoSoTsf
1998cQr+rzzztdB5ijWXCS64zo/0OiqBeZUNZ67jVdToa9qW5UYe2H0Y+ZNdfA5GYMFD
1999yk/l3/uBu3suTZPfXiW2TjEi27Q8ruNUIZ54DpTcs6y2rBRFzadPWwn/VQMlvRXM
2000jrzl8Y08dgnYmaAHprxVzwMXcQ/Brol+v9GvjaH1DooHqkn8O178wsPQNhdtvN01
2001IXL46cYdcUwWrE/GX5u+9DaSi+0KWxAPQ+NVD5qUI0CKl4714yGGh7feXMjJdHgl
2002VG4QJZlJvC4FsURgCHJT6uHGIelnSwhbAgMBAAGjVzBVMA4GA1UdDwEB/wQEAwIF
2003oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMCAGA1UdEQQZMBeC
2004FVRlc3RTeXN0ZW1DZXJ0UG9vbC5nbzANBgkqhkiG9w0BAQsFAAOCAQEAwuSRx/VR
2005BKh2ICxZjL6jBwk/7UlU1XKbhQD96RqkidDNGEc6eLZ90Z5XXTurEsXqdm5jQYPs
20061cdcSW+fOSMl7MfW9e5tM66FaIPZl9rKZ1r7GkOfgn93xdLAWe8XHd19xRfDreub
2007YC8DVqgLASOEYFupVSl76ktPfxkU5KCvmUf3P2PrRybk1qLGFytGxfyice2gHSNI
2008gify3K/+H/7wCkyFW4xYvzl7WW4mXxoqPRPjQt1J423DhnnQ4G1P8V/vhUpXNXOq
2009N9IEPnWuihC09cyx/WMQIUlWnaQLHdfpPS04Iez3yy2PdfXJzwfPrja7rNE+skK6
2010pa/O1nF0AfWOpw==
2011-----END CERTIFICATE-----
2012	`)); !ok {
2013		t.Fatal("AppendCertsFromPEM failed")
2014	}
2015	if reflect.DeepEqual(a, b) {
2016		t.Fatal("changing one pool modified the other")
2017	}
2018}
2019
2020const emptyNameConstraintsPEM = `
2021-----BEGIN CERTIFICATE-----
2022MIIC1jCCAb6gAwIBAgICEjQwDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAxMdRW1w
2023dHkgbmFtZSBjb25zdHJhaW50cyBpc3N1ZXIwHhcNMTMwMjAxMDAwMDAwWhcNMjAw
2024NTMwMTA0ODM4WjAhMR8wHQYDVQQDExZFbXB0eSBuYW1lIGNvbnN0cmFpbnRzMIIB
2025IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwriElUIt3LCqmJObs+yDoWPD
2026F5IqgWk6moIobYjPfextZiYU6I3EfvAwoNxPDkN2WowcocUZMJbEeEq5ebBksFnx
2027f12gBxlIViIYwZAzu7aFvhDMyPKQI3C8CG0ZSC9ABZ1E3umdA3CEueNOmP/TChNq
2028Cl23+BG1Qb/PJkpAO+GfpWSVhTcV53Mf/cKvFHcjGNrxzdSoq9fyW7a6gfcGEQY0
2029LVkmwFWUfJ0wT8kaeLr0E0tozkIfo01KNWNzv6NcYP80QOBRDlApWu9ODmEVJHPD
2030blx4jzTQ3JLa+4DvBNOjVUOp+mgRmjiW0rLdrxwOxIqIOwNjweMCp/hgxX/hTQID
2031AQABoxEwDzANBgNVHR4EBjAEoAChADANBgkqhkiG9w0BAQsFAAOCAQEAWG+/zUMH
2032QhP8uNCtgSHyim/vh7wminwAvWgMKxlkLBFns6nZeQqsOV1lABY7U0Zuoqa1Z5nb
20336L+iJa4ElREJOi/erLc9uLwBdDCAR0hUTKD7a6i4ooS39DTle87cUnj0MW1CUa6H
2034v5SsvpYW+1XleYJk/axQOOTcy4Es53dvnZsjXH0EA/QHnn7UV+JmlE3rtVxcYp6M
2035LYPmRhTioROA/drghicRkiu9hxdPyxkYS16M5g3Zj30jdm+k/6C6PeNtN9YmOOga
2036nCOSyFYfGhqOANYzpmuV+oIedAsPpIbfIzN8njYUs1zio+1IoI4o8ddM9sCbtPU8
2037o+WoY6IsCKXV/g==
2038-----END CERTIFICATE-----`
2039
2040func TestEmptyNameConstraints(t *testing.T) {
2041	block, _ := pem.Decode([]byte(emptyNameConstraintsPEM))
2042	_, err := ParseCertificate(block.Bytes)
2043	if err == nil {
2044		t.Fatal("unexpected success")
2045	}
2046
2047	const expected = "empty name constraints"
2048	if str := err.Error(); !strings.Contains(str, expected) {
2049		t.Errorf("expected %q in error but got %q", expected, str)
2050	}
2051}
2052
2053func TestPKIXNameString(t *testing.T) {
2054	der, err := base64.StdEncoding.DecodeString(certBytes)
2055	if err != nil {
2056		t.Fatal(err)
2057	}
2058	certs, err := ParseCertificates(der)
2059	if err != nil {
2060		t.Fatal(err)
2061	}
2062
2063	// Check that parsed non-standard attributes are printed.
2064	rdns := pkix.Name{
2065		Locality: []string{"Gophertown"},
2066		ExtraNames: []pkix.AttributeTypeAndValue{
2067			{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}},
2068	}.ToRDNSequence()
2069	nn := pkix.Name{}
2070	nn.FillFromRDNSequence(&rdns)
2071
2072	// Check that zero-length non-nil ExtraNames hide Names.
2073	extra := []pkix.AttributeTypeAndValue{
2074		{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "backing array"}}
2075	extraNotNil := pkix.Name{
2076		Locality:   []string{"Gophertown"},
2077		ExtraNames: extra[:0],
2078		Names: []pkix.AttributeTypeAndValue{
2079			{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}},
2080	}
2081
2082	tests := []struct {
2083		dn   pkix.Name
2084		want string
2085	}{
2086		{nn, "L=Gophertown,1.2.3.4.5=#130a676f6c616e672e6f7267"},
2087		{extraNotNil, "L=Gophertown"},
2088		{pkix.Name{
2089			CommonName:         "Steve Kille",
2090			Organization:       []string{"Isode Limited"},
2091			OrganizationalUnit: []string{"RFCs"},
2092			Locality:           []string{"Richmond"},
2093			Province:           []string{"Surrey"},
2094			StreetAddress:      []string{"The Square"},
2095			PostalCode:         []string{"TW9 1DT"},
2096			SerialNumber:       "RFC 2253",
2097			Country:            []string{"GB"},
2098		}, "SERIALNUMBER=RFC 2253,CN=Steve Kille,OU=RFCs,O=Isode Limited,POSTALCODE=TW9 1DT,STREET=The Square,L=Richmond,ST=Surrey,C=GB"},
2099		{certs[0].Subject,
2100			"CN=mail.google.com,O=Google LLC,L=Mountain View,ST=California,C=US"},
2101		{pkix.Name{
2102			Organization: []string{"#Google, Inc. \n-> 'Alphabet\" "},
2103			Country:      []string{"US"},
2104		}, "O=\\#Google\\, Inc. \n-\\> 'Alphabet\\\"\\ ,C=US"},
2105		{pkix.Name{
2106			CommonName:   "foo.com",
2107			Organization: []string{"Gopher Industries"},
2108			ExtraNames: []pkix.AttributeTypeAndValue{
2109				{Type: asn1.ObjectIdentifier([]int{2, 5, 4, 3}), Value: "bar.com"}},
2110		}, "CN=bar.com,O=Gopher Industries"},
2111		{pkix.Name{
2112			Locality: []string{"Gophertown"},
2113			ExtraNames: []pkix.AttributeTypeAndValue{
2114				{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}},
2115		}, "1.2.3.4.5=#130a676f6c616e672e6f7267,L=Gophertown"},
2116		// If there are no ExtraNames, the Names are printed instead.
2117		{pkix.Name{
2118			Locality: []string{"Gophertown"},
2119			Names: []pkix.AttributeTypeAndValue{
2120				{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}},
2121		}, "L=Gophertown,1.2.3.4.5=#130a676f6c616e672e6f7267"},
2122		// If there are both, print only the ExtraNames.
2123		{pkix.Name{
2124			Locality: []string{"Gophertown"},
2125			ExtraNames: []pkix.AttributeTypeAndValue{
2126				{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}},
2127			Names: []pkix.AttributeTypeAndValue{
2128				{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 6}), Value: "example.com"}},
2129		}, "1.2.3.4.5=#130a676f6c616e672e6f7267,L=Gophertown"},
2130	}
2131
2132	for i, test := range tests {
2133		if got := test.dn.String(); got != test.want {
2134			t.Errorf("#%d: String() = \n%s\n, want \n%s", i, got, test.want)
2135		}
2136	}
2137
2138	if extra[0].Value != "backing array" {
2139		t.Errorf("the backing array of an empty ExtraNames got modified by String")
2140	}
2141}
2142
2143func TestRDNSequenceString(t *testing.T) {
2144	// Test some extra cases that get lost in pkix.Name conversions such as
2145	// multi-valued attributes.
2146
2147	var (
2148		oidCountry            = []int{2, 5, 4, 6}
2149		oidOrganization       = []int{2, 5, 4, 10}
2150		oidOrganizationalUnit = []int{2, 5, 4, 11}
2151		oidCommonName         = []int{2, 5, 4, 3}
2152	)
2153
2154	tests := []struct {
2155		seq  pkix.RDNSequence
2156		want string
2157	}{
2158		{
2159			seq: pkix.RDNSequence{
2160				pkix.RelativeDistinguishedNameSET{
2161					pkix.AttributeTypeAndValue{Type: oidCountry, Value: "US"},
2162				},
2163				pkix.RelativeDistinguishedNameSET{
2164					pkix.AttributeTypeAndValue{Type: oidOrganization, Value: "Widget Inc."},
2165				},
2166				pkix.RelativeDistinguishedNameSET{
2167					pkix.AttributeTypeAndValue{Type: oidOrganizationalUnit, Value: "Sales"},
2168					pkix.AttributeTypeAndValue{Type: oidCommonName, Value: "J. Smith"},
2169				},
2170			},
2171			want: "OU=Sales+CN=J. Smith,O=Widget Inc.,C=US",
2172		},
2173	}
2174
2175	for i, test := range tests {
2176		if got := test.seq.String(); got != test.want {
2177			t.Errorf("#%d: String() = \n%s\n, want \n%s", i, got, test.want)
2178		}
2179	}
2180}
2181
2182const criticalNameConstraintWithUnknownTypePEM = `
2183-----BEGIN CERTIFICATE-----
2184MIIC/TCCAeWgAwIBAgICEjQwDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAxMdRW1w
2185dHkgbmFtZSBjb25zdHJhaW50cyBpc3N1ZXIwHhcNMTMwMjAxMDAwMDAwWhcNMjAw
2186NTMwMTA0ODM4WjAhMR8wHQYDVQQDExZFbXB0eSBuYW1lIGNvbnN0cmFpbnRzMIIB
2187IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwriElUIt3LCqmJObs+yDoWPD
2188F5IqgWk6moIobYjPfextZiYU6I3EfvAwoNxPDkN2WowcocUZMJbEeEq5ebBksFnx
2189f12gBxlIViIYwZAzu7aFvhDMyPKQI3C8CG0ZSC9ABZ1E3umdA3CEueNOmP/TChNq
2190Cl23+BG1Qb/PJkpAO+GfpWSVhTcV53Mf/cKvFHcjGNrxzdSoq9fyW7a6gfcGEQY0
2191LVkmwFWUfJ0wT8kaeLr0E0tozkIfo01KNWNzv6NcYP80QOBRDlApWu9ODmEVJHPD
2192blx4jzTQ3JLa+4DvBNOjVUOp+mgRmjiW0rLdrxwOxIqIOwNjweMCp/hgxX/hTQID
2193AQABozgwNjA0BgNVHR4BAf8EKjAooCQwIokgIACrzQAAAAAAAAAAAAAAAP////8A
2194AAAAAAAAAAAAAAChADANBgkqhkiG9w0BAQsFAAOCAQEAWG+/zUMHQhP8uNCtgSHy
2195im/vh7wminwAvWgMKxlkLBFns6nZeQqsOV1lABY7U0Zuoqa1Z5nb6L+iJa4ElREJ
2196Oi/erLc9uLwBdDCAR0hUTKD7a6i4ooS39DTle87cUnj0MW1CUa6Hv5SsvpYW+1Xl
2197eYJk/axQOOTcy4Es53dvnZsjXH0EA/QHnn7UV+JmlE3rtVxcYp6MLYPmRhTioROA
2198/drghicRkiu9hxdPyxkYS16M5g3Zj30jdm+k/6C6PeNtN9YmOOganCOSyFYfGhqO
2199ANYzpmuV+oIedAsPpIbfIzN8njYUs1zio+1IoI4o8ddM9sCbtPU8o+WoY6IsCKXV
2200/g==
2201-----END CERTIFICATE-----`
2202
2203func TestCriticalNameConstraintWithUnknownType(t *testing.T) {
2204	block, _ := pem.Decode([]byte(criticalNameConstraintWithUnknownTypePEM))
2205	cert, err := ParseCertificate(block.Bytes)
2206	if err != nil {
2207		t.Fatalf("unexpected parsing failure: %s", err)
2208	}
2209
2210	if l := len(cert.UnhandledCriticalExtensions); l != 1 {
2211		t.Fatalf("expected one unhandled critical extension, but found %d", l)
2212	}
2213}
2214
2215const badIPMaskPEM = `
2216-----BEGIN CERTIFICATE-----
2217MIICzzCCAbegAwIBAgICEjQwDQYJKoZIhvcNAQELBQAwHTEbMBkGA1UEAxMSQmFk
2218IElQIG1hc2sgaXNzdWVyMB4XDTEzMDIwMTAwMDAwMFoXDTIwMDUzMDEwNDgzOFow
2219FjEUMBIGA1UEAxMLQmFkIElQIG1hc2swggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
2220ggEKAoIBAQDCuISVQi3csKqYk5uz7IOhY8MXkiqBaTqagihtiM997G1mJhTojcR+
22218DCg3E8OQ3ZajByhxRkwlsR4Srl5sGSwWfF/XaAHGUhWIhjBkDO7toW+EMzI8pAj
2222cLwIbRlIL0AFnUTe6Z0DcIS5406Y/9MKE2oKXbf4EbVBv88mSkA74Z+lZJWFNxXn
2223cx/9wq8UdyMY2vHN1Kir1/JbtrqB9wYRBjQtWSbAVZR8nTBPyRp4uvQTS2jOQh+j
2224TUo1Y3O/o1xg/zRA4FEOUCla704OYRUkc8NuXHiPNNDcktr7gO8E06NVQ6n6aBGa
2225OJbSst2vHA7Eiog7A2PB4wKn+GDFf+FNAgMBAAGjIDAeMBwGA1UdHgEB/wQSMBCg
2226DDAKhwgBAgME//8BAKEAMA0GCSqGSIb3DQEBCwUAA4IBAQBYb7/NQwdCE/y40K2B
2227IfKKb++HvCaKfAC9aAwrGWQsEWezqdl5Cqw5XWUAFjtTRm6iprVnmdvov6IlrgSV
2228EQk6L96stz24vAF0MIBHSFRMoPtrqLiihLf0NOV7ztxSePQxbUJRroe/lKy+lhb7
2229VeV5gmT9rFA45NzLgSznd2+dmyNcfQQD9AeeftRX4maUTeu1XFxinowtg+ZGFOKh
2230E4D92uCGJxGSK72HF0/LGRhLXozmDdmPfSN2b6T/oLo942031iY46BqcI5LIVh8a
2231Go4A1jOma5X6gh50Cw+kht8jM3yeNhSzXOKj7Uigjijx10z2wJu09Tyj5ahjoiwI
2232pdX+
2233-----END CERTIFICATE-----`
2234
2235func TestBadIPMask(t *testing.T) {
2236	block, _ := pem.Decode([]byte(badIPMaskPEM))
2237	_, err := ParseCertificate(block.Bytes)
2238	if err == nil {
2239		t.Fatalf("unexpected success")
2240	}
2241
2242	const expected = "contained invalid mask"
2243	if !strings.Contains(err.Error(), expected) {
2244		t.Fatalf("expected %q in error but got: %s", expected, err)
2245	}
2246}
2247
2248const additionalGeneralSubtreePEM = `
2249-----BEGIN CERTIFICATE-----
2250MIIG4TCCBMmgAwIBAgIRALss+4rLw2Ia7tFFhxE8g5cwDQYJKoZIhvcNAQELBQAw
2251bjELMAkGA1UEBhMCTkwxIDAeBgNVBAoMF01pbmlzdGVyaWUgdmFuIERlZmVuc2ll
2252MT0wOwYDVQQDDDRNaW5pc3RlcmllIHZhbiBEZWZlbnNpZSBDZXJ0aWZpY2F0aWUg
2253QXV0b3JpdGVpdCAtIEcyMB4XDTEzMDMwNjEyMDM0OVoXDTEzMTEzMDEyMDM1MFow
2254bDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUNlcnRpUGF0aCBMTEMxIjAgBgNVBAsT
2255GUNlcnRpZmljYXRpb24gQXV0aG9yaXRpZXMxITAfBgNVBAMTGENlcnRpUGF0aCBC
2256cmlkZ2UgQ0EgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANLW
22574kXiRqvwBhJfN9uz12FA+P2D34MPxOt7TGXljm2plJ2CLzvaH8/ymsMdSWdJBS1M
22588FmwvNL1w3A6ZuzksJjPikAu8kY3dcp3mrkk9eCPORDAwGtfsXwZysLiuEaDWpbD
2259dHOaHnI6qWU0N6OI+hNX58EjDpIGC1WQdho1tHOTPc5Hf5/hOpM/29v/wr7kySjs
2260Z+7nsvkm5rNhuJNzPsLsgzVaJ5/BVyOplZy24FKM8Y43MjR4osZm+a2e0zniqw6/
2261rvcjcGYabYaznZfQG1GXoyf2Vea+CCgpgUhlVafgkwEs8izl8rIpvBzXiFAgFQuG
2262Ituoy92PJbDs430fA/cCAwEAAaOCAnowggJ2MEUGCCsGAQUFBwEBBDkwNzA1Bggr
2263BgEFBQcwAoYpaHR0cDovL2NlcnRzLmNhLm1pbmRlZi5ubC9taW5kZWYtY2EtMi5w
2264N2MwHwYDVR0jBBgwFoAUzln9WSPz2M64Rl2HYf2/KD8StmQwDwYDVR0TAQH/BAUw
2265AwEB/zCB6QYDVR0gBIHhMIHeMEgGCmCEEAGHawECBQEwOjA4BggrBgEFBQcCARYs
2266aHR0cDovL2Nwcy5kcC5jYS5taW5kZWYubmwvbWluZGVmLWNhLWRwLWNwcy8wSAYK
2267YIQQAYdrAQIFAjA6MDgGCCsGAQUFBwIBFixodHRwOi8vY3BzLmRwLmNhLm1pbmRl
2268Zi5ubC9taW5kZWYtY2EtZHAtY3BzLzBIBgpghBABh2sBAgUDMDowOAYIKwYBBQUH
2269AgEWLGh0dHA6Ly9jcHMuZHAuY2EubWluZGVmLm5sL21pbmRlZi1jYS1kcC1jcHMv
2270MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmxzLmNhLm1pbmRlZi5ubC9taW5k
2271ZWYtY2EtMi5jcmwwDgYDVR0PAQH/BAQDAgEGMEYGA1UdHgEB/wQ8MDqhODA2pDEw
2272LzELMAkGA1UEBhMCTkwxIDAeBgNVBAoTF01pbmlzdGVyaWUgdmFuIERlZmVuc2ll
2273gQFjMF0GA1UdIQRWMFQwGgYKYIQQAYdrAQIFAQYMKwYBBAGBu1MBAQECMBoGCmCE
2274EAGHawECBQIGDCsGAQQBgbtTAQEBAjAaBgpghBABh2sBAgUDBgwrBgEEAYG7UwEB
2275AQIwHQYDVR0OBBYEFNDCjBM3M3ZKkag84ei3/aKc0d0UMA0GCSqGSIb3DQEBCwUA
2276A4ICAQAQXFn9jF90/DNFf15JhoGtta/0dNInb14PMu3PAjcdrXYCDPpQZOArTUng
22775YT1WuzfmjnXiTsziT3my0r9Mxvz/btKK/lnVOMW4c2q/8sIsIPnnW5ZaRGrsANB
2278dNDZkzMYmeG2Pfgvd0AQSOrpE/TVgWfu/+MMRWwX9y6VbooBR7BLv7zMuVH0WqLn
22796OMFth7fqsThlfMSzkE/RDSaU6n3wXAWT1SIqBITtccRjSUQUFm/q3xrb2cwcZA6
22808vdS4hzNd+ttS905ay31Ks4/1Wrm1bH5RhEfRSH0VSXnc0b+z+RyBbmiwtVZqzxE
2281u3UQg/rAmtLDclLFEzjp8YDTIRYSLwstDbEXO/0ArdGrQm79HQ8i/3ZbP2357myW
2282i15qd6gMJIgGHS4b8Hc7R1K8LQ9Gm1aLKBEWVNGZlPK/cpXThpVmoEyslN2DHCrc
2283fbMbjNZpXlTMa+/b9z7Fa4X8dY8u/ELzZuJXJv5Rmqtg29eopFFYDCl0Nkh1XAjo
2284QejEoHHUvYV8TThHZr6Z6Ib8CECgTehU4QvepkgDXNoNrKRZBG0JhLjkwxh2whZq
2285nvWBfALC2VuNOM6C0rDY+HmhMlVt0XeqnybD9MuQALMit7Z00Cw2CIjNsBI9xBqD
2286xKK9CjUb7gzRUWSpB9jGHsvpEMHOzIFhufvH2Bz1XJw+Cl7khw==
2287-----END CERTIFICATE-----`
2288
2289func TestAdditionFieldsInGeneralSubtree(t *testing.T) {
2290	// Very rarely, certificates can include additional fields in the
2291	// GeneralSubtree structure. This tests that such certificates can be
2292	// parsed.
2293	block, _ := pem.Decode([]byte(additionalGeneralSubtreePEM))
2294	if _, err := ParseCertificate(block.Bytes); err != nil {
2295		t.Fatalf("failed to parse certificate: %s", err)
2296	}
2297}
2298
2299func TestEmptySubject(t *testing.T) {
2300	template := Certificate{
2301		SerialNumber: big.NewInt(1),
2302		DNSNames:     []string{"example.com"},
2303	}
2304
2305	derBytes, err := CreateCertificate(rand.Reader, &template, &template, &testPrivateKey.PublicKey, testPrivateKey)
2306	if err != nil {
2307		t.Fatalf("failed to create certificate: %s", err)
2308	}
2309
2310	cert, err := ParseCertificate(derBytes)
2311	if err != nil {
2312		t.Fatalf("failed to parse certificate: %s", err)
2313	}
2314
2315	for _, ext := range cert.Extensions {
2316		if ext.Id.Equal(oidExtensionSubjectAltName) {
2317			if !ext.Critical {
2318				t.Fatal("SAN extension is not critical")
2319			}
2320			return
2321		}
2322	}
2323
2324	t.Fatal("SAN extension is missing")
2325}
2326
2327// multipleURLsInCRLDPPEM contains two URLs in a single CRL DistributionPoint
2328// structure. It is taken from https://crt.sh/?id=12721534.
2329const multipleURLsInCRLDPPEM = `
2330-----BEGIN CERTIFICATE-----
2331MIIF4TCCBMmgAwIBAgIQc+6uFePfrahUGpXs8lhiTzANBgkqhkiG9w0BAQsFADCB
23328zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy
2333dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1
2334YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3
2335dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh
2336IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD
2337LUFDQzAeFw0xNDA5MTgwODIxMDBaFw0zMDA5MTgwODIxMDBaMIGGMQswCQYDVQQG
2338EwJFUzEzMDEGA1UECgwqQ09OU09SQ0kgQURNSU5JU1RSQUNJTyBPQkVSVEEgREUg
2339Q0FUQUxVTllBMSowKAYDVQQLDCFTZXJ2ZWlzIFDDumJsaWNzIGRlIENlcnRpZmlj
2340YWNpw7MxFjAUBgNVBAMMDUVDLUNpdXRhZGFuaWEwggEiMA0GCSqGSIb3DQEBAQUA
2341A4IBDwAwggEKAoIBAQDFkHPRZPZlXTWZ5psJhbS/Gx+bxcTpGrlVQHHtIkgGz77y
2342TA7UZUFb2EQMncfbOhR0OkvQQn1aMvhObFJSR6nI+caf2D+h/m/InMl1MyH3S0Ak
2343YGZZsthnyC6KxqK2A/NApncrOreh70ULkQs45aOKsi1kR1W0zE+iFN+/P19P7AkL
2344Rl3bXBCVd8w+DLhcwRrkf1FCDw6cEqaFm3cGgf5cbBDMaVYAweWTxwBZAq2RbQAW
2345jE7mledcYghcZa4U6bUmCBPuLOnO8KMFAvH+aRzaf3ws5/ZoOVmryyLLJVZ54peZ
2346OwnP9EL4OuWzmXCjBifXR2IAblxs5JYj57tls45nAgMBAAGjggHaMIIB1jASBgNV
2347HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUC2hZPofI
2348oxUa4ECCIl+fHbLFNxUwHwYDVR0jBBgwFoAUoMOLRKo3pUW/l4Ba0fF4opvpXY0w
2349gdYGA1UdIASBzjCByzCByAYEVR0gADCBvzAxBggrBgEFBQcCARYlaHR0cHM6Ly93
2350d3cuYW9jLmNhdC9DQVRDZXJ0L1JlZ3VsYWNpbzCBiQYIKwYBBQUHAgIwfQx7QXF1
2351ZXN0IGNlcnRpZmljYXQgw6lzIGVtw6hzIMO6bmljYSBpIGV4Y2x1c2l2YW1lbnQg
2352YSBFbnRpdGF0cyBkZSBDZXJ0aWZpY2FjacOzLiBWZWdldSBodHRwczovL3d3dy5h
2353b2MuY2F0L0NBVENlcnQvUmVndWxhY2lvMDMGCCsGAQUFBwEBBCcwJTAjBggrBgEF
2354BQcwAYYXaHR0cDovL29jc3AuY2F0Y2VydC5jYXQwYgYDVR0fBFswWTBXoFWgU4Yn
2355aHR0cDovL2Vwc2NkLmNhdGNlcnQubmV0L2NybC9lYy1hY2MuY3JshihodHRwOi8v
2356ZXBzY2QyLmNhdGNlcnQubmV0L2NybC9lYy1hY2MuY3JsMA0GCSqGSIb3DQEBCwUA
2357A4IBAQChqFTjlAH5PyIhLjLgEs68CyNNC1+vDuZXRhy22TI83JcvGmQrZosPvVIL
2358PsUXx+C06Pfqmh48Q9S89X9K8w1SdJxP/rZeGEoRiKpwvQzM4ArD9QxyC8jirxex
23593Umg9Ai/sXQ+1lBf6xw4HfUUr1WIp7pNHj0ZWLo106urqktcdeAFWme+/klis5fu
2360labCSVPuT/QpwakPrtqOhRms8vgpKiXa/eLtL9ZiA28X/Mker0zlAeTA7Z7uAnp6
2361oPJTlZu1Gg1ZDJueTWWsLlO+P+Wzm3MRRIbcgdRzm4mdO7ubu26SzX/aQXDhuih+
2362eVxXDTCfs7GUlxnjOp5j559X/N0A
2363-----END CERTIFICATE-----
2364`
2365
2366func TestMultipleURLsInCRLDP(t *testing.T) {
2367	block, _ := pem.Decode([]byte(multipleURLsInCRLDPPEM))
2368	cert, err := ParseCertificate(block.Bytes)
2369	if err != nil {
2370		t.Fatalf("failed to parse certificate: %s", err)
2371	}
2372
2373	want := []string{
2374		"http://epscd.catcert.net/crl/ec-acc.crl",
2375		"http://epscd2.catcert.net/crl/ec-acc.crl",
2376	}
2377	if got := cert.CRLDistributionPoints; !reflect.DeepEqual(got, want) {
2378		t.Errorf("CRL distribution points = %#v, want #%v", got, want)
2379	}
2380}
2381
2382const hexPKCS1TestPKCS8Key = "30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031"
2383const hexPKCS1TestECKey = "3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50"
2384
2385var pkcs1MismatchKeyTests = []struct {
2386	hexKey        string
2387	errorContains string
2388}{
2389	{hexKey: hexPKCS1TestPKCS8Key, errorContains: "use ParsePKCS8PrivateKey instead"},
2390	{hexKey: hexPKCS1TestECKey, errorContains: "use ParseECPrivateKey instead"},
2391}
2392
2393func TestPKCS1MismatchKeyFormat(t *testing.T) {
2394	for i, test := range pkcs1MismatchKeyTests {
2395		derBytes, _ := hex.DecodeString(test.hexKey)
2396		_, err := ParsePKCS1PrivateKey(derBytes)
2397		if !strings.Contains(err.Error(), test.errorContains) {
2398			t.Errorf("#%d: expected error containing %q, got %s", i, test.errorContains, err)
2399		}
2400	}
2401}
2402
2403func TestCreateRevocationList(t *testing.T) {
2404	ec256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
2405	if err != nil {
2406		t.Fatalf("Failed to generate ECDSA P256 key: %s", err)
2407	}
2408	_, ed25519Priv, err := ed25519.GenerateKey(rand.Reader)
2409	if err != nil {
2410		t.Fatalf("Failed to generate Ed25519 key: %s", err)
2411	}
2412	tests := []struct {
2413		name          string
2414		key           crypto.Signer
2415		issuer        *Certificate
2416		template      *RevocationList
2417		expectedError string
2418	}{
2419		{
2420			name:          "nil template",
2421			key:           ec256Priv,
2422			issuer:        nil,
2423			template:      nil,
2424			expectedError: "x509: template can not be nil",
2425		},
2426		{
2427			name:          "nil issuer",
2428			key:           ec256Priv,
2429			issuer:        nil,
2430			template:      &RevocationList{},
2431			expectedError: "x509: issuer can not be nil",
2432		},
2433		{
2434			name: "issuer doesn't have crlSign key usage bit set",
2435			key:  ec256Priv,
2436			issuer: &Certificate{
2437				KeyUsage: KeyUsageCertSign,
2438			},
2439			template:      &RevocationList{},
2440			expectedError: "x509: issuer must have the crlSign key usage bit set",
2441		},
2442		{
2443			name: "issuer missing SubjectKeyId",
2444			key:  ec256Priv,
2445			issuer: &Certificate{
2446				KeyUsage: KeyUsageCRLSign,
2447			},
2448			template:      &RevocationList{},
2449			expectedError: "x509: issuer certificate doesn't contain a subject key identifier",
2450		},
2451		{
2452			name: "nextUpdate before thisUpdate",
2453			key:  ec256Priv,
2454			issuer: &Certificate{
2455				KeyUsage: KeyUsageCRLSign,
2456				Subject: pkix.Name{
2457					CommonName: "testing",
2458				},
2459				SubjectKeyId: []byte{1, 2, 3},
2460			},
2461			template: &RevocationList{
2462				ThisUpdate: time.Time{}.Add(time.Hour),
2463				NextUpdate: time.Time{},
2464			},
2465			expectedError: "x509: template.ThisUpdate is after template.NextUpdate",
2466		},
2467		{
2468			name: "nil Number",
2469			key:  ec256Priv,
2470			issuer: &Certificate{
2471				KeyUsage: KeyUsageCRLSign,
2472				Subject: pkix.Name{
2473					CommonName: "testing",
2474				},
2475				SubjectKeyId: []byte{1, 2, 3},
2476			},
2477			template: &RevocationList{
2478				ThisUpdate: time.Time{}.Add(time.Hour * 24),
2479				NextUpdate: time.Time{}.Add(time.Hour * 48),
2480			},
2481			expectedError: "x509: template contains nil Number field",
2482		},
2483		{
2484			name: "invalid signature algorithm",
2485			key:  ec256Priv,
2486			issuer: &Certificate{
2487				KeyUsage: KeyUsageCRLSign,
2488				Subject: pkix.Name{
2489					CommonName: "testing",
2490				},
2491				SubjectKeyId: []byte{1, 2, 3},
2492			},
2493			template: &RevocationList{
2494				SignatureAlgorithm: SHA256WithRSA,
2495				RevokedCertificates: []pkix.RevokedCertificate{
2496					{
2497						SerialNumber:   big.NewInt(2),
2498						RevocationTime: time.Time{}.Add(time.Hour),
2499					},
2500				},
2501				Number:     big.NewInt(5),
2502				ThisUpdate: time.Time{}.Add(time.Hour * 24),
2503				NextUpdate: time.Time{}.Add(time.Hour * 48),
2504			},
2505			expectedError: "x509: requested SignatureAlgorithm does not match private key type",
2506		},
2507		{
2508			name: "valid",
2509			key:  ec256Priv,
2510			issuer: &Certificate{
2511				KeyUsage: KeyUsageCRLSign,
2512				Subject: pkix.Name{
2513					CommonName: "testing",
2514				},
2515				SubjectKeyId: []byte{1, 2, 3},
2516			},
2517			template: &RevocationList{
2518				RevokedCertificates: []pkix.RevokedCertificate{
2519					{
2520						SerialNumber:   big.NewInt(2),
2521						RevocationTime: time.Time{}.Add(time.Hour),
2522					},
2523				},
2524				Number:     big.NewInt(5),
2525				ThisUpdate: time.Time{}.Add(time.Hour * 24),
2526				NextUpdate: time.Time{}.Add(time.Hour * 48),
2527			},
2528		},
2529		{
2530			name: "valid, Ed25519 key",
2531			key:  ed25519Priv,
2532			issuer: &Certificate{
2533				KeyUsage: KeyUsageCRLSign,
2534				Subject: pkix.Name{
2535					CommonName: "testing",
2536				},
2537				SubjectKeyId: []byte{1, 2, 3},
2538			},
2539			template: &RevocationList{
2540				RevokedCertificates: []pkix.RevokedCertificate{
2541					{
2542						SerialNumber:   big.NewInt(2),
2543						RevocationTime: time.Time{}.Add(time.Hour),
2544					},
2545				},
2546				Number:     big.NewInt(5),
2547				ThisUpdate: time.Time{}.Add(time.Hour * 24),
2548				NextUpdate: time.Time{}.Add(time.Hour * 48),
2549			},
2550		},
2551		{
2552			name: "valid, non-default signature algorithm",
2553			key:  ec256Priv,
2554			issuer: &Certificate{
2555				KeyUsage: KeyUsageCRLSign,
2556				Subject: pkix.Name{
2557					CommonName: "testing",
2558				},
2559				SubjectKeyId: []byte{1, 2, 3},
2560			},
2561			template: &RevocationList{
2562				SignatureAlgorithm: ECDSAWithSHA512,
2563				RevokedCertificates: []pkix.RevokedCertificate{
2564					{
2565						SerialNumber:   big.NewInt(2),
2566						RevocationTime: time.Time{}.Add(time.Hour),
2567					},
2568				},
2569				Number:     big.NewInt(5),
2570				ThisUpdate: time.Time{}.Add(time.Hour * 24),
2571				NextUpdate: time.Time{}.Add(time.Hour * 48),
2572			},
2573		},
2574		{
2575			name: "valid, extra extension",
2576			key:  ec256Priv,
2577			issuer: &Certificate{
2578				KeyUsage: KeyUsageCRLSign,
2579				Subject: pkix.Name{
2580					CommonName: "testing",
2581				},
2582				SubjectKeyId: []byte{1, 2, 3},
2583			},
2584			template: &RevocationList{
2585				RevokedCertificates: []pkix.RevokedCertificate{
2586					{
2587						SerialNumber:   big.NewInt(2),
2588						RevocationTime: time.Time{}.Add(time.Hour),
2589					},
2590				},
2591				Number:     big.NewInt(5),
2592				ThisUpdate: time.Time{}.Add(time.Hour * 24),
2593				NextUpdate: time.Time{}.Add(time.Hour * 48),
2594				ExtraExtensions: []pkix.Extension{
2595					{
2596						Id:    []int{2, 5, 29, 99},
2597						Value: []byte{5, 0},
2598					},
2599				},
2600			},
2601		},
2602		{
2603			name: "valid, empty list",
2604			key:  ec256Priv,
2605			issuer: &Certificate{
2606				KeyUsage: KeyUsageCRLSign,
2607				Subject: pkix.Name{
2608					CommonName: "testing",
2609				},
2610				SubjectKeyId: []byte{1, 2, 3},
2611			},
2612			template: &RevocationList{
2613				Number:     big.NewInt(5),
2614				ThisUpdate: time.Time{}.Add(time.Hour * 24),
2615				NextUpdate: time.Time{}.Add(time.Hour * 48),
2616			},
2617		},
2618	}
2619
2620	for _, tc := range tests {
2621		t.Run(tc.name, func(t *testing.T) {
2622			crl, err := CreateRevocationList(rand.Reader, tc.template, tc.issuer, tc.key)
2623			if err != nil && tc.expectedError == "" {
2624				t.Fatalf("CreateRevocationList failed unexpectedly: %s", err)
2625			} else if err != nil && tc.expectedError != err.Error() {
2626				t.Fatalf("CreateRevocationList failed unexpectedly, wanted: %s, got: %s", tc.expectedError, err)
2627			} else if err == nil && tc.expectedError != "" {
2628				t.Fatalf("CreateRevocationList didn't fail, expected: %s", tc.expectedError)
2629			}
2630			if tc.expectedError != "" {
2631				return
2632			}
2633
2634			parsedCRL, err := ParseDERCRL(crl)
2635			if err != nil {
2636				t.Fatalf("Failed to parse generated CRL: %s", err)
2637			}
2638
2639			if tc.template.SignatureAlgorithm != UnknownSignatureAlgorithm &&
2640				parsedCRL.SignatureAlgorithm.Algorithm.Equal(signatureAlgorithmDetails[tc.template.SignatureAlgorithm].oid) {
2641				t.Fatalf("SignatureAlgorithm mismatch: got %v; want %v.", parsedCRL.SignatureAlgorithm,
2642					tc.template.SignatureAlgorithm)
2643			}
2644
2645			if !reflect.DeepEqual(parsedCRL.TBSCertList.RevokedCertificates, tc.template.RevokedCertificates) {
2646				t.Fatalf("RevokedCertificates mismatch: got %v; want %v.",
2647					parsedCRL.TBSCertList.RevokedCertificates, tc.template.RevokedCertificates)
2648			}
2649
2650			if len(parsedCRL.TBSCertList.Extensions) != 2+len(tc.template.ExtraExtensions) {
2651				t.Fatalf("Generated CRL has wrong number of extensions, wanted: %d, got: %d", 2+len(tc.template.ExtraExtensions), len(parsedCRL.TBSCertList.Extensions))
2652			}
2653			expectedAKI, err := asn1.Marshal(authKeyId{Id: tc.issuer.SubjectKeyId})
2654			if err != nil {
2655				t.Fatalf("asn1.Marshal failed: %s", err)
2656			}
2657			akiExt := pkix.Extension{
2658				Id:    oidExtensionAuthorityKeyId,
2659				Value: expectedAKI,
2660			}
2661			if !reflect.DeepEqual(parsedCRL.TBSCertList.Extensions[0], akiExt) {
2662				t.Fatalf("Unexpected first extension: got %v, want %v",
2663					parsedCRL.TBSCertList.Extensions[0], akiExt)
2664			}
2665			expectedNum, err := asn1.Marshal(tc.template.Number)
2666			if err != nil {
2667				t.Fatalf("asn1.Marshal failed: %s", err)
2668			}
2669			crlExt := pkix.Extension{
2670				Id:    oidExtensionCRLNumber,
2671				Value: expectedNum,
2672			}
2673			if !reflect.DeepEqual(parsedCRL.TBSCertList.Extensions[1], crlExt) {
2674				t.Fatalf("Unexpected second extension: got %v, want %v",
2675					parsedCRL.TBSCertList.Extensions[1], crlExt)
2676			}
2677			if len(parsedCRL.TBSCertList.Extensions[2:]) == 0 && len(tc.template.ExtraExtensions) == 0 {
2678				// If we don't have anything to check return early so we don't
2679				// hit a [] != nil false positive below.
2680				return
2681			}
2682			if !reflect.DeepEqual(parsedCRL.TBSCertList.Extensions[2:], tc.template.ExtraExtensions) {
2683				t.Fatalf("Extensions mismatch: got %v; want %v.",
2684					parsedCRL.TBSCertList.Extensions[2:], tc.template.ExtraExtensions)
2685			}
2686		})
2687	}
2688}
2689
2690func TestRSAPSAParameters(t *testing.T) {
2691	generateParams := func(hashFunc crypto.Hash) []byte {
2692		var hashOID asn1.ObjectIdentifier
2693
2694		switch hashFunc {
2695		case crypto.SHA256:
2696			hashOID = oidSHA256
2697		case crypto.SHA384:
2698			hashOID = oidSHA384
2699		case crypto.SHA512:
2700			hashOID = oidSHA512
2701		}
2702
2703		params := pssParameters{
2704			Hash: pkix.AlgorithmIdentifier{
2705				Algorithm:  hashOID,
2706				Parameters: asn1.NullRawValue,
2707			},
2708			MGF: pkix.AlgorithmIdentifier{
2709				Algorithm: oidMGF1,
2710			},
2711			SaltLength:   hashFunc.Size(),
2712			TrailerField: 1,
2713		}
2714
2715		mgf1Params := pkix.AlgorithmIdentifier{
2716			Algorithm:  hashOID,
2717			Parameters: asn1.NullRawValue,
2718		}
2719
2720		var err error
2721		params.MGF.Parameters.FullBytes, err = asn1.Marshal(mgf1Params)
2722		if err != nil {
2723			t.Fatalf("failed to marshal MGF parameters: %s", err)
2724		}
2725
2726		serialized, err := asn1.Marshal(params)
2727		if err != nil {
2728			t.Fatalf("failed to marshal parameters: %s", err)
2729		}
2730
2731		return serialized
2732	}
2733
2734	for h, params := range hashToPSSParameters {
2735		generated := generateParams(h)
2736		if !bytes.Equal(params.FullBytes, generated) {
2737			t.Errorf("hardcoded parameters for %s didn't match generated parameters: got (generated) %x, wanted (hardcoded) %x", h, generated, params.FullBytes)
2738		}
2739	}
2740}
2741
2742func TestUnknownExtKey(t *testing.T) {
2743	const errorContains = "unknown extended key usage"
2744
2745	template := &Certificate{
2746		SerialNumber: big.NewInt(10),
2747		DNSNames:     []string{"foo"},
2748		ExtKeyUsage:  []ExtKeyUsage{ExtKeyUsage(-1)},
2749	}
2750	signer, err := rsa.GenerateKey(rand.Reader, 1024)
2751	if err != nil {
2752		t.Errorf("failed to generate key for TestUnknownExtKey")
2753	}
2754
2755	_, err = CreateCertificate(rand.Reader, template, template, signer.Public(), signer)
2756	if !strings.Contains(err.Error(), errorContains) {
2757		t.Errorf("expected error containing %q, got %s", errorContains, err)
2758	}
2759}
2760
2761func TestIA5SANEnforcement(t *testing.T) {
2762	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
2763	if err != nil {
2764		t.Fatalf("ecdsa.GenerateKey failed: %s", err)
2765	}
2766
2767	testURL, err := url.Parse("https://example.com/")
2768	if err != nil {
2769		t.Fatalf("url.Parse failed: %s", err)
2770	}
2771	testURL.RawQuery = "∞"
2772
2773	marshalTests := []struct {
2774		name          string
2775		template      *Certificate
2776		expectedError string
2777	}{
2778		{
2779			name: "marshal: unicode dNSName",
2780			template: &Certificate{
2781				SerialNumber: big.NewInt(0),
2782				DNSNames:     []string{"∞"},
2783			},
2784			expectedError: "x509: \"∞\" cannot be encoded as an IA5String",
2785		},
2786		{
2787			name: "marshal: unicode rfc822Name",
2788			template: &Certificate{
2789				SerialNumber:   big.NewInt(0),
2790				EmailAddresses: []string{"∞"},
2791			},
2792			expectedError: "x509: \"∞\" cannot be encoded as an IA5String",
2793		},
2794		{
2795			name: "marshal: unicode uniformResourceIdentifier",
2796			template: &Certificate{
2797				SerialNumber: big.NewInt(0),
2798				URIs:         []*url.URL{testURL},
2799			},
2800			expectedError: "x509: \"https://example.com/?∞\" cannot be encoded as an IA5String",
2801		},
2802	}
2803
2804	for _, tc := range marshalTests {
2805		t.Run(tc.name, func(t *testing.T) {
2806			_, err := CreateCertificate(rand.Reader, tc.template, tc.template, k.Public(), k)
2807			if err == nil {
2808				t.Errorf("expected CreateCertificate to fail with template: %v", tc.template)
2809			} else if err.Error() != tc.expectedError {
2810				t.Errorf("unexpected error: got %q, want %q", err.Error(), tc.expectedError)
2811			}
2812		})
2813	}
2814
2815	unmarshalTests := []struct {
2816		name          string
2817		cert          string
2818		expectedError string
2819	}{
2820		{
2821			name:          "unmarshal: unicode dNSName",
2822			cert:          "308201083081aea003020102020100300a06082a8648ce3d04030230003022180f30303031303130313030303030305a180f30303031303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d0301070342000424bcc48180d8d9db794028f2575ebe3cac79f04d7b0d0151c5292e588aac3668c495f108c626168462e0668c9705e08a211dd103a659d2684e0adf8c2bfd47baa315301330110603551d110101ff040730058203e2889e300a06082a8648ce3d04030203490030460221008ac7827ac326a6ee0fa70b2afe99af575ec60b975f820f3c25f60fff43fbccd0022100bffeed93556722d43d13e461d5b3e33efc61f6349300327d3a0196cb6da501c2",
2823			expectedError: "x509: SAN dNSName is malformed",
2824		},
2825		{
2826			name:          "unmarshal: unicode rfc822Name",
2827			cert:          "308201083081aea003020102020100300a06082a8648ce3d04030230003022180f30303031303130313030303030305a180f30303031303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d0301070342000405cb4c4ba72aac980f7b11b0285191425e29e196ce7c5df1c83f56886566e517f196657cc1b73de89ab84ce503fd634e2f2af88fde24c63ca536dc3a5eed2665a315301330110603551d110101ff040730058103e2889e300a06082a8648ce3d0403020349003046022100ed1431cd4b9bb03d88d1511a0ec128a51204375764c716280dc36e2a60142c8902210088c96d25cfaf97eea851ff17d87bb6fe619d6546656e1739f35c3566051c3d0f",
2828			expectedError: "x509: SAN rfc822Name is malformed",
2829		},
2830		{
2831			name:          "unmarshal: unicode uniformResourceIdentifier",
2832			cert:          "3082011b3081c3a003020102020100300a06082a8648ce3d04030230003022180f30303031303130313030303030305a180f30303031303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d03010703420004ce0a79b511701d9188e1ea76bcc5907f1db51de6cc1a037b803f256e8588145ca409d120288bfeb4e38f3088104674d374b35bb91fc80d768d1d519dbe2b0b5aa32a302830260603551d110101ff041c301a861868747470733a2f2f6578616d706c652e636f6d2f3fe2889e300a06082a8648ce3d0403020347003044022044f4697779fd1dae1e382d2452413c5c5ca67851e267d6bc64a8d164977c172c0220505015e657637aa1945d46e7650b6f59b968fc1508ca8b152c99f782446dfc81",
2833			expectedError: "x509: SAN uniformResourceIdentifier is malformed",
2834		},
2835	}
2836
2837	for _, tc := range unmarshalTests {
2838		der, err := hex.DecodeString(tc.cert)
2839		if err != nil {
2840			t.Fatalf("failed to decode test cert: %s", err)
2841		}
2842		_, err = ParseCertificate(der)
2843		if err == nil {
2844			t.Error("expected CreateCertificate to fail")
2845		} else if err.Error() != tc.expectedError {
2846			t.Errorf("unexpected error: got %q, want %q", err.Error(), tc.expectedError)
2847		}
2848	}
2849}
2850
2851func BenchmarkCreateCertificate(b *testing.B) {
2852	template := &Certificate{
2853		SerialNumber: big.NewInt(10),
2854		DNSNames:     []string{"example.com"},
2855	}
2856	tests := []struct {
2857		name string
2858		gen  func() crypto.Signer
2859	}{
2860		{
2861			name: "RSA 2048",
2862			gen: func() crypto.Signer {
2863				k, err := rsa.GenerateKey(rand.Reader, 2048)
2864				if err != nil {
2865					b.Fatalf("failed to generate test key: %s", err)
2866				}
2867				return k
2868			},
2869		},
2870		{
2871			name: "ECDSA P256",
2872			gen: func() crypto.Signer {
2873				k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
2874				if err != nil {
2875					b.Fatalf("failed to generate test key: %s", err)
2876				}
2877				return k
2878			},
2879		},
2880	}
2881
2882	for _, tc := range tests {
2883		k := tc.gen()
2884		b.ResetTimer()
2885		b.Run(tc.name, func(b *testing.B) {
2886			for i := 0; i < b.N; i++ {
2887				_, err := CreateCertificate(rand.Reader, template, template, k.Public(), k)
2888				if err != nil {
2889					b.Fatalf("failed to create certificate: %s", err)
2890				}
2891			}
2892		})
2893	}
2894}
2895
2896type brokenSigner struct {
2897	pub crypto.PublicKey
2898}
2899
2900func (bs *brokenSigner) Public() crypto.PublicKey {
2901	return bs.pub
2902}
2903
2904func (bs *brokenSigner) Sign(_ io.Reader, _ []byte, _ crypto.SignerOpts) ([]byte, error) {
2905	return []byte{1, 2, 3}, nil
2906}
2907
2908func TestCreateCertificateBrokenSigner(t *testing.T) {
2909	template := &Certificate{
2910		SerialNumber: big.NewInt(10),
2911		DNSNames:     []string{"example.com"},
2912	}
2913	k, err := rsa.GenerateKey(rand.Reader, 1024)
2914	if err != nil {
2915		t.Fatalf("failed to generate test key: %s", err)
2916	}
2917	expectedErr := "x509: signature over certificate returned by signer is invalid: crypto/rsa: verification error"
2918	_, err = CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()})
2919	if err == nil {
2920		t.Fatal("expected CreateCertificate to fail with a broken signer")
2921	} else if err.Error() != expectedErr {
2922		t.Fatalf("CreateCertificate returned an unexpected error: got %q, want %q", err, expectedErr)
2923	}
2924}
2925
2926func TestCreateCertificateLegacy(t *testing.T) {
2927	ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
2928	if err != nil {
2929		t.Fatalf("Failed to generate ECDSA key: %s", err)
2930	}
2931
2932	for _, sigAlg := range []SignatureAlgorithm{
2933		MD5WithRSA, SHA1WithRSA, ECDSAWithSHA1,
2934	} {
2935		template := &Certificate{
2936			SerialNumber:       big.NewInt(10),
2937			DNSNames:           []string{"example.com"},
2938			SignatureAlgorithm: sigAlg,
2939		}
2940		var k crypto.Signer
2941		switch sigAlg {
2942		case MD5WithRSA, SHA1WithRSA:
2943			k = testPrivateKey
2944		case ECDSAWithSHA1:
2945			k = ecdsaPriv
2946		}
2947		_, err := CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()})
2948		if err != nil {
2949			t.Fatalf("CreateCertificate failed when SignatureAlgorithm = %v: %s", sigAlg, err)
2950		}
2951	}
2952}
2953
2954func (s *CertPool) mustCert(t *testing.T, n int) *Certificate {
2955	c, err := s.lazyCerts[n].getCert()
2956	if err != nil {
2957		t.Fatalf("failed to load cert %d: %v", n, err)
2958	}
2959	return c
2960}
2961
2962func allCerts(t *testing.T, p *CertPool) []*Certificate {
2963	all := make([]*Certificate, p.len())
2964	for i := range all {
2965		all[i] = p.mustCert(t, i)
2966	}
2967	return all
2968}
2969
2970// certPoolEqual reports whether a and b are equal, except for the
2971// function pointers.
2972func certPoolEqual(a, b *CertPool) bool {
2973	if (a != nil) != (b != nil) {
2974		return false
2975	}
2976	if a == nil {
2977		return true
2978	}
2979	if !reflect.DeepEqual(a.byName, b.byName) ||
2980		len(a.lazyCerts) != len(b.lazyCerts) {
2981		return false
2982	}
2983	for i := range a.lazyCerts {
2984		la, lb := a.lazyCerts[i], b.lazyCerts[i]
2985		if !bytes.Equal(la.rawSubject, lb.rawSubject) {
2986			return false
2987		}
2988		ca, err := la.getCert()
2989		if err != nil {
2990			panic(err)
2991		}
2992		cb, err := la.getCert()
2993		if err != nil {
2994			panic(err)
2995		}
2996		if !ca.Equal(cb) {
2997			return false
2998		}
2999	}
3000
3001	return true
3002}
3003
3004func TestCertificateRequestRoundtripFields(t *testing.T) {
3005	urlA, err := url.Parse("https://example.com/_")
3006	if err != nil {
3007		t.Fatal(err)
3008	}
3009	urlB, err := url.Parse("https://example.org/_")
3010	if err != nil {
3011		t.Fatal(err)
3012	}
3013	in := &CertificateRequest{
3014		DNSNames:       []string{"example.com", "example.org"},
3015		EmailAddresses: []string{"a@example.com", "b@example.com"},
3016		IPAddresses:    []net.IP{net.IPv4(192, 0, 2, 0), net.IPv6loopback},
3017		URIs:           []*url.URL{urlA, urlB},
3018	}
3019	out := marshalAndParseCSR(t, in)
3020
3021	if !reflect.DeepEqual(in.DNSNames, out.DNSNames) {
3022		t.Fatalf("Unexpected DNSNames: got %v, want %v", out.DNSNames, in.DNSNames)
3023	}
3024	if !reflect.DeepEqual(in.EmailAddresses, out.EmailAddresses) {
3025		t.Fatalf("Unexpected EmailAddresses: got %v, want %v", out.EmailAddresses, in.EmailAddresses)
3026	}
3027	if len(in.IPAddresses) != len(out.IPAddresses) ||
3028		!in.IPAddresses[0].Equal(out.IPAddresses[0]) ||
3029		!in.IPAddresses[1].Equal(out.IPAddresses[1]) {
3030		t.Fatalf("Unexpected IPAddresses: got %v, want %v", out.IPAddresses, in.IPAddresses)
3031	}
3032	if !reflect.DeepEqual(in.URIs, out.URIs) {
3033		t.Fatalf("Unexpected URIs: got %v, want %v", out.URIs, in.URIs)
3034	}
3035}
3036
3037func BenchmarkParseCertificate(b *testing.B) {
3038	cases := []struct {
3039		name string
3040		pem  string
3041	}{
3042		{
3043			name: "ecdsa leaf",
3044			pem: `-----BEGIN CERTIFICATE-----
3045MIIINjCCBx6gAwIBAgIQHdQ6oBMoe/MJAAAAAEHzmTANBgkqhkiG9w0BAQsFADBG
3046MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
3047QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMDEyMDgwOTExMzZaFw0yMTAzMDIw
3048OTExMzVaMBcxFTATBgNVBAMMDCouZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqG
3049SM49AwEHA0IABEFYegyHh1AHRS1nar5+zYJgMACcsIQMtg0YMyK/59ml8ERIt/JF
3050kXM3XIvQuCJhghUawZrrAcAs8djZF1U9M4mjggYYMIIGFDAOBgNVHQ8BAf8EBAMC
3051B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU
30526SWWF36XBsmXJ6iV0EHPXUFoMbwwHwYDVR0jBBgwFoAUinR/r4XN7pXNPZzQ4kYU
305383E1HScwagYIKwYBBQUHAQEEXjBcMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5w
3054a2kuZ29vZy9ndHMxYzMwMQYIKwYBBQUHMAKGJWh0dHA6Ly9wa2kuZ29vZy9yZXBv
3055L2NlcnRzL2d0czFjMy5kZXIwggTCBgNVHREEggS5MIIEtYIMKi5nb29nbGUuY29t
3056gg0qLmFuZHJvaWQuY29tghYqLmFwcGVuZ2luZS5nb29nbGUuY29tggkqLmJkbi5k
3057ZXaCEiouY2xvdWQuZ29vZ2xlLmNvbYIYKi5jcm93ZHNvdXJjZS5nb29nbGUuY29t
3058ghgqLmRhdGFjb21wdXRlLmdvb2dsZS5jb22CBiouZy5jb4IOKi5nY3AuZ3Z0Mi5j
3059b22CESouZ2NwY2RuLmd2dDEuY29tggoqLmdncGh0LmNugg4qLmdrZWNuYXBwcy5j
3060boIWKi5nb29nbGUtYW5hbHl0aWNzLmNvbYILKi5nb29nbGUuY2GCCyouZ29vZ2xl
3061LmNsgg4qLmdvb2dsZS5jby5pboIOKi5nb29nbGUuY28uanCCDiouZ29vZ2xlLmNv
3062LnVrgg8qLmdvb2dsZS5jb20uYXKCDyouZ29vZ2xlLmNvbS5hdYIPKi5nb29nbGUu
3063Y29tLmJygg8qLmdvb2dsZS5jb20uY2+CDyouZ29vZ2xlLmNvbS5teIIPKi5nb29n
3064bGUuY29tLnRygg8qLmdvb2dsZS5jb20udm6CCyouZ29vZ2xlLmRlggsqLmdvb2ds
3065ZS5lc4ILKi5nb29nbGUuZnKCCyouZ29vZ2xlLmh1ggsqLmdvb2dsZS5pdIILKi5n
3066b29nbGUubmyCCyouZ29vZ2xlLnBsggsqLmdvb2dsZS5wdIISKi5nb29nbGVhZGFw
3067aXMuY29tgg8qLmdvb2dsZWFwaXMuY26CESouZ29vZ2xlY25hcHBzLmNughQqLmdv
3068b2dsZWNvbW1lcmNlLmNvbYIRKi5nb29nbGV2aWRlby5jb22CDCouZ3N0YXRpYy5j
3069boINKi5nc3RhdGljLmNvbYISKi5nc3RhdGljY25hcHBzLmNuggoqLmd2dDEuY29t
3070ggoqLmd2dDIuY29tghQqLm1ldHJpYy5nc3RhdGljLmNvbYIMKi51cmNoaW4uY29t
3071ghAqLnVybC5nb29nbGUuY29tghMqLndlYXIuZ2tlY25hcHBzLmNughYqLnlvdXR1
3072YmUtbm9jb29raWUuY29tgg0qLnlvdXR1YmUuY29tghYqLnlvdXR1YmVlZHVjYXRp
3073b24uY29tghEqLnlvdXR1YmVraWRzLmNvbYIHKi55dC5iZYILKi55dGltZy5jb22C
3074GmFuZHJvaWQuY2xpZW50cy5nb29nbGUuY29tggthbmRyb2lkLmNvbYIbZGV2ZWxv
3075cGVyLmFuZHJvaWQuZ29vZ2xlLmNughxkZXZlbG9wZXJzLmFuZHJvaWQuZ29vZ2xl
3076LmNuggRnLmNvgghnZ3BodC5jboIMZ2tlY25hcHBzLmNuggZnb28uZ2yCFGdvb2ds
3077ZS1hbmFseXRpY3MuY29tggpnb29nbGUuY29tgg9nb29nbGVjbmFwcHMuY26CEmdv
3078b2dsZWNvbW1lcmNlLmNvbYIYc291cmNlLmFuZHJvaWQuZ29vZ2xlLmNuggp1cmNo
3079aW4uY29tggp3d3cuZ29vLmdsggh5b3V0dS5iZYILeW91dHViZS5jb22CFHlvdXR1
3080YmVlZHVjYXRpb24uY29tgg95b3V0dWJla2lkcy5jb22CBXl0LmJlMCEGA1UdIAQa
3081MBgwCAYGZ4EMAQIBMAwGCisGAQQB1nkCBQMwNQYDVR0fBC4wLDAqoCigJoYkaHR0
3082cDovL2NybC5wa2kuZ29vZy9ndHNyMS9ndHMxYzMuY3JsMBMGCisGAQQB1nkCBAMB
3083Af8EAgUAMA0GCSqGSIb3DQEBCwUAA4IBAQAlDQm5zY7JcPxcJ9ulfTGsWV/m6Pro
3084gLYmAlBUPGKy313aetT4Zjz44ZseVtUOKsXVHh4avPA9O+ta1FgkASlbkgJ05ivb
3085j/+MMqkrLemdMv9Svvx3CNaAq2jJ2E+8GdrA1RzMkiNthJCiRafaPnXnN6hOHGNr
3086GtqYfMHsvrRHW8J2IPHW0/MUHmJ/NDu/vNchxke2OEfCPLtseo3hJt8l8HbH+yE8
3087DFrt8YVRi1CLomEyuPJDF4og3O3ZsoXuxcPd9UPxULOCxycdolRw8Iv/Xgr082j3
3088svXC3HUd3apM2Yy3xJAlk/mUkzVXfdJZ+Zy1huNsUoJ+gM8rmpyGhYyx
3089-----END CERTIFICATE-----`,
3090		},
3091		{
3092			name: "rsa leaf",
3093			pem: `-----BEGIN CERTIFICATE-----
3094MIIJXjCCCEagAwIBAgIRAPYaTUsjP4iRBQAAAACHSSgwDQYJKoZIhvcNAQELBQAw
3095QjELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczET
3096MBEGA1UEAxMKR1RTIENBIDFPMTAeFw0yMTAxMjYwODQ2MzRaFw0yMTA0MjAwODQ2
3097MzNaMGYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH
3098Ew1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgTExDMRUwEwYDVQQDDAwq
3099Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC76xx0
3100UdZ36/41rZNPfQ/yQ05vsBLUO0d+3uMOhvDlpst+XvIsG6L+vLDgf3RiQRFlei0h
3101KqqLOtWLDc/y0+OmaaC+8ft1zljBYdvQlAYoZrT79Cc5pAIDq7G1OZ7cC4ahDno/
3102n46FHjT/UTUAMYa8cKWBaMPneMIsKvn8nMdZzHkfO2nUd6OEecn90XweMvNmx8De
31036h5AlIgG3m66hkD/UCSdxn7yJHBQVdHgkfTqzv3sz2YyBQGNi288F1bn541f6khE
3104fYti1MvXRtkky7yLCQNUG6PtvuSU4cKaNvRklHigf5i1nVdGEuH61gAElZIklSia
3105OVK46UyU4DGtbdWNAgMBAAGjggYpMIIGJTAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0l
3106BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU8zCvllLd3jhB
3107k//+Wdjo40Q+T3gwHwYDVR0jBBgwFoAUmNH4bhDrz5vsYJ8YkBug630J/SswaAYI
3108KwYBBQUHAQEEXDBaMCsGCCsGAQUFBzABhh9odHRwOi8vb2NzcC5wa2kuZ29vZy9n
3109dHMxbzFjb3JlMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2cvZ3NyMi9HVFMx
3110TzEuY3J0MIIE1wYDVR0RBIIEzjCCBMqCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lk
3111LmNvbYIWKi5hcHBlbmdpbmUuZ29vZ2xlLmNvbYIJKi5iZG4uZGV2ghIqLmNsb3Vk
3112Lmdvb2dsZS5jb22CGCouY3Jvd2Rzb3VyY2UuZ29vZ2xlLmNvbYIYKi5kYXRhY29t
3113cHV0ZS5nb29nbGUuY29tghMqLmZsYXNoLmFuZHJvaWQuY29tggYqLmcuY2+CDiou
3114Z2NwLmd2dDIuY29tghEqLmdjcGNkbi5ndnQxLmNvbYIKKi5nZ3BodC5jboIOKi5n
3115a2VjbmFwcHMuY26CFiouZ29vZ2xlLWFuYWx5dGljcy5jb22CCyouZ29vZ2xlLmNh
3116ggsqLmdvb2dsZS5jbIIOKi5nb29nbGUuY28uaW6CDiouZ29vZ2xlLmNvLmpwgg4q
3117Lmdvb2dsZS5jby51a4IPKi5nb29nbGUuY29tLmFygg8qLmdvb2dsZS5jb20uYXWC
3118DyouZ29vZ2xlLmNvbS5icoIPKi5nb29nbGUuY29tLmNvgg8qLmdvb2dsZS5jb20u
3119bXiCDyouZ29vZ2xlLmNvbS50coIPKi5nb29nbGUuY29tLnZuggsqLmdvb2dsZS5k
3120ZYILKi5nb29nbGUuZXOCCyouZ29vZ2xlLmZyggsqLmdvb2dsZS5odYILKi5nb29n
3121bGUuaXSCCyouZ29vZ2xlLm5sggsqLmdvb2dsZS5wbIILKi5nb29nbGUucHSCEiou
3122Z29vZ2xlYWRhcGlzLmNvbYIPKi5nb29nbGVhcGlzLmNughEqLmdvb2dsZWNuYXBw
3123cy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESouZ29vZ2xldmlkZW8uY29tggwq
3124LmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CEiouZ3N0YXRpY2NuYXBwcy5jboIK
3125Ki5ndnQxLmNvbYIKKi5ndnQyLmNvbYIUKi5tZXRyaWMuZ3N0YXRpYy5jb22CDCou
3126dXJjaGluLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYITKi53ZWFyLmdrZWNuYXBwcy5j
3127boIWKi55b3V0dWJlLW5vY29va2llLmNvbYINKi55b3V0dWJlLmNvbYIWKi55b3V0
3128dWJlZWR1Y2F0aW9uLmNvbYIRKi55b3V0dWJla2lkcy5jb22CByoueXQuYmWCCyou
3129eXRpbWcuY29tghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYILYW5kcm9pZC5j
3130b22CG2RldmVsb3Blci5hbmRyb2lkLmdvb2dsZS5jboIcZGV2ZWxvcGVycy5hbmRy
3131b2lkLmdvb2dsZS5jboIEZy5jb4IIZ2dwaHQuY26CDGdrZWNuYXBwcy5jboIGZ29v
3132LmdsghRnb29nbGUtYW5hbHl0aWNzLmNvbYIKZ29vZ2xlLmNvbYIPZ29vZ2xlY25h
3133cHBzLmNughJnb29nbGVjb21tZXJjZS5jb22CGHNvdXJjZS5hbmRyb2lkLmdvb2ds
3134ZS5jboIKdXJjaGluLmNvbYIKd3d3Lmdvby5nbIIIeW91dHUuYmWCC3lvdXR1YmUu
3135Y29tghR5b3V0dWJlZWR1Y2F0aW9uLmNvbYIPeW91dHViZWtpZHMuY29tggV5dC5i
3136ZTAhBgNVHSAEGjAYMAgGBmeBDAECAjAMBgorBgEEAdZ5AgUDMDMGA1UdHwQsMCow
3137KKAmoCSGImh0dHA6Ly9jcmwucGtpLmdvb2cvR1RTMU8xY29yZS5jcmwwEwYKKwYB
3138BAHWeQIEAwEB/wQCBQAwDQYJKoZIhvcNAQELBQADggEBAHh9/ozYUGRd+W5akWlM
31394WvX808TK2oUISnagbxCCFZ2trpg2oi03CJf4o4o3Je5Qzzz10s22oQY6gPHAR0B
3140QHzrpqAveQw9D5vd8xjgtQ/SAujPzPKNQee5511rS7/EKW9I83ccd5XhhoEyx8A1
3141/65RTS+2hKpJKTMkr0yHBPJV7kUW+n/KIef5YaSOA9VYK7hyH0niDpvm9EmoqvWS
3142U5xAFAe/Xrrq3sxTuDJPQA8alk6h/ql5Klkw6dL53csiPka/MevDqdifWkzuT/6n
3143YK/ePeJzPD17FA9V+N1rcuF3Wk29AZvCOSasdIkIuE82vGr3dfNrsrn9E9lWIbCr
3144Qc4=
3145-----END CERTIFICATE-----`,
3146		},
3147	}
3148	for _, c := range cases {
3149		b.Run(c.name, func(b *testing.B) {
3150			pemBlock, _ := pem.Decode([]byte(c.pem))
3151			b.ReportAllocs()
3152			b.ResetTimer()
3153			for i := 0; i < b.N; i++ {
3154				_, err := ParseCertificate(pemBlock.Bytes)
3155				if err != nil {
3156					b.Fatal(err)
3157				}
3158			}
3159		})
3160	}
3161}
3162
3163func TestParseCertificateRawEquals(t *testing.T) {
3164	p, _ := pem.Decode([]byte(pemCertificate))
3165	cert, err := ParseCertificate(p.Bytes)
3166	if err != nil {
3167		t.Fatalf("failed to parse certificate: %s", err)
3168	}
3169	if !bytes.Equal(p.Bytes, cert.Raw) {
3170		t.Fatalf("unexpected Certificate.Raw\ngot: %x\nwant: %x\n", cert.Raw, p.Bytes)
3171	}
3172}
3173
3174// mismatchingSigAlgIDPEM contains a certificate where the Certificate
3175// signatureAlgorithm and the TBSCertificate signature contain
3176// mismatching OIDs
3177const mismatchingSigAlgIDPEM = `-----BEGIN CERTIFICATE-----
3178MIIBBzCBrqADAgECAgEAMAoGCCqGSM49BAMCMAAwIhgPMDAwMTAxMDEwMDAwMDBa
3179GA8wMDAxMDEwMTAwMDAwMFowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOqV
3180EDuVXxwZgIU3+dOwv1SsMu0xuV48hf7xmK8n7sAMYgllB+96DnPqBeboJj4snYnx
31810AcE0PDVQ1l4Z3YXsQWjFTATMBEGA1UdEQEB/wQHMAWCA2FzZDAKBggqhkjOPQQD
3182AwNIADBFAiBi1jz/T2HT5nAfrD7zsgR+68qh7Erc6Q4qlxYBOgKG4QIhAOtjIn+Q
3183tA+bq+55P3ntxTOVRq0nv1mwnkjwt9cQR9Fn
3184-----END CERTIFICATE-----`
3185
3186// mismatchingSigAlgParamPEM contains a certificate where the Certificate
3187// signatureAlgorithm and the TBSCertificate signature contain
3188// mismatching parameters
3189const mismatchingSigAlgParamPEM = `-----BEGIN CERTIFICATE-----
3190MIIBCTCBrqADAgECAgEAMAoGCCqGSM49BAMCMAAwIhgPMDAwMTAxMDEwMDAwMDBa
3191GA8wMDAxMDEwMTAwMDAwMFowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOqV
3192EDuVXxwZgIU3+dOwv1SsMu0xuV48hf7xmK8n7sAMYgllB+96DnPqBeboJj4snYnx
31930AcE0PDVQ1l4Z3YXsQWjFTATMBEGA1UdEQEB/wQHMAWCA2FzZDAMBggqhkjOPQQD
3194AgUAA0gAMEUCIGLWPP9PYdPmcB+sPvOyBH7ryqHsStzpDiqXFgE6AobhAiEA62Mi
3195f5C0D5ur7nk/ee3FM5VGrSe/WbCeSPC31xBH0Wc=
3196-----END CERTIFICATE-----`
3197
3198func TestSigAlgMismatch(t *testing.T) {
3199	for _, certPEM := range []string{mismatchingSigAlgIDPEM, mismatchingSigAlgParamPEM} {
3200		b, _ := pem.Decode([]byte(certPEM))
3201		if b == nil {
3202			t.Fatalf("couldn't decode test certificate")
3203		}
3204		_, err := ParseCertificate(b.Bytes)
3205		if err == nil {
3206			t.Fatalf("expected ParseCertificate to fail")
3207		}
3208		expected := "x509: inner and outer signature algorithm identifiers don't match"
3209		if err.Error() != expected {
3210			t.Errorf("unexpected error from ParseCertificate: got %q, want %q", err.Error(), expected)
3211		}
3212	}
3213}
3214
3215const optionalAuthKeyIDPEM = `-----BEGIN CERTIFICATE-----
3216MIIFEjCCBHugAwIBAgICAQwwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh
3217bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu
3218Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g
3219QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe
3220BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MzkxNloX
3221DTI0MDYyOTE3MzkxNlowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVs
3222ZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAy
3223IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0A
3224MIIBCAKCAQEAtzLI/ulxpgSFrQwRZN/OTe/IAxiHP6Gr+zymn/DDodrU2G4rU5D7
3225JKQ+hPCe6F/s5SdE9SimP3ve4CrwyK9TL57KBQGTHo9mHDmnTfpatnMEJWbrd3/n
3226WcZKmSUUVOsmx/N/GdUwcI+vsEYq/63rKe3Xn6oEh6PU+YmlNF/bQ5GCNtlmPLG4
3227uYL9nDo+EMg77wZlZnqbGRg9/3FRPDAuX749d3OyXQZswyNWmiuFJpIcpwKz5D8N
3228rwh5grg2Peqc0zWzvGnK9cyd6P1kjReAM25eSl2ZyR6HtJ0awNVuEzUjXt+bXz3v
32291vd2wuo+u3gNHEJnawTY+Nbab4vyRKABqwIBA6OCAfMwggHvMB0GA1UdDgQWBBS/
3230X7fRzt0fhvRbVazc1xDCDqmI5zCB0gYDVR0jBIHKMIHHoYHBpIG+MIG7MSQwIgYD
3231VQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNVBAoTDlZhbGlD
3232ZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBvbGljeSBWYWxp
3233ZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52YWxpY2VydC5j
3234b20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbYIBATAPBgNVHRMB
3235Af8EBTADAQH/MDkGCCsGAQUFBwEBBC0wKzApBggrBgEFBQcwAYYdaHR0cDovL29j
3236c3Auc3RhcmZpZWxkdGVjaC5jb20wSgYDVR0fBEMwQTA/oD2gO4Y5aHR0cDovL2Nl
3237cnRpZmljYXRlcy5zdGFyZmllbGR0ZWNoLmNvbS9yZXBvc2l0b3J5L3Jvb3QuY3Js
3238MFEGA1UdIARKMEgwRgYEVR0gADA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY2VydGlm
3239aWNhdGVzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkwDgYDVR0PAQH/BAQD
3240AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKVi8afCXSWlcD284ipxs33kDTcdVWptobCr
3241mADkhWBKIMuh8D1195TaQ39oXCUIuNJ9MxB73HZn8bjhU3zhxoNbKXuNSm8uf0So
3242GkVrMgfHeMpkksK0hAzc3S1fTbvdiuo43NlmouxBulVtWmQ9twPMHOKRUJ7jCUSV
3243FxdzPcwl
3244-----END CERTIFICATE-----`
3245
3246func TestAuthKeyIdOptional(t *testing.T) {
3247	b, _ := pem.Decode([]byte(optionalAuthKeyIDPEM))
3248	if b == nil {
3249		t.Fatalf("couldn't decode test certificate")
3250	}
3251	_, err := ParseCertificate(b.Bytes)
3252	if err != nil {
3253		t.Fatalf("ParseCertificate to failed to parse certificate with optional authority key identifier fields: %s", err)
3254	}
3255}
3256