1// Copyright 2009 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// +build ignore 6 7// Generate a self-signed X.509 certificate for a TLS server. Outputs to 8// 'cert.pem' and 'key.pem' and will overwrite existing files. 9 10package main 11 12import ( 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 30var ( 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 40func 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 53func 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: %v", err) 82 } 83 84 // ECDSA, ED25519 and RSA subject keys should have the DigitalSignature 85 // KeyUsage bits set in the x509.Certificate template 86 keyUsage := x509.KeyUsageDigitalSignature 87 // Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In 88 // the context of TLS this KeyUsage is particular to RSA key exchange and 89 // authentication. 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 return 160 } 161 privBytes, err := x509.MarshalPKCS8PrivateKey(priv) 162 if err != nil { 163 log.Fatalf("Unable to marshal private key: %v", err) 164 } 165 if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil { 166 log.Fatalf("Failed to write data to key.pem: %v", err) 167 } 168 if err := keyOut.Close(); err != nil { 169 log.Fatalf("Error closing key.pem: %v", err) 170 } 171 log.Print("wrote key.pem\n") 172} 173