]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/tls: Support ECDSA keys in generate_cert.go
authorAsim Shankar <asimshankar@gmail.com>
Mon, 28 Jul 2014 21:46:34 +0000 (14:46 -0700)
committerAdam Langley <agl@golang.org>
Mon, 28 Jul 2014 21:46:34 +0000 (14:46 -0700)
R=golang-codereviews, bradfitz, agl
CC=golang-codereviews
https://golang.org/cl/117180043

src/pkg/crypto/tls/generate_cert.go

index 5c6d8396d5208ea7a998718b2f154d3e688291b0..83f9916ff9d937e1eefcd30e0de6d95a3d5a8c42 100644 (file)
@@ -10,6 +10,8 @@
 package main
 
 import (
+       "crypto/ecdsa"
+       "crypto/elliptic"
        "crypto/rand"
        "crypto/rsa"
        "crypto/x509"
@@ -26,13 +28,41 @@ import (
 )
 
 var (
-       host      = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
-       validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
-       validFor  = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
-       isCA      = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
-       rsaBits   = flag.Int("rsa-bits", 2048, "Size of RSA key to generate")
+       host       = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
+       validFrom  = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
+       validFor   = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
+       isCA       = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
+       rsaBits    = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set")
+       ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521")
 )
 
+func publicKey(priv interface{}) interface{} {
+       switch k := priv.(type) {
+       case *rsa.PrivateKey:
+               return &k.PublicKey
+       case *ecdsa.PrivateKey:
+               return &k.PublicKey
+       default:
+               return nil
+       }
+}
+
+func pemBlockForKey(priv interface{}) *pem.Block {
+       switch k := priv.(type) {
+       case *rsa.PrivateKey:
+               return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
+       case *ecdsa.PrivateKey:
+               b, err := x509.MarshalECPrivateKey(k)
+               if err != nil {
+                       fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
+                       os.Exit(2)
+               }
+               return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
+       default:
+               return nil
+       }
+}
+
 func main() {
        flag.Parse()
 
@@ -40,7 +70,23 @@ func main() {
                log.Fatalf("Missing required --host parameter")
        }
 
-       priv, err := rsa.GenerateKey(rand.Reader, *rsaBits)
+       var priv interface{}
+       var err error
+       switch *ecdsaCurve {
+       case "":
+               priv, err = rsa.GenerateKey(rand.Reader, *rsaBits)
+       case "P224":
+               priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
+       case "P256":
+               priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+       case "P384":
+               priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
+       case "P521":
+               priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
+       default:
+               fmt.Fprintf(os.Stderr, "Unrecognized elliptic curve: %q", *ecdsaCurve)
+               os.Exit(1)
+       }
        if err != nil {
                log.Fatalf("failed to generate private key: %s", err)
        }
@@ -91,7 +137,7 @@ func main() {
                template.KeyUsage |= x509.KeyUsageCertSign
        }
 
-       derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
+       derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
        if err != nil {
                log.Fatalf("Failed to create certificate: %s", err)
        }
@@ -109,7 +155,7 @@ func main() {
                log.Print("failed to open key.pem for writing:", err)
                return
        }
-       pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
+       pem.Encode(keyOut, pemBlockForKey(priv))
        keyOut.Close()
        log.Print("written key.pem\n")
 }