diff --git a/README.md b/README.md index 5903738..846528b 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,9 @@ mkcert supports the following root stores: -cert-file FILE, -key-file FILE, -p12-file FILE Customize the output paths. + -ecdsa + Generate a certificate with an ECDSA key. + -pkcs12 Generate a ".p12" PKCS #12 file, also know as a ".pfx" file, containing certificate and key for legacy applications. diff --git a/cert.go b/cert.go index 9741cf8..a4c7591 100644 --- a/cert.go +++ b/cert.go @@ -5,6 +5,9 @@ package main import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" "crypto/rand" "crypto/rsa" "crypto/sha1" @@ -44,8 +47,9 @@ func (m *mkcert) makeCert(hosts []string) { log.Fatalln("ERROR: can't create new certificates because the CA key (rootCA-key.pem) is missing") } - priv, err := rsa.GenerateKey(rand.Reader, 2048) + priv, err := m.generateKey(false) fatalIfErr(err, "failed to generate certificate key") + pub := priv.(crypto.Signer).Public() serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) @@ -79,8 +83,7 @@ func (m *mkcert) makeCert(hosts []string) { tpl.Subject.CommonName = hosts[0] } - pub := priv.PublicKey - cert, err := x509.CreateCertificate(rand.Reader, tpl, m.caCert, &pub, m.caKey) + cert, err := x509.CreateCertificate(rand.Reader, tpl, m.caCert, pub, m.caKey) fatalIfErr(err, "failed to generate certificate") certFile, keyFile, p12File := m.fileNames(hosts) @@ -127,6 +130,16 @@ func (m *mkcert) makeCert(hosts []string) { } } +func (m *mkcert) generateKey(rootCA bool) (crypto.PrivateKey, error) { + if m.ecdsa { + return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + } + if rootCA { + return rsa.GenerateKey(rand.Reader, 3072) + } + return rsa.GenerateKey(rand.Reader, 2048) +} + func (m *mkcert) fileNames(hosts []string) (certFile, keyFile, p12File string) { defaultName := strings.Replace(hosts[0], ":", "_", -1) defaultName = strings.Replace(defaultName, "*", "_wildcard", -1) @@ -182,15 +195,15 @@ func (m *mkcert) loadCA() { } func (m *mkcert) newCA() { - priv, err := rsa.GenerateKey(rand.Reader, 3072) + priv, err := m.generateKey(true) fatalIfErr(err, "failed to generate the CA key") - pub := priv.PublicKey + pub := priv.(crypto.Signer).Public() serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) fatalIfErr(err, "failed to generate serial number") - spkiASN1, err := x509.MarshalPKIXPublicKey(&pub) + spkiASN1, err := x509.MarshalPKIXPublicKey(pub) fatalIfErr(err, "failed to encode public key") var spki struct { @@ -225,7 +238,7 @@ func (m *mkcert) newCA() { MaxPathLenZero: true, } - cert, err := x509.CreateCertificate(rand.Reader, tpl, tpl, &pub, priv) + cert, err := x509.CreateCertificate(rand.Reader, tpl, tpl, pub, priv) fatalIfErr(err, "failed to generate CA certificate") privDER, err := x509.MarshalPKCS8PrivateKey(priv) diff --git a/main.go b/main.go index 98a146f..1e6f48f 100644 --- a/main.go +++ b/main.go @@ -44,6 +44,9 @@ const advancedUsage = `Advanced options: -cert-file FILE, -key-file FILE, -p12-file FILE Customize the output paths. + -ecdsa + Generate a certificate with an ECDSA key. + -pkcs12 Generate a ".p12" PKCS #12 file, also know as a ".pfx" file, containing certificate and key for legacy applications. @@ -63,6 +66,7 @@ func main() { installFlag = flag.Bool("install", false, "") uninstallFlag = flag.Bool("uninstall", false, "") pkcs12Flag = flag.Bool("pkcs12", false, "") + ecdsaFlag = flag.Bool("ecdsa", false, "") helpFlag = flag.Bool("help", false, "") carootFlag = flag.Bool("CAROOT", false, "") certFileFlag = flag.String("cert-file", "", "") @@ -90,7 +94,8 @@ func main() { log.Fatalln("ERROR: you can't set -install and -uninstall at the same time") } (&mkcert{ - installMode: *installFlag, uninstallMode: *uninstallFlag, pkcs12: *pkcs12Flag, + installMode: *installFlag, uninstallMode: *uninstallFlag, + pkcs12: *pkcs12Flag, ecdsa: *ecdsaFlag, certFile: *certFileFlag, keyFile: *keyFileFlag, p12File: *p12FileFlag, }).Run(flag.Args()) } @@ -100,7 +105,7 @@ const rootKeyName = "rootCA-key.pem" type mkcert struct { installMode, uninstallMode bool - pkcs12 bool + pkcs12, ecdsa bool keyFile, certFile, p12File string CAROOT string