crypto/tls: Support ECDSA keys in generate_cert.go

R=golang-codereviews, bradfitz, agl
CC=golang-codereviews
https://golang.org/cl/117180043
This commit is contained in:
Asim Shankar 2014-07-28 14:46:34 -07:00 committed by Adam Langley
parent 601d9250e6
commit cf213d5c40

View File

@ -10,6 +10,8 @@
package main package main
import ( import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
@ -30,9 +32,37 @@ var (
validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") 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") 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") 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") 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() { func main() {
flag.Parse() flag.Parse()
@ -40,7 +70,23 @@ func main() {
log.Fatalf("Missing required --host parameter") 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 { if err != nil {
log.Fatalf("failed to generate private key: %s", err) log.Fatalf("failed to generate private key: %s", err)
} }
@ -91,7 +137,7 @@ func main() {
template.KeyUsage |= x509.KeyUsageCertSign 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 { if err != nil {
log.Fatalf("Failed to create certificate: %s", err) log.Fatalf("Failed to create certificate: %s", err)
} }
@ -109,7 +155,7 @@ func main() {
log.Print("failed to open key.pem for writing:", err) log.Print("failed to open key.pem for writing:", err)
return return
} }
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) pem.Encode(keyOut, pemBlockForKey(priv))
keyOut.Close() keyOut.Close()
log.Print("written key.pem\n") log.Print("written key.pem\n")
} }