From 7bb6973341cc9af04c8b75260365c9489ccbb430 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Wed, 19 Nov 2025 02:57:26 -0800 Subject: [PATCH] QoL for CSR generation. --- certlib/certgen/config.go | 29 +++++++++++++++++++---------- certlib/certgen/keygen.go | 13 +++++++++++++ certlib/certlib.go | 4 ++++ certlib/helpers.go | 5 +++-- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/certlib/certgen/config.go b/certlib/certgen/config.go index dd1d1b7..96296ce 100644 --- a/certlib/certgen/config.go +++ b/certlib/certgen/config.go @@ -63,12 +63,7 @@ type CertificateRequest struct { Profile Profile `yaml:"profile"` } -func (cs CertificateRequest) Generate() (crypto.PrivateKey, *x509.CertificateRequest, error) { - pub, priv, err := cs.KeySpec.Generate() - if err != nil { - return nil, nil, err - } - +func (cs CertificateRequest) Request(priv crypto.PrivateKey) (*x509.CertificateRequest, error) { subject := pkix.Name{} subject.CommonName = cs.Subject.CommonName subject.Country = []string{cs.Subject.Country} @@ -81,13 +76,13 @@ func (cs CertificateRequest) Generate() (crypto.PrivateKey, *x509.CertificateReq for i, ip := range cs.Subject.IPAddresses { ipAddresses = append(ipAddresses, net.ParseIP(ip)) if ipAddresses[i] == nil { - return nil, nil, fmt.Errorf("invalid IP address: %s", ip) + return nil, fmt.Errorf("invalid IP address: %s", ip) } } req := &x509.CertificateRequest{ PublicKeyAlgorithm: 0, - PublicKey: pub, + PublicKey: getPublic(priv), Subject: subject, DNSNames: cs.Subject.DNSNames, IPAddresses: ipAddresses, @@ -95,12 +90,26 @@ func (cs CertificateRequest) Generate() (crypto.PrivateKey, *x509.CertificateReq reqBytes, err := x509.CreateCertificateRequest(rand.Reader, req, priv) if err != nil { - return nil, nil, fmt.Errorf("failed to create certificate request: %w", err) + return nil, fmt.Errorf("failed to create certificate request: %w", err) } req, err = x509.ParseCertificateRequest(reqBytes) if err != nil { - return nil, nil, fmt.Errorf("failed to parse certificate request: %w", err) + return nil, fmt.Errorf("failed to parse certificate request: %w", err) + } + + return req, nil +} + +func (cs CertificateRequest) Generate() (crypto.PrivateKey, *x509.CertificateRequest, error) { + _, priv, err := cs.KeySpec.Generate() + if err != nil { + return nil, nil, err + } + + req, err := cs.Request(priv) + if err != nil { + return nil, nil, err } return priv, req, nil diff --git a/certlib/certgen/keygen.go b/certlib/certgen/keygen.go index 23205d6..9ba5536 100644 --- a/certlib/certgen/keygen.go +++ b/certlib/certgen/keygen.go @@ -71,3 +71,16 @@ func GenerateKey(algorithm x509.PublicKeyAlgorithm, bitSize int) (crypto.PublicK return pub, key, nil } + +func getPublic(priv crypto.PrivateKey) crypto.PublicKey { + switch priv := priv.(type) { + case *rsa.PrivateKey: + return &priv.PublicKey + case *ecdsa.PrivateKey: + return &priv.PublicKey + case *ed25519.PrivateKey: + return priv.Public() + default: + return nil + } +} diff --git a/certlib/certlib.go b/certlib/certlib.go index cb66b39..22c6797 100644 --- a/certlib/certlib.go +++ b/certlib/certlib.go @@ -131,3 +131,7 @@ func LoadCSR(path string) (*x509.CertificateRequest, error) { req, _, err := ParseCSR(in) return req, err } + +func ExportCSRAsPEM(req *x509.CertificateRequest) []byte { + return pem.EncodeToMemory(&pem.Block{Type: pemTypeCertificateRequest, Bytes: req.Raw}) +} diff --git a/certlib/helpers.go b/certlib/helpers.go index b4c23af..135795b 100644 --- a/certlib/helpers.go +++ b/certlib/helpers.go @@ -76,8 +76,9 @@ var DelegationExtension = pkix.Extension{ } const ( - pemTypeCertificate = "CERTIFICATE" - pemTypePrivateKey = "PRIVATE KEY" + pemTypeCertificate = "CERTIFICATE" + pemTypeCertificateRequest = "CERTIFICATE REQUEST" + pemTypePrivateKey = "PRIVATE KEY" ) // InclusiveDate returns the time.Time representation of a date - 1