certgen/ca.go

63 lines
1.7 KiB
Go

package certgen
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"math/big"
"time"
)
// MakeCaTls generates a CA TLS certificate
func MakeCaTls(bits int, name pkix.Name, serialNumber *big.Int, future Future) (*CertGen, error) {
// base certificate data
now := time.Now()
ca := &x509.Certificate{
SerialNumber: serialNumber,
Subject: name,
NotBefore: now,
NotAfter: future(now),
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}
// generate rsa private key
caPrivKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, fmt.Errorf("Failed to generate CA private key: %w", err)
}
// create certificate bytes
caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, caPrivKey.Public(), caPrivKey)
if err != nil {
return nil, fmt.Errorf("Failed to generate CA certificate bytes: %w", err)
}
// add the raw certificate bytes so `*x509.Certificate.Equal(*x509.Certificate)` is valid
ca.Raw = caBytes
// get private key bytes
privKeyBytes := x509.MarshalPKCS1PrivateKey(caPrivKey)
gen := &CertGen{cert: ca, certBytes: caBytes, key: caPrivKey, keyBytes: privKeyBytes}
// generate pem blocks
err = gen.generatePem()
if err != nil {
return nil, fmt.Errorf("Failed to generate PEM encoding: %w", err)
}
// generate key pair
caKeyPair, err := tls.X509KeyPair(gen.certPem, gen.keyPem)
if err != nil {
return nil, fmt.Errorf("Failed to generate CA key pair: %w", err)
}
gen.tlsCert = caKeyPair
return gen, nil
}