mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-17 14:37:02 +00:00
test: Use our own generate_cert helper
The current generate_cert helper was originally taken from Go's source, and is more complex than we need it to be. This patch replaces it with our own version, rewritten from scratch independently.
This commit is contained in:
@@ -1,26 +1,21 @@
|
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !coverage
|
//go:build !coverage
|
||||||
// +build !coverage
|
// +build !coverage
|
||||||
|
|
||||||
// Generate a self-signed X.509 certificate for a TLS server. Outputs to
|
// Utility to generate self-signed certificates.
|
||||||
// 'cert.pem' and 'key.pem' and will overwrite existing files.
|
// It generates a self-signed x509 certificate and key pair, and writes them
|
||||||
|
// to "fullchain.pem" and "privkey.pem".
|
||||||
|
//
|
||||||
|
// Intended for use in tests, not for production use.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
crand "crypto/rand"
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
@@ -31,138 +26,104 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
|
host = flag.String("host", "",
|
||||||
validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
|
"Hostnames/IPs to generate the certificate for (comma separated)")
|
||||||
validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
|
validFor = flag.Duration("validfor", 4*time.Hour,
|
||||||
isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
|
"How long will the certificate be valid for")
|
||||||
rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set")
|
isCA = flag.Bool("ca", false,
|
||||||
ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521")
|
"Should this cert be its own CA?")
|
||||||
)
|
)
|
||||||
|
|
||||||
func publicKey(priv interface{}) interface{} {
|
func fatalf(f string, a ...interface{}) {
|
||||||
switch k := priv.(type) {
|
fmt.Printf(f, a...)
|
||||||
case *rsa.PrivateKey:
|
os.Exit(1)
|
||||||
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()
|
||||||
|
if *host == "" {
|
||||||
if len(*host) == 0 {
|
fatalf("Required flag: --host")
|
||||||
log.Fatalf("Missing required --host parameter")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var priv interface{}
|
// Build the certificate template.
|
||||||
var err error
|
serial, err := crand.Int(crand.Reader, big.NewInt(1<<62))
|
||||||
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)
|
fatalf("Error generating serial number: %v\n", err)
|
||||||
}
|
}
|
||||||
|
tmpl := x509.Certificate{
|
||||||
|
SerialNumber: serial,
|
||||||
|
Subject: pkix.Name{Organization: []string{"Test Cert Org"}},
|
||||||
|
|
||||||
var notBefore time.Time
|
// Valid from now until `--validfor` in the future.
|
||||||
if len(*validFrom) == 0 {
|
// Extended certs can be useful for manual troubleshooting.
|
||||||
notBefore = time.Now()
|
NotBefore: time.Now(),
|
||||||
} else {
|
NotAfter: time.Now().Add(*validFor),
|
||||||
notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notAfter := notBefore.Add(*validFor)
|
KeyUsage: x509.KeyUsageKeyEncipherment |
|
||||||
|
x509.KeyUsageDigitalSignature |
|
||||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
x509.KeyUsageCertSign,
|
||||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to generate serial number: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
template := x509.Certificate{
|
|
||||||
SerialNumber: serialNumber,
|
|
||||||
Subject: pkix.Name{
|
|
||||||
Organization: []string{"Acme Co"},
|
|
||||||
},
|
|
||||||
NotBefore: notBefore,
|
|
||||||
NotAfter: notAfter,
|
|
||||||
|
|
||||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
|
||||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||||
|
|
||||||
BasicConstraintsValid: true,
|
BasicConstraintsValid: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *isCA {
|
||||||
|
tmpl.IsCA = true
|
||||||
|
}
|
||||||
|
|
||||||
hosts := strings.Split(*host, ",")
|
hosts := strings.Split(*host, ",")
|
||||||
for _, h := range hosts {
|
for _, h := range hosts {
|
||||||
if ip := net.ParseIP(h); ip != nil {
|
if ip := net.ParseIP(h); ip != nil {
|
||||||
template.IPAddresses = append(template.IPAddresses, ip)
|
tmpl.IPAddresses = append(tmpl.IPAddresses, ip)
|
||||||
} else {
|
} else {
|
||||||
// We use IDNA-encoded DNS names, otherwise the TLS library won't
|
// We use IDNA-encoded DNS names, otherwise the TLS library won't
|
||||||
// load the certificates.
|
// load the certificates.
|
||||||
ih, err := idna.ToASCII(h)
|
ih, err := idna.ToASCII(h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("host %q cannot be IDNA-encoded: %v", h, err)
|
fatalf("Host %q cannot be IDNA-encoded: %v\n", h, err)
|
||||||
}
|
}
|
||||||
template.DNSNames = append(template.DNSNames, ih)
|
tmpl.DNSNames = append(tmpl.DNSNames, ih)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if *isCA {
|
// Generate a private key (RSA 2048).
|
||||||
template.IsCA = true
|
privK, err := rsa.GenerateKey(crand.Reader, 2048)
|
||||||
template.KeyUsage |= x509.KeyUsageCertSign
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
fatalf("Error generating key: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
certOut, err := os.Create("fullchain.pem")
|
// Write the certificate.
|
||||||
|
{
|
||||||
|
derBytes, err := x509.CreateCertificate(
|
||||||
|
crand.Reader, &tmpl, &tmpl, &privK.PublicKey, privK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to open fullchain.pem for writing: %s", err)
|
fatalf("Failed to create certificate: %v\n", err)
|
||||||
}
|
}
|
||||||
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
|
||||||
certOut.Close()
|
|
||||||
|
|
||||||
keyOut, err := os.OpenFile("privkey.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
fullchain, err := os.Create("fullchain.pem")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to open privkey.pem for writing: %s", err)
|
fatalf("Failed to open fullchain.pem: %v\n", err)
|
||||||
return
|
}
|
||||||
|
err = pem.Encode(fullchain,
|
||||||
|
&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||||
|
if err != nil {
|
||||||
|
fatalf("Error encoding certificate: %v\n", err)
|
||||||
|
}
|
||||||
|
fullchain.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the private key.
|
||||||
|
{
|
||||||
|
privkey, err := os.Create("privkey.pem")
|
||||||
|
if err != nil {
|
||||||
|
fatalf("failed to open privkey.pem: %v\n", err)
|
||||||
|
}
|
||||||
|
block := &pem.Block{Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: x509.MarshalPKCS1PrivateKey(privK)}
|
||||||
|
err = pem.Encode(privkey, block)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("Error encoding private key: %v\n", err)
|
||||||
|
}
|
||||||
|
privkey.Close()
|
||||||
}
|
}
|
||||||
pem.Encode(keyOut, pemBlockForKey(priv))
|
|
||||||
keyOut.Close()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ function generate_certs_for() {
|
|||||||
mkdir -p ${CONFDIR}/certs/${1}/
|
mkdir -p ${CONFDIR}/certs/${1}/
|
||||||
(
|
(
|
||||||
cd ${CONFDIR}/certs/${1}
|
cd ${CONFDIR}/certs/${1}
|
||||||
generate_cert -ca -duration=1h -host=${1}
|
generate_cert -ca -validfor=1h -host=${1}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user