Skip to content
Snippets Groups Projects
selfsigned.go 1.71 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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
    	}
    }