...

Source file src/github.com/jackc/pgx/v5/testsetup/generate_certs.go

Documentation: github.com/jackc/pgx/v5/testsetup

     1  // Generates a CA, server certificate, and encrypted client certificate for testing pgx.
     2  
     3  package main
     4  
     5  import (
     6  	"crypto/rand"
     7  	"crypto/rsa"
     8  	"crypto/x509"
     9  	"crypto/x509/pkix"
    10  	"encoding/pem"
    11  	"fmt"
    12  	"math/big"
    13  	"net"
    14  	"os"
    15  	"time"
    16  )
    17  
    18  func main() {
    19  	// Create the CA
    20  	ca := &x509.Certificate{
    21  		SerialNumber: big.NewInt(1),
    22  		Subject: pkix.Name{
    23  			CommonName: "pgx-root-ca",
    24  		},
    25  		NotBefore:             time.Now(),
    26  		NotAfter:              time.Now().AddDate(20, 0, 0),
    27  		IsCA:                  true,
    28  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
    29  		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
    30  		BasicConstraintsValid: true,
    31  	}
    32  
    33  	caKey, err := rsa.GenerateKey(rand.Reader, 4096)
    34  	if err != nil {
    35  		panic(err)
    36  	}
    37  
    38  	caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caKey.PublicKey, caKey)
    39  	if err != nil {
    40  		panic(err)
    41  	}
    42  
    43  	err = writePrivateKey("ca.key", caKey)
    44  	if err != nil {
    45  		panic(err)
    46  	}
    47  
    48  	err = writeCertificate("ca.pem", caBytes)
    49  	if err != nil {
    50  		panic(err)
    51  	}
    52  
    53  	// Create a server certificate signed by the CA for localhost.
    54  	serverCert := &x509.Certificate{
    55  		SerialNumber: big.NewInt(2),
    56  		Subject: pkix.Name{
    57  			CommonName: "localhost",
    58  		},
    59  		DNSNames:    []string{"localhost"},
    60  		IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback},
    61  		NotBefore:   time.Now(),
    62  		NotAfter:    time.Now().AddDate(20, 0, 0),
    63  		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
    64  		KeyUsage:    x509.KeyUsageDigitalSignature,
    65  	}
    66  
    67  	serverCertPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
    68  	if err != nil {
    69  		panic(err)
    70  	}
    71  
    72  	serverBytes, err := x509.CreateCertificate(rand.Reader, serverCert, ca, &serverCertPrivKey.PublicKey, caKey)
    73  	if err != nil {
    74  		panic(err)
    75  	}
    76  
    77  	err = writePrivateKey("localhost.key", serverCertPrivKey)
    78  	if err != nil {
    79  		panic(err)
    80  	}
    81  
    82  	err = writeCertificate("localhost.crt", serverBytes)
    83  	if err != nil {
    84  		panic(err)
    85  	}
    86  
    87  	// Create a client certificate signed by the CA and encrypted.
    88  	clientCert := &x509.Certificate{
    89  		SerialNumber: big.NewInt(3),
    90  		Subject: pkix.Name{
    91  			CommonName: "pgx_sslcert",
    92  		},
    93  		NotBefore:   time.Now(),
    94  		NotAfter:    time.Now().AddDate(20, 0, 0),
    95  		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
    96  		KeyUsage:    x509.KeyUsageDigitalSignature,
    97  	}
    98  
    99  	clientCertPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
   100  	if err != nil {
   101  		panic(err)
   102  	}
   103  
   104  	clientBytes, err := x509.CreateCertificate(rand.Reader, clientCert, ca, &clientCertPrivKey.PublicKey, caKey)
   105  	if err != nil {
   106  		panic(err)
   107  	}
   108  
   109  	writeEncryptedPrivateKey("pgx_sslcert.key", clientCertPrivKey, "certpw")
   110  	if err != nil {
   111  		panic(err)
   112  	}
   113  
   114  	writeCertificate("pgx_sslcert.crt", clientBytes)
   115  	if err != nil {
   116  		panic(err)
   117  	}
   118  }
   119  
   120  func writePrivateKey(path string, privateKey *rsa.PrivateKey) error {
   121  	file, err := os.Create(path)
   122  	if err != nil {
   123  		return fmt.Errorf("writePrivateKey: %w", err)
   124  	}
   125  
   126  	err = pem.Encode(file, &pem.Block{
   127  		Type:  "RSA PRIVATE KEY",
   128  		Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
   129  	})
   130  	if err != nil {
   131  		return fmt.Errorf("writePrivateKey: %w", err)
   132  	}
   133  
   134  	err = file.Close()
   135  	if err != nil {
   136  		return fmt.Errorf("writePrivateKey: %w", err)
   137  	}
   138  
   139  	return nil
   140  }
   141  
   142  func writeEncryptedPrivateKey(path string, privateKey *rsa.PrivateKey, password string) error {
   143  	file, err := os.Create(path)
   144  	if err != nil {
   145  		return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
   146  	}
   147  
   148  	block, err := x509.EncryptPEMBlock(rand.Reader, "CERTIFICATE", x509.MarshalPKCS1PrivateKey(privateKey), []byte(password), x509.PEMCipher3DES)
   149  	if err != nil {
   150  		return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
   151  	}
   152  
   153  	err = pem.Encode(file, block)
   154  	if err != nil {
   155  		return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
   156  	}
   157  
   158  	err = file.Close()
   159  	if err != nil {
   160  		return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
   161  	}
   162  
   163  	return nil
   164  
   165  }
   166  
   167  func writeCertificate(path string, certBytes []byte) error {
   168  	file, err := os.Create(path)
   169  	if err != nil {
   170  		return fmt.Errorf("writeCertificate: %w", err)
   171  	}
   172  
   173  	err = pem.Encode(file, &pem.Block{
   174  		Type:  "CERTIFICATE",
   175  		Bytes: certBytes,
   176  	})
   177  	if err != nil {
   178  		return fmt.Errorf("writeCertificate: %w", err)
   179  	}
   180  
   181  	err = file.Close()
   182  	if err != nil {
   183  		return fmt.Errorf("writeCertificate: %w", err)
   184  	}
   185  
   186  	return nil
   187  }
   188  

View as plain text