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 interface{}) interface{} {
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 interface{}
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: %s", err)
82 }
83
84 var notBefore time.Time
85 if len(*validFrom) == 0 {
86 notBefore = time.Now()
87 } else {
88 notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
89 if err != nil {
90 log.Fatalf("Failed to parse creation date: %s", err)
91 }
92 }
93
94 notAfter := notBefore.Add(*validFor)
95
96 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
97 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
98 if err != nil {
99 log.Fatalf("Failed to generate serial number: %s", err)
100 }
101
102 template := x509.Certificate{
103 SerialNumber: serialNumber,
104 Subject: pkix.Name{
105 Organization: []string{"Acme Co"},
106 },
107 NotBefore: notBefore,
108 NotAfter: notAfter,
109
110 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
111 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
112 BasicConstraintsValid: true,
113 }
114
115 hosts := strings.Split(*host, ",")
116 for _, h := range hosts {
117 if ip := net.ParseIP(h); ip != nil {
118 template.IPAddresses = append(template.IPAddresses, ip)
119 } else {
120 template.DNSNames = append(template.DNSNames, h)
121 }
122 }
123
124 if *isCA {
125 template.IsCA = true
126 template.KeyUsage |= x509.KeyUsageCertSign
127 }
128
129 derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
130 if err != nil {
131 log.Fatalf("Failed to create certificate: %s", err)
132 }
133
134 certOut, err := os.Create("cert.pem")
135 if err != nil {
136 log.Fatalf("Failed to open cert.pem for writing: %s", err)
137 }
138 if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
139 log.Fatalf("Failed to write data to cert.pem: %s", err)
140 }
141 if err := certOut.Close(); err != nil {
142 log.Fatalf("Error closing cert.pem: %s", err)
143 }
144 log.Print("wrote cert.pem\n")
145
146 keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
147 if err != nil {
148 log.Fatalf("Failed to open key.pem for writing:", err)
149 return
150 }
151 privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
152 if err != nil {
153 log.Fatalf("Unable to marshal private key: %v", err)
154 }
155 if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil {
156 log.Fatalf("Failed to write data to key.pem: %s", err)
157 }
158 if err := keyOut.Close(); err != nil {
159 log.Fatalf("Error closing key.pem: %s", err)
160 }
161 log.Print("wrote key.pem\n")
162 }
163
View as plain text