1
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
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
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
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