pgx/testsetup/generate_certs.go

188 lines
4.2 KiB
Go

// Generates a CA, server certificate, and encrypted client certificate for testing pgx.
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net"
"os"
"time"
)
func main() {
// Create the CA
ca := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "pgx-root-ca",
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(20, 0, 0),
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}
caKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
panic(err)
}
caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caKey.PublicKey, caKey)
if err != nil {
panic(err)
}
err = writePrivateKey("ca.key", caKey)
if err != nil {
panic(err)
}
err = writeCertificate("ca.pem", caBytes)
if err != nil {
panic(err)
}
// Create a server certificate signed by the CA for localhost.
serverCert := &x509.Certificate{
SerialNumber: big.NewInt(2),
Subject: pkix.Name{
CommonName: "localhost",
},
DNSNames: []string{"localhost"},
IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(20, 0, 0),
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
}
serverCertPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
serverBytes, err := x509.CreateCertificate(rand.Reader, serverCert, ca, &serverCertPrivKey.PublicKey, caKey)
if err != nil {
panic(err)
}
err = writePrivateKey("localhost.key", serverCertPrivKey)
if err != nil {
panic(err)
}
err = writeCertificate("localhost.crt", serverBytes)
if err != nil {
panic(err)
}
// Create a client certificate signed by the CA and encrypted.
clientCert := &x509.Certificate{
SerialNumber: big.NewInt(3),
Subject: pkix.Name{
CommonName: "pgx_sslcert",
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(20, 0, 0),
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
}
clientCertPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
clientBytes, err := x509.CreateCertificate(rand.Reader, clientCert, ca, &clientCertPrivKey.PublicKey, caKey)
if err != nil {
panic(err)
}
err = writeEncryptedPrivateKey("pgx_sslcert.key", clientCertPrivKey, "certpw")
if err != nil {
panic(err)
}
err = writeCertificate("pgx_sslcert.crt", clientBytes)
if err != nil {
panic(err)
}
}
func writePrivateKey(path string, privateKey *rsa.PrivateKey) error {
file, err := os.Create(path)
if err != nil {
return fmt.Errorf("writePrivateKey: %w", err)
}
err = pem.Encode(file, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
})
if err != nil {
return fmt.Errorf("writePrivateKey: %w", err)
}
err = file.Close()
if err != nil {
return fmt.Errorf("writePrivateKey: %w", err)
}
return nil
}
func writeEncryptedPrivateKey(path string, privateKey *rsa.PrivateKey, password string) error {
file, err := os.Create(path)
if err != nil {
return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
}
block, err := x509.EncryptPEMBlock(rand.Reader, "CERTIFICATE", x509.MarshalPKCS1PrivateKey(privateKey), []byte(password), x509.PEMCipher3DES)
if err != nil {
return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
}
err = pem.Encode(file, block)
if err != nil {
return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
}
err = file.Close()
if err != nil {
return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
}
return nil
}
func writeCertificate(path string, certBytes []byte) error {
file, err := os.Create(path)
if err != nil {
return fmt.Errorf("writeCertificate: %w", err)
}
err = pem.Encode(file, &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
})
if err != nil {
return fmt.Errorf("writeCertificate: %w", err)
}
err = file.Close()
if err != nil {
return fmt.Errorf("writeCertificate: %w", err)
}
return nil
}