Compare commits

...

4 Commits

Author SHA1 Message Date
fb1b1ffcad Update CHANGELOG for v1.15.4. 2025-11-19 02:57:40 -08:00
7bb6973341 QoL for CSR generation. 2025-11-19 02:57:26 -08:00
8e997bda34 Update CHANGELOG for v1.15.3. 2025-11-19 02:43:47 -08:00
d76db4a947 Minor bug fixes. 2025-11-19 02:43:25 -08:00
7 changed files with 61 additions and 22 deletions

View File

@@ -1,5 +1,11 @@
CHANGELOG CHANGELOG
v1.15.4 - 2025-11-19
Quality of life fixes for CSR generation.
v1.15.3 - 2025-11-19
Minor bug fixes.
v1.15.2 - 2025-11-19 v1.15.2 - 2025-11-19
Minor bug fixes. Minor bug fixes.

View File

@@ -63,12 +63,7 @@ type CertificateRequest struct {
Profile Profile `yaml:"profile"` Profile Profile `yaml:"profile"`
} }
func (cs CertificateRequest) Generate() (crypto.PrivateKey, *x509.CertificateRequest, error) { func (cs CertificateRequest) Request(priv crypto.PrivateKey) (*x509.CertificateRequest, error) {
pub, priv, err := cs.KeySpec.Generate()
if err != nil {
return nil, nil, err
}
subject := pkix.Name{} subject := pkix.Name{}
subject.CommonName = cs.Subject.CommonName subject.CommonName = cs.Subject.CommonName
subject.Country = []string{cs.Subject.Country} 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 { for i, ip := range cs.Subject.IPAddresses {
ipAddresses = append(ipAddresses, net.ParseIP(ip)) ipAddresses = append(ipAddresses, net.ParseIP(ip))
if ipAddresses[i] == nil { 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{ req := &x509.CertificateRequest{
PublicKeyAlgorithm: 0, PublicKeyAlgorithm: 0,
PublicKey: pub, PublicKey: getPublic(priv),
Subject: subject, Subject: subject,
DNSNames: cs.Subject.DNSNames, DNSNames: cs.Subject.DNSNames,
IPAddresses: ipAddresses, IPAddresses: ipAddresses,
@@ -95,12 +90,26 @@ func (cs CertificateRequest) Generate() (crypto.PrivateKey, *x509.CertificateReq
reqBytes, err := x509.CreateCertificateRequest(rand.Reader, req, priv) reqBytes, err := x509.CreateCertificateRequest(rand.Reader, req, priv)
if err != nil { 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) req, err = x509.ParseCertificateRequest(reqBytes)
if err != nil { 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 return priv, req, nil

View File

@@ -71,3 +71,16 @@ func GenerateKey(algorithm x509.PublicKeyAlgorithm, bitSize int) (crypto.PublicK
return pub, key, nil 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
}
}

View File

@@ -121,3 +121,17 @@ func ExportPrivateKeyPEM(priv crypto.PrivateKey) ([]byte, error) {
return pem.EncodeToMemory(&pem.Block{Type: pemTypePrivateKey, Bytes: keyDER}), nil return pem.EncodeToMemory(&pem.Block{Type: pemTypePrivateKey, Bytes: keyDER}), nil
} }
func LoadCSR(path string) (*x509.CertificateRequest, error) {
in, err := os.ReadFile(path)
if err != nil {
return nil, certerr.LoadingError(certerr.ErrorSourceCSR, err)
}
req, _, err := ParseCSR(in)
return req, err
}
func ExportCSRAsPEM(req *x509.CertificateRequest) []byte {
return pem.EncodeToMemory(&pem.Block{Type: pemTypeCertificateRequest, Bytes: req.Raw})
}

View File

@@ -249,11 +249,6 @@ func showBasicConstraints(cert *x509.Certificate) {
fmt.Fprintln(os.Stdout) fmt.Fprintln(os.Stdout)
} }
var (
dateFormat string
showHash bool // if true, print a SHA256 hash of the certificate's Raw field
)
func wrapPrint(text string, indent int) { func wrapPrint(text string, indent int) {
tabs := "" tabs := ""
var tabsSb140 strings.Builder var tabsSb140 strings.Builder
@@ -265,11 +260,12 @@ func wrapPrint(text string, indent int) {
fmt.Fprintf(os.Stdout, tabs+"%s\n", wrap(text, indent)) fmt.Fprintf(os.Stdout, tabs+"%s\n", wrap(text, indent))
} }
func DisplayCert(w io.Writer, cert *x509.Certificate) { func DisplayCert(w io.Writer, cert *x509.Certificate, showHash bool) {
fmt.Fprintln(w, "CERTIFICATE") fmt.Fprintln(w, "CERTIFICATE")
if showHash { if showHash {
fmt.Fprintln(w, wrap(fmt.Sprintf("SHA256: %x", sha256.Sum256(cert.Raw)), 0)) fmt.Fprintln(w, wrap(fmt.Sprintf("SHA256: %x", sha256.Sum256(cert.Raw)), 0))
} }
fmt.Fprintln(w, wrap("Subject: "+DisplayName(cert.Subject), 0)) fmt.Fprintln(w, wrap("Subject: "+DisplayName(cert.Subject), 0))
fmt.Fprintln(w, wrap("Issuer: "+DisplayName(cert.Issuer), 0)) fmt.Fprintln(w, wrap("Issuer: "+DisplayName(cert.Issuer), 0))
fmt.Fprintf(w, "\tSignature algorithm: %s / %s\n", sigAlgoPK(cert.SignatureAlgorithm), fmt.Fprintf(w, "\tSignature algorithm: %s / %s\n", sigAlgoPK(cert.SignatureAlgorithm),
@@ -285,8 +281,8 @@ func DisplayCert(w io.Writer, cert *x509.Certificate) {
fmt.Fprintf(w, "\t%s\n", wrap("SKI: "+dumpHex(cert.SubjectKeyId), 1)) fmt.Fprintf(w, "\t%s\n", wrap("SKI: "+dumpHex(cert.SubjectKeyId), 1))
} }
wrapPrint("Valid from: "+cert.NotBefore.Format(dateFormat), 1) wrapPrint("Valid from: "+cert.NotBefore.Format(lib.DateShortFormat), 1)
fmt.Fprintf(w, "\t until: %s\n", cert.NotAfter.Format(dateFormat)) fmt.Fprintf(w, "\t until: %s\n", cert.NotAfter.Format(lib.DateShortFormat))
fmt.Fprintf(w, "\tKey usages: %s\n", keyUsages(cert.KeyUsage)) fmt.Fprintf(w, "\tKey usages: %s\n", keyUsages(cert.KeyUsage))
if len(cert.ExtKeyUsage) > 0 { if len(cert.ExtKeyUsage) > 0 {

View File

@@ -76,8 +76,9 @@ var DelegationExtension = pkix.Extension{
} }
const ( const (
pemTypeCertificate = "CERTIFICATE" pemTypeCertificate = "CERTIFICATE"
pemTypePrivateKey = "PRIVATE KEY" pemTypeCertificateRequest = "CERTIFICATE REQUEST"
pemTypePrivateKey = "PRIVATE KEY"
) )
// InclusiveDate returns the time.Time representation of a date - 1 // InclusiveDate returns the time.Time representation of a date - 1

View File

@@ -35,12 +35,12 @@ func main() {
} }
if config.leafOnly { if config.leafOnly {
dump.DisplayCert(os.Stdout, certs[0]) dump.DisplayCert(os.Stdout, certs[0], config.showHash)
continue continue
} }
for i := range certs { for i := range certs {
dump.DisplayCert(os.Stdout, certs[i]) dump.DisplayCert(os.Stdout, certs[i], config.showHash)
} }
} }
} }