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