Source file
src/crypto/tls/generate_cert.go
1
2
3
4
5
6
7
8
9
10 package main
11
12 import (
13 "crypto/ecdsa"
14 "crypto/ed25519"
15 "crypto/elliptic"
16 "crypto/rand"
17 "crypto/rsa"
18 "crypto/x509"
19 "crypto/x509/pkix"
20 "encoding/pem"
21 "flag"
22 "log"
23 "math/big"
24 "net"
25 "os"
26 "strings"
27 "time"
28 )
29
30 var (
31 host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
32 validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
33 validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
34 isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
35 rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set")
36 ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521")
37 ed25519Key = flag.Bool("ed25519", false, "Generate an Ed25519 key")
38 )
39
40 func publicKey(priv any) any {
41 switch k := priv.(type) {
42 case *rsa.PrivateKey:
43 return &k.PublicKey
44 case *ecdsa.PrivateKey:
45 return &k.PublicKey
46 case ed25519.PrivateKey:
47 return k.Public().(ed25519.PublicKey)
48 default:
49 return nil
50 }
51 }
52
53 func main() {
54 flag.Parse()
55
56 if len(*host) == 0 {
57 log.Fatalf("Missing required --host parameter")
58 }
59
60 var priv any
61 var err error
62 switch *ecdsaCurve {
63 case "":
64 if *ed25519Key {
65 _, priv, err = ed25519.GenerateKey(rand.Reader)
66 } else {
67 priv, err = rsa.GenerateKey(rand.Reader, *rsaBits)
68 }
69 case "P224":
70 priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
71 case "P256":
72 priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
73 case "P384":
74 priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
75 case "P521":
76 priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
77 default:
78 log.Fatalf("Unrecognized elliptic curve: %q", *ecdsaCurve)
79 }
80 if err != nil {
81 log.Fatalf("Failed to generate private key: %v", err)
82 }
83
84
85
86 keyUsage := x509.KeyUsageDigitalSignature
87
88
89
90 if _, isRSA := priv.(*rsa.PrivateKey); isRSA {
91 keyUsage |= x509.KeyUsageKeyEncipherment
92 }
93
94 var notBefore time.Time
95 if len(*validFrom) == 0 {
96 notBefore = time.Now()
97 } else {
98 notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
99 if err != nil {
100 log.Fatalf("Failed to parse creation date: %v", err)
101 }
102 }
103
104 notAfter := notBefore.Add(*validFor)
105
106 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
107 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
108 if err != nil {
109 log.Fatalf("Failed to generate serial number: %v", err)
110 }
111
112 template := x509.Certificate{
113 SerialNumber: serialNumber,
114 Subject: pkix.Name{
115 Organization: []string{"Acme Co"},
116 },
117 NotBefore: notBefore,
118 NotAfter: notAfter,
119
120 KeyUsage: keyUsage,
121 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
122 BasicConstraintsValid: true,
123 }
124
125 hosts := strings.Split(*host, ",")
126 for _, h := range hosts {
127 if ip := net.ParseIP(h); ip != nil {
128 template.IPAddresses = append(template.IPAddresses, ip)
129 } else {
130 template.DNSNames = append(template.DNSNames, h)
131 }
132 }
133
134 if *isCA {
135 template.IsCA = true
136 template.KeyUsage |= x509.KeyUsageCertSign
137 }
138
139 derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
140 if err != nil {
141 log.Fatalf("Failed to create certificate: %v", err)
142 }
143
144 certOut, err := os.Create("cert.pem")
145 if err != nil {
146 log.Fatalf("Failed to open cert.pem for writing: %v", err)
147 }
148 if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
149 log.Fatalf("Failed to write data to cert.pem: %v", err)
150 }
151 if err := certOut.Close(); err != nil {
152 log.Fatalf("Error closing cert.pem: %v", err)
153 }
154 log.Print("wrote cert.pem\n")
155
156 keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
157 if err != nil {
158 log.Fatalf("Failed to open key.pem for writing: %v", err)
159 }
160 privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
161 if err != nil {
162 log.Fatalf("Unable to marshal private key: %v", err)
163 }
164 if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil {
165 log.Fatalf("Failed to write data to key.pem: %v", err)
166 }
167 if err := keyOut.Close(); err != nil {
168 log.Fatalf("Error closing key.pem: %v", err)
169 }
170 log.Print("wrote key.pem\n")
171 }
172
View as plain text