Source file src/crypto/tls/certificates_generator_test.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package tls
     6  
     7  //go:generate go test -run ^TestGenerateCertificates$ crypto/tls -generate
     8  
     9  import (
    10  	"bytes"
    11  	"crypto/ecdsa"
    12  	"crypto/ed25519"
    13  	"crypto/elliptic"
    14  	"crypto/fips140"
    15  	"crypto/rand"
    16  	"crypto/rsa"
    17  	"crypto/x509"
    18  	"crypto/x509/pkix"
    19  	"encoding/pem"
    20  	"flag"
    21  	"fmt"
    22  	"internal/testenv"
    23  	"math/big"
    24  	"os"
    25  	"strings"
    26  	"testing"
    27  	"testing/cryptotest"
    28  	"time"
    29  )
    30  
    31  var generate = flag.Bool("generate", false, "regenerate certificates_test.go")
    32  
    33  func TestGenerateCertificates(t *testing.T) {
    34  	testenv.MustHaveSource(t)
    35  	if testing.Short() && !*generate {
    36  		t.Skip("set -generate to regenerate certificates_test.go, or run without -short to check")
    37  	}
    38  	if fips140.Version() == "v1.0.0" {
    39  		t.Skip("FIPS 140-3 module v1.0.0 doesn't support SetGlobalRandom")
    40  	}
    41  
    42  	// Allow RSA keys below 1024 bits for testRSA512.
    43  	t.Setenv("GODEBUG", os.Getenv("GODEBUG")+",rsa1024min=0")
    44  	// Unset cryptocustomrand to avoid MaybeReadByte non-determinism.
    45  	t.Setenv("GODEBUG", os.Getenv("GODEBUG")+",cryptocustomrand=0")
    46  	cryptotest.SetGlobalRandom(t, 0)
    47  
    48  	notBefore := time.Unix(1476984729, 0).Add(-100 * 24 * time.Hour)
    49  	notAfter := time.Unix(1476984729, 0).Add(100 * 24 * time.Hour)
    50  	serial := int64(0)
    51  	nextSerial := func() *big.Int {
    52  		serial++
    53  		return big.NewInt(serial)
    54  	}
    55  
    56  	// Root CA key and cert.
    57  	rootKey, err := rsa.GenerateKey(rand.Reader, 2048)
    58  	if err != nil {
    59  		t.Fatal(err)
    60  	}
    61  	rootTemplate := &x509.Certificate{
    62  		SerialNumber:          nextSerial(),
    63  		Subject:               pkix.Name{CommonName: "Root"},
    64  		NotBefore:             notBefore,
    65  		NotAfter:              notAfter,
    66  		KeyUsage:              x509.KeyUsageCertSign,
    67  		BasicConstraintsValid: true,
    68  		IsCA:                  true,
    69  	}
    70  	rootDER, err := x509.CreateCertificate(rand.Reader, rootTemplate, rootTemplate, &rootKey.PublicKey, rootKey)
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	rootCert, err := x509.ParseCertificate(rootDER)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	// Client Root CA key and cert.
    80  	clientRootKey, err := rsa.GenerateKey(rand.Reader, 2048)
    81  	if err != nil {
    82  		t.Fatal(err)
    83  	}
    84  	clientRootTemplate := &x509.Certificate{
    85  		SerialNumber:          nextSerial(),
    86  		Subject:               pkix.Name{CommonName: "Client Root"},
    87  		NotBefore:             notBefore,
    88  		NotAfter:              notAfter,
    89  		KeyUsage:              x509.KeyUsageCertSign,
    90  		BasicConstraintsValid: true,
    91  		IsCA:                  true,
    92  	}
    93  	clientRootDER, err := x509.CreateCertificate(rand.Reader, clientRootTemplate, clientRootTemplate, &clientRootKey.PublicKey, clientRootKey)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  	clientRootCert, err := x509.ParseCertificate(clientRootDER)
    98  	if err != nil {
    99  		t.Fatal(err)
   100  	}
   101  
   102  	// Helper to create a leaf template.
   103  	serverLeaf := func(cn string, san string) *x509.Certificate {
   104  		return &x509.Certificate{
   105  			SerialNumber:          nextSerial(),
   106  			Subject:               pkix.Name{CommonName: cn},
   107  			NotBefore:             notBefore,
   108  			NotAfter:              notAfter,
   109  			KeyUsage:              x509.KeyUsageDigitalSignature,
   110  			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   111  			BasicConstraintsValid: true,
   112  			DNSNames:              []string{san},
   113  		}
   114  	}
   115  	clientLeaf := func(cn string, san string) *x509.Certificate {
   116  		return &x509.Certificate{
   117  			SerialNumber:          nextSerial(),
   118  			Subject:               pkix.Name{CommonName: cn},
   119  			NotBefore:             notBefore,
   120  			NotAfter:              notAfter,
   121  			KeyUsage:              x509.KeyUsageDigitalSignature,
   122  			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
   123  			BasicConstraintsValid: true,
   124  			DNSNames:              []string{san},
   125  		}
   126  	}
   127  
   128  	type certKeyPair struct {
   129  		name    string
   130  		comment string
   131  		certPEM string
   132  		keyPEM  string
   133  	}
   134  	var pairs []certKeyPair
   135  
   136  	emit := func(name, comment string, certDER []byte, key any) {
   137  		keyDER, err := x509.MarshalPKCS8PrivateKey(key)
   138  		if err != nil {
   139  			t.Fatal(err)
   140  		}
   141  		certPEM := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}))
   142  		keyPEM := string(pem.EncodeToMemory(&pem.Block{Type: "TESTING KEY", Bytes: keyDER}))
   143  		pairs = append(pairs, certKeyPair{name, comment, strings.TrimSpace(certPEM), strings.TrimSpace(keyPEM)})
   144  	}
   145  
   146  	// Roots.
   147  	emit("testRoot", "Self-signed RSA 2048 root CA, CN=Root.", rootDER, rootKey)
   148  	emit("testClientRoot", "Self-signed RSA 2048 root CA, CN=Client Root.", clientRootDER, clientRootKey)
   149  
   150  	// Server certs issued by root.
   151  
   152  	// ECDSA P-256 (default).
   153  	ecdsaP256Key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   154  	if err != nil {
   155  		t.Fatal(err)
   156  	}
   157  	tmpl := serverLeaf("ECDSA P-256", "test.golang.example")
   158  	der, err := x509.CreateCertificate(rand.Reader, tmpl, rootCert, &ecdsaP256Key.PublicKey, rootKey)
   159  	if err != nil {
   160  		t.Fatal(err)
   161  	}
   162  	emit("testECDSAP256", "ECDSA P-256 server leaf, SAN=test.golang.example, issued by Root.", der, ecdsaP256Key)
   163  
   164  	// RSA 2048.
   165  	rsa2048Key, err := rsa.GenerateKey(rand.Reader, 2048)
   166  	if err != nil {
   167  		t.Fatal(err)
   168  	}
   169  	tmpl = serverLeaf("RSA 2048", "test.golang.example")
   170  	der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, &rsa2048Key.PublicKey, rootKey)
   171  	if err != nil {
   172  		t.Fatal(err)
   173  	}
   174  	emit("testRSA2048", "RSA 2048 server leaf, SAN=test.golang.example, issued by Root.", der, rsa2048Key)
   175  
   176  	// ECDSA P-384.
   177  	ecdsaP384Key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
   178  	if err != nil {
   179  		t.Fatal(err)
   180  	}
   181  	tmpl = serverLeaf("ECDSA P-384", "test.golang.example")
   182  	der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, &ecdsaP384Key.PublicKey, rootKey)
   183  	if err != nil {
   184  		t.Fatal(err)
   185  	}
   186  	emit("testECDSAP384", "ECDSA P-384 server leaf, SAN=test.golang.example, issued by Root.", der, ecdsaP384Key)
   187  
   188  	// ECDSA P-521.
   189  	ecdsaP521Key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
   190  	if err != nil {
   191  		t.Fatal(err)
   192  	}
   193  	tmpl = serverLeaf("ECDSA P-521", "test.golang.example")
   194  	der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, &ecdsaP521Key.PublicKey, rootKey)
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  	emit("testECDSAP521", "ECDSA P-521 server leaf, SAN=test.golang.example, issued by Root.", der, ecdsaP521Key)
   199  
   200  	// Ed25519.
   201  	ed25519Pub, ed25519Key, err := ed25519.GenerateKey(rand.Reader)
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  	tmpl = serverLeaf("Ed25519", "test.golang.example")
   206  	der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, ed25519Pub, rootKey)
   207  	if err != nil {
   208  		t.Fatal(err)
   209  	}
   210  	emit("testEd25519", "Ed25519 server leaf, SAN=test.golang.example, issued by Root.", der, ed25519Key)
   211  
   212  	// RSA-PSS: signed by root with SHA512WithRSAPSS. The leaf SPKI is
   213  	// rsaEncryption while the signatureAlgorithm is rsassaPss, for use
   214  	// with the rsa_pss_rsae_* SignatureSchemes.
   215  	rsaPSSKey, err := rsa.GenerateKey(rand.Reader, 2048)
   216  	if err != nil {
   217  		t.Fatal(err)
   218  	}
   219  	tmpl = serverLeaf("RSA-PSS", "test.golang.example")
   220  	tmpl.SignatureAlgorithm = x509.SHA512WithRSAPSS
   221  	der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, &rsaPSSKey.PublicKey, rootKey)
   222  	if err != nil {
   223  		t.Fatal(err)
   224  	}
   225  	emit("testRSAPSS", "RSA 2048 server leaf, SAN=test.golang.example, issued by Root.\n\t// Signature algorithm is SHA512WithRSAPSS (rsaEncryption SPKI, rsassaPss signature).", der, rsaPSSKey)
   226  
   227  	// RSA 1024: key is intentionally too small for rsa_pss_rsae_sha512
   228  	// (which requires at least 1040 bits), but large enough for
   229  	// rsa_pss_rsae_sha256. Used by TestHandshakeServerRSAPSS.
   230  	rsa1024Key, err := rsa.GenerateKey(rand.Reader, 1024)
   231  	if err != nil {
   232  		t.Fatal(err)
   233  	}
   234  	tmpl = serverLeaf("RSA 1024", "test.golang.example")
   235  	der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, &rsa1024Key.PublicKey, rootKey)
   236  	if err != nil {
   237  		t.Fatal(err)
   238  	}
   239  	emit("testRSA1024", "RSA 1024 server leaf, SAN=test.golang.example, issued by Root.\n\t// Key is too small for rsa_pss_rsae_sha512; used by TestHandshakeServerRSAPSS.", der, rsa1024Key)
   240  
   241  	// RSA 512: key is too small for any rsa_pss_rsae_* SignatureScheme
   242  	// (the smallest, SHA-256, requires at least 528 bits). Used by
   243  	// TestKeyTooSmallForRSAPSS.
   244  	rsa512Key, err := rsa.GenerateKey(rand.Reader, 512)
   245  	if err != nil {
   246  		t.Fatal(err)
   247  	}
   248  	tmpl = serverLeaf("RSA 512", "test.golang.example")
   249  	der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, &rsa512Key.PublicKey, rootKey)
   250  	if err != nil {
   251  		t.Fatal(err)
   252  	}
   253  	emit("testRSA512", "RSA 512 server leaf, SAN=test.golang.example, issued by Root.\n\t// Key is too small for any rsa_pss_rsae_*; used by TestKeyTooSmallForRSAPSS.", der, rsa512Key)
   254  
   255  	// SNI cert (different SAN for SNI mismatch testing).
   256  	sniKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   257  	if err != nil {
   258  		t.Fatal(err)
   259  	}
   260  	tmpl = serverLeaf("different.example.com", "different.example.com")
   261  	der, err = x509.CreateCertificate(rand.Reader, tmpl, rootCert, &sniKey.PublicKey, rootKey)
   262  	if err != nil {
   263  		t.Fatal(err)
   264  	}
   265  	emit("testSNI", "ECDSA P-256 server leaf, SAN=different.example.com, issued by Root.", der, sniKey)
   266  
   267  	// Client certs issued by client root.
   268  
   269  	clientRSAKey, err := rsa.GenerateKey(rand.Reader, 2048)
   270  	if err != nil {
   271  		t.Fatal(err)
   272  	}
   273  	tmpl = clientLeaf("clientAuth RSA 2048", "test.golang.example")
   274  	der, err = x509.CreateCertificate(rand.Reader, tmpl, clientRootCert, &clientRSAKey.PublicKey, clientRootKey)
   275  	if err != nil {
   276  		t.Fatal(err)
   277  	}
   278  	emit("testClientRSA2048", "RSA 2048 client leaf, SAN=test.golang.example, issued by Client Root.", der, clientRSAKey)
   279  
   280  	clientECDSAKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   281  	if err != nil {
   282  		t.Fatal(err)
   283  	}
   284  	tmpl = clientLeaf("clientAuth ECDSA P-256", "test.golang.example")
   285  	der, err = x509.CreateCertificate(rand.Reader, tmpl, clientRootCert, &clientECDSAKey.PublicKey, clientRootKey)
   286  	if err != nil {
   287  		t.Fatal(err)
   288  	}
   289  	emit("testClientECDSAP256", "ECDSA P-256 client leaf, SAN=test.golang.example, issued by Client Root.", der, clientECDSAKey)
   290  
   291  	clientEd25519Pub, clientEd25519Key, err := ed25519.GenerateKey(rand.Reader)
   292  	if err != nil {
   293  		t.Fatal(err)
   294  	}
   295  	tmpl = clientLeaf("clientAuth Ed25519", "test.golang.example")
   296  	der, err = x509.CreateCertificate(rand.Reader, tmpl, clientRootCert, clientEd25519Pub, clientRootKey)
   297  	if err != nil {
   298  		t.Fatal(err)
   299  	}
   300  	emit("testClientEd25519", "Ed25519 client leaf, SAN=test.golang.example, issued by Client Root.", der, clientEd25519Key)
   301  
   302  	// Client RSA-PSS: signed by client root with SHA512WithRSAPSS. The leaf
   303  	// SPKI is rsaEncryption while the signatureAlgorithm is rsassaPss.
   304  	clientRSAPSSKey, err := rsa.GenerateKey(rand.Reader, 2048)
   305  	if err != nil {
   306  		t.Fatal(err)
   307  	}
   308  	tmpl = clientLeaf("clientAuth RSA-PSS", "test.golang.example")
   309  	tmpl.SignatureAlgorithm = x509.SHA512WithRSAPSS
   310  	der, err = x509.CreateCertificate(rand.Reader, tmpl, clientRootCert, &clientRSAPSSKey.PublicKey, clientRootKey)
   311  	if err != nil {
   312  		t.Fatal(err)
   313  	}
   314  	emit("testClientRSAPSS", "RSA 2048 client leaf, SAN=test.golang.example, issued by Client Root.\n\t// Signature algorithm is SHA512WithRSAPSS (rsaEncryption SPKI, rsassaPss signature).", der, clientRSAPSSKey)
   315  
   316  	// Generate certificates_test.go.
   317  	var buf bytes.Buffer
   318  	fmt.Fprint(&buf, `// Code generated by certificates_generator_test.go; DO NOT EDIT.
   319  // To regenerate, run: go generate
   320  
   321  package tls
   322  
   323  import "crypto/x509"
   324  
   325  `)
   326  
   327  	fmt.Fprint(&buf, `var (
   328  `)
   329  	for _, p := range pairs {
   330  		fmt.Fprintf(&buf, "\t// %s\n", p.comment)
   331  		fmt.Fprintf(&buf, "\t%sCert = parseTestCert(%sCertPEM, %sKeyPEM)\n\n",
   332  			p.name, p.name, p.name)
   333  	}
   334  	fmt.Fprint(&buf, `	// x509.CertPool containing testRootCert.
   335  	testRootCertPool = newTestCertPool(testRootCertPEM)
   336  	// x509.CertPool containing testClientRootCert.
   337  	testClientRootCertPool = newTestCertPool(testClientRootCertPEM)
   338  )
   339  
   340  `)
   341  
   342  	for _, p := range pairs {
   343  		fmt.Fprintf(&buf, "const %sCertPEM = `\n%s`\n\n", p.name, p.certPEM)
   344  		fmt.Fprintf(&buf, "const %sKeyPEM = `\n%s`\n\n", p.name, p.keyPEM)
   345  	}
   346  
   347  	fmt.Fprint(&buf, `func parseTestCert(certPEM, keyPEM string) Certificate {
   348  	tlsCert, err := X509KeyPair([]byte(certPEM), []byte(testingKey(keyPEM)))
   349  	if err != nil {
   350  		panic(err)
   351  	}
   352  	return tlsCert
   353  }
   354  
   355  func newTestCertPool(certPEM string) *x509.CertPool {
   356  	pool := x509.NewCertPool()
   357  	if !pool.AppendCertsFromPEM([]byte(certPEM)) {
   358  		panic("failed to parse certificate for pool")
   359  	}
   360  	return pool
   361  }
   362  `)
   363  
   364  	if *generate {
   365  		if err := os.WriteFile("certificates_test.go", buf.Bytes(), 0644); err != nil {
   366  			t.Fatal(err)
   367  		}
   368  		t.Log("wrote certificates_test.go")
   369  	} else {
   370  		// Check that the generated content matches the existing file.
   371  		existing, err := os.ReadFile("certificates_test.go")
   372  		if err != nil {
   373  			t.Fatal(err)
   374  		}
   375  		if !bytes.Equal(existing, buf.Bytes()) {
   376  			t.Fatal("certificates_test.go is out of date; run go generate to update it")
   377  		}
   378  	}
   379  }
   380  

View as plain text