237
286
random := rand.Reader
239
288
block, _ := pem.Decode([]byte(pemPrivateKey))
240
priv, err := ParsePKCS1PrivateKey(block.Bytes)
242
t.Errorf("Failed to parse private key: %s", err)
246
commonName := "test.example.com"
247
template := Certificate{
248
SerialNumber: big.NewInt(1),
250
CommonName: commonName,
251
Organization: []string{"Acme Co"},
253
NotBefore: time.Unix(1000, 0),
254
NotAfter: time.Unix(100000, 0),
256
SubjectKeyId: []byte{1, 2, 3, 4},
257
KeyUsage: KeyUsageCertSign,
259
BasicConstraintsValid: true,
261
DNSNames: []string{"test.example.com"},
263
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
264
PermittedDNSDomains: []string{".example.com", "example.com"},
267
derBytes, err := CreateCertificate(random, &template, &template, &priv.PublicKey, priv)
269
t.Errorf("Failed to create certificate: %s", err)
273
cert, err := ParseCertificate(derBytes)
275
t.Errorf("Failed to parse certificate: %s", err)
279
if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
280
t.Errorf("Failed to parse policy identifiers: got:%#v want:%#v", cert.PolicyIdentifiers, template.PolicyIdentifiers)
283
if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
284
t.Errorf("Failed to parse name constraints: %#v", cert.PermittedDNSDomains)
287
if cert.Subject.CommonName != commonName {
288
t.Errorf("Subject wasn't correctly copied from the template. Got %s, want %s", cert.Subject.CommonName, commonName)
291
if cert.Issuer.CommonName != commonName {
292
t.Errorf("Issuer wasn't correctly copied from the template. Got %s, want %s", cert.Issuer.CommonName, commonName)
295
err = cert.CheckSignatureFrom(cert)
297
t.Errorf("Signature verification failed: %s", err)
289
rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes)
291
t.Fatalf("Failed to parse private key: %s", err)
294
ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
296
t.Fatalf("Failed to generate ECDSA key: %s", err)
301
pub, priv interface{}
304
{"RSA/RSA", &rsaPriv.PublicKey, rsaPriv, true},
305
{"RSA/ECDSA", &rsaPriv.PublicKey, ecdsaPriv, false},
306
{"ECDSA/RSA", &ecdsaPriv.PublicKey, rsaPriv, false},
307
{"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true},
310
testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
311
testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{3, 2, 1}}
313
for _, test := range tests {
314
commonName := "test.example.com"
315
template := Certificate{
316
SerialNumber: big.NewInt(1),
318
CommonName: commonName,
319
Organization: []string{"Σ Acme Co"},
321
NotBefore: time.Unix(1000, 0),
322
NotAfter: time.Unix(100000, 0),
324
SubjectKeyId: []byte{1, 2, 3, 4},
325
KeyUsage: KeyUsageCertSign,
327
ExtKeyUsage: testExtKeyUsage,
328
UnknownExtKeyUsage: testUnknownExtKeyUsage,
330
BasicConstraintsValid: true,
333
DNSNames: []string{"test.example.com"},
334
EmailAddresses: []string{"gopher@golang.org"},
335
IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
337
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
338
PermittedDNSDomains: []string{".example.com", "example.com"},
341
derBytes, err := CreateCertificate(random, &template, &template, test.pub, test.priv)
343
t.Errorf("%s: failed to create certificate: %s", test.name, err)
347
cert, err := ParseCertificate(derBytes)
349
t.Errorf("%s: failed to parse certificate: %s", test.name, err)
353
if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
354
t.Errorf("%s: failed to parse policy identifiers: got:%#v want:%#v", test.name, cert.PolicyIdentifiers, template.PolicyIdentifiers)
357
if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
358
t.Errorf("%s: failed to parse name constraints: %#v", test.name, cert.PermittedDNSDomains)
361
if cert.Subject.CommonName != commonName {
362
t.Errorf("%s: subject wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Subject.CommonName, commonName)
365
if cert.Issuer.CommonName != commonName {
366
t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName)
369
if !reflect.DeepEqual(cert.ExtKeyUsage, testExtKeyUsage) {
370
t.Errorf("%s: extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.ExtKeyUsage, testExtKeyUsage)
373
if !reflect.DeepEqual(cert.UnknownExtKeyUsage, testUnknownExtKeyUsage) {
374
t.Errorf("%s: unknown extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.UnknownExtKeyUsage, testUnknownExtKeyUsage)
377
if !reflect.DeepEqual(cert.DNSNames, template.DNSNames) {
378
t.Errorf("%s: SAN DNS names differ from template. Got %v, want %v", test.name, cert.DNSNames, template.DNSNames)
381
if !reflect.DeepEqual(cert.EmailAddresses, template.EmailAddresses) {
382
t.Errorf("%s: SAN emails differ from template. Got %v, want %v", test.name, cert.EmailAddresses, template.EmailAddresses)
385
if !reflect.DeepEqual(cert.IPAddresses, template.IPAddresses) {
386
t.Errorf("%s: SAN IPs differ from template. Got %v, want %v", test.name, cert.IPAddresses, template.IPAddresses)
390
err = cert.CheckSignatureFrom(cert)
392
t.Errorf("%s: signature verification failed: %s", test.name, err)
398
// Self-signed certificate using ECDSA with SHA1 & secp256r1
399
var ecdsaSHA1CertPem = `
400
-----BEGIN CERTIFICATE-----
401
MIICDjCCAbUCCQDF6SfN0nsnrjAJBgcqhkjOPQQBMIGPMQswCQYDVQQGEwJVUzET
402
MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMG
403
A1UECgwMR29vZ2xlLCBJbmMuMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
404
CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIwMjAyMDUw
405
WhcNMjIwNTE4MjAyMDUwWjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
406
b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTATBgNVBAoMDEdvb2dsZSwg
407
SW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAhBgkqhkiG9w0BCQEWFGdv
408
bGFuZy1kZXZAZ21haWwuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/Wgn
409
WQDo5+bz71T0327ERgd5SDDXFbXLpzIZDXTkjpe8QTEbsF+ezsQfrekrpDPC4Cd3
410
P9LY0tG+aI8IyVKdUjAJBgcqhkjOPQQBA0gAMEUCIGlsqMcRqWVIWTD6wXwe6Jk2
411
DKxL46r/FLgJYnzBEH99AiEA3fBouObsvV1R3oVkb4BQYnD4/4LeId6lAT43YvyV
413
-----END CERTIFICATE-----
416
// Self-signed certificate using ECDSA with SHA256 & secp256r1
417
var ecdsaSHA256p256CertPem = `
418
-----BEGIN CERTIFICATE-----
419
MIICDzCCAbYCCQDlsuMWvgQzhTAKBggqhkjOPQQDAjCBjzELMAkGA1UEBhMCVVMx
420
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
421
BgNVBAoMDEdvb2dsZSwgSW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAh
422
BgkqhkiG9w0BCQEWFGdvbGFuZy1kZXZAZ21haWwuY29tMB4XDTEyMDUyMTAwMTkx
423
NloXDTIyMDUxOTAwMTkxNlowgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
424
Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYDVQQKDAxHb29nbGUs
425
IEluYy4xFzAVBgNVBAMMDnd3dy5nb29nbGUuY29tMSMwIQYJKoZIhvcNAQkBFhRn
426
b2xhbmctZGV2QGdtYWlsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPMt
427
2ErhxAty5EJRu9yM+MTy+hUXm3pdW1ensAv382KoGExSXAFWP7pjJnNtHO+XSwVm
428
YNtqjcAGFKpweoN//kQwCgYIKoZIzj0EAwIDRwAwRAIgIYSaUA/IB81gjbIw/hUV
429
70twxJr5EcgOo0hLp3Jm+EYCIFDO3NNcgmURbJ1kfoS3N/0O+irUtoPw38YoNkqJ
431
-----END CERTIFICATE-----
434
// Self-signed certificate using ECDSA with SHA256 & secp384r1
435
var ecdsaSHA256p384CertPem = `
436
-----BEGIN CERTIFICATE-----
437
MIICSjCCAdECCQDje/no7mXkVzAKBggqhkjOPQQDAjCBjjELMAkGA1UEBhMCVVMx
438
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
439
BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
440
CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMDYxMDM0
441
WhcNMjIwNTE5MDYxMDM0WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
442
b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
443
SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
444
YW5nLWRldkBnbWFpbC5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARRuzRNIKRK
445
jIktEmXanNmrTR/q/FaHXLhWRZ6nHWe26Fw7Rsrbk+VjGy4vfWtNn7xSFKrOu5ze
446
qxKnmE0h5E480MNgrUiRkaGO2GMJJVmxx20aqkXOk59U8yGA4CghE6MwCgYIKoZI
447
zj0EAwIDZwAwZAIwBZEN8gvmRmfeP/9C1PRLzODIY4JqWub2PLRT4mv9GU+yw3Gr
448
PU9A3CHMdEcdw/MEAjBBO1lId8KOCh9UZunsSMfqXiVurpzmhWd6VYZ/32G+M+Mh
450
-----END CERTIFICATE-----
453
// Self-signed certificate using ECDSA with SHA384 & secp521r1
454
var ecdsaSHA384p521CertPem = `
455
-----BEGIN CERTIFICATE-----
456
MIICljCCAfcCCQDhp1AFD/ahKjAKBggqhkjOPQQDAzCBjjELMAkGA1UEBhMCVVMx
457
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
458
BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
459
CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMTUwNDI5
460
WhcNMjIwNTE5MTUwNDI5WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
461
b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
462
SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
463
YW5nLWRldkBnbWFpbC5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACqx9Rv
464
IssRs1LWYcNN+WffwlHw4Tv3y8/LIAA9MF1ZScIonU9nRMxt4a2uGJVCPDw6JHpz
465
PaYc0E9puLoE9AfKpwFr59Jkot7dBg55SKPEFkddoip/rvmN7NPAWjMBirOwjOkm
466
8FPthvPhGPqsu9AvgVuHu3PosWiHGNrhh379pva8MzAKBggqhkjOPQQDAwOBjAAw
467
gYgCQgEHNmswkUdPpHqrVxp9PvLVl+xxPuHBkT+75z9JizyxtqykHQo9Uh6SWCYH
468
BF9KLolo01wMt8DjoYP5Fb3j5MH7xwJCAbWZzTOp4l4DPkIvAh4LeC4VWbwPPyqh
469
kBg71w/iEcSY3wUKgHGcJJrObZw7wys91I5kENljqw/Samdr3ka+jBJa
470
-----END CERTIFICATE-----
473
var ecdsaTests = []struct {
474
sigAlgo SignatureAlgorithm
477
{ECDSAWithSHA1, ecdsaSHA1CertPem},
478
{ECDSAWithSHA256, ecdsaSHA256p256CertPem},
479
{ECDSAWithSHA256, ecdsaSHA256p384CertPem},
480
{ECDSAWithSHA384, ecdsaSHA384p521CertPem},
483
func TestECDSA(t *testing.T) {
484
for i, test := range ecdsaTests {
485
pemBlock, _ := pem.Decode([]byte(test.pemCert))
486
cert, err := ParseCertificate(pemBlock.Bytes)
488
t.Errorf("%d: failed to parse certificate: %s", i, err)
491
if sa := cert.SignatureAlgorithm; sa != test.sigAlgo {
492
t.Errorf("%d: signature algorithm is %v, want %v", i, sa, test.sigAlgo)
494
if parsedKey, ok := cert.PublicKey.(*ecdsa.PublicKey); !ok {
495
t.Errorf("%d: wanted an ECDSA public key but found: %#v", i, parsedKey)
497
if pka := cert.PublicKeyAlgorithm; pka != ECDSA {
498
t.Errorf("%d: public key algorithm is %v, want ECDSA", i, pka)
500
if err = cert.CheckSignatureFrom(cert); err != nil {
501
t.Errorf("%d: certificate verification failed: %s", i, err)