Skip to content
Snippets Groups Projects
selfsigned.go 1.71 KiB
Newer Older
ale's avatar
ale committed
package acmeserver

import (
	"context"
	"crypto"
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"log"
	"math/big"
	"time"
)

type selfSignedGenerator struct{}

// NewSelfSignedCertGenerator returns a CertGenerator that will create
// self-signed certificates for every request. Primarily useful for
// testing acmeserver as a functional component in integration tests.
func NewSelfSignedCertGenerator() CertGenerator {
	return &selfSignedGenerator{}
}

func (g *selfSignedGenerator) GetCertificate(_ context.Context, priv crypto.Signer, c *certConfig) ([][]byte, *x509.Certificate, error) {
	notBefore := time.Now()
	notAfter := notBefore.AddDate(1, 0, 0)

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return nil, nil, err
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			CommonName: c.Names[0],
		},
		DNSNames:  c.Names,
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	der, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
	if err != nil {
		return nil, nil, err
	}

	cert, err := x509.ParseCertificate(der)
	if err != nil {
		return nil, nil, err
	}

	log.Printf("created certificate for %s", c.Names[0])

	return [][]byte{der}, cert, nil
}

func publicKey(priv interface{}) interface{} {
	switch k := priv.(type) {
	case *rsa.PrivateKey:
		return &k.PublicKey
	case *ecdsa.PrivateKey:
		return &k.PublicKey
	default:
		return nil
	}
}