package certs import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "math/big" "net" "strings" "time" log "github.com/sirupsen/logrus" ) // GenerateCerts venerates a ca with a leaf certificate and key and returns the ca, cert and key as PEM encoded slices func GenerateCerts(host string) (ca []byte, cert []byte, key []byte) { notBefore := time.Now().Add(time.Minute * -5) notAfter := notBefore.Add(100 * 365 * 24 * time.Hour) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { log.WithField("err", err).Fatal("failed to generate serial number") } rootKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { log.WithField("err", err).Fatal("failed scdsa.GenerateKey") } rootTemplate := x509.Certificate{ SerialNumber: serialNumber, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageCertSign, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, IsCA: true, Subject: pkix.Name{Organization: []string{"nil1"}}, } derBytes, err := x509.CreateCertificate(rand.Reader, &rootTemplate, &rootTemplate, &rootKey.PublicKey, rootKey) if err != nil { log.WithField("err", err).Fatal("failed createCertificate for Ca") } ca = encodeCert(derBytes) leafKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { log.WithField("err", err).Fatal("failed createLeafKey for certificate") } key = encodeKey(leafKey) serialNumber, err = rand.Int(rand.Reader, serialNumberLimit) if err != nil { log.WithField("err", err).Fatal("failed to generate serial number") } leafTemplate := x509.Certificate{ SerialNumber: serialNumber, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, IsCA: false, Subject: pkix.Name{Organization: []string{"nil2"}}, } hosts := strings.Split(host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { leafTemplate.IPAddresses = append(leafTemplate.IPAddresses, ip) } else { leafTemplate.DNSNames = append(leafTemplate.DNSNames, h) } } derBytes, err = x509.CreateCertificate(rand.Reader, &leafTemplate, &rootTemplate, &leafKey.PublicKey, rootKey) if err != nil { log.WithField("err", err).Fatal("failed createLeaf certificate") } cert = encodeCert(derBytes) return ca, cert, key } func encodeKey(key *ecdsa.PrivateKey) []byte { b, err := x509.MarshalECPrivateKey(key) if err != nil { log.WithField("err", err).Fatal("unable to marshal ECDSA private key") } return pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: b}) } func encodeCert(derBytes []byte) []byte { return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) }