...
Run Format

Source file src/crypto/tls/generate_cert.go

     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	
    10	package main
    11	
    12	import (
    13		"crypto/ecdsa"
    14		"crypto/elliptic"
    15		"crypto/rand"
    16		"crypto/rsa"
    17		"crypto/x509"
    18		"crypto/x509/pkix"
    19		"encoding/pem"
    20		"flag"
    21		"fmt"
    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, P384, P521")
    37	)
    38	
    39	func publicKey(priv interface{}) interface{} {
    40		switch k := priv.(type) {
    41		case *rsa.PrivateKey:
    42			return &k.PublicKey
    43		case *ecdsa.PrivateKey:
    44			return &k.PublicKey
    45		default:
    46			return nil
    47		}
    48	}
    49	
    50	func pemBlockForKey(priv interface{}) *pem.Block {
    51		switch k := priv.(type) {
    52		case *rsa.PrivateKey:
    53			return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
    54		case *ecdsa.PrivateKey:
    55			b, err := x509.MarshalECPrivateKey(k)
    56			if err != nil {
    57				fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
    58				os.Exit(2)
    59			}
    60			return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
    61		default:
    62			return nil
    63		}
    64	}
    65	
    66	func main() {
    67		flag.Parse()
    68	
    69		if len(*host) == 0 {
    70			log.Fatalf("Missing required --host parameter")
    71		}
    72	
    73		var priv interface{}
    74		var err error
    75		switch *ecdsaCurve {
    76		case "":
    77			priv, err = rsa.GenerateKey(rand.Reader, *rsaBits)
    78		case "P224":
    79			priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
    80		case "P256":
    81			priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    82		case "P384":
    83			priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
    84		case "P521":
    85			priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
    86		default:
    87			fmt.Fprintf(os.Stderr, "Unrecognized elliptic curve: %q", *ecdsaCurve)
    88			os.Exit(1)
    89		}
    90		if err != nil {
    91			log.Fatalf("failed to generate private key: %s", err)
    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				fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err)
   101				os.Exit(1)
   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: %s", 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:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
   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: %s", err)
   143		}
   144	
   145		certOut, err := os.Create("cert.pem")
   146		if err != nil {
   147			log.Fatalf("failed to open cert.pem for writing: %s", err)
   148		}
   149		pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
   150		certOut.Close()
   151		log.Print("written cert.pem\n")
   152	
   153		keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
   154		if err != nil {
   155			log.Print("failed to open key.pem for writing:", err)
   156			return
   157		}
   158		pem.Encode(keyOut, pemBlockForKey(priv))
   159		keyOut.Close()
   160		log.Print("written key.pem\n")
   161	}
   162	

View as plain text