certkit

package module
v0.8.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 2, 2026 License: MIT Imports: 53 Imported by: 0

README

certkit

Note: certkit is under active development. CLI flags, output formats, and library APIs may change between releases. Do not rely on interface stability for scripting or automation until a 1.0 release.

A Swiss Army knife for TLS/SSL certificates. Inspect, verify, bundle, scan, and generate certificates and keys -- all from a single tool.

What can it do?

  • Inspect any certificate, key, or CSR and see exactly what's in it
  • Verify that a cert chains to a trusted root, matches its key, and isn't about to expire
  • Connect to a TLS server and display its certificate chain, cipher suite, and ALPN
  • Bundle a leaf cert into a full chain for your web server (nginx, Apache, HAProxy, etc.)
  • Convert between PEM, DER, PKCS#12, JKS, and PKCS#7
  • Sign certificates -- self-signed CAs or issue certs from CSRs
  • Scan a directory full of certs and keys to understand what you have
  • Generate new key pairs and CSRs for certificate renewals
  • Check revocation via OCSP or CRL

Works with every common format out of the box. No OpenSSL gymnastics required.

Web App

Use certkit directly in your browser at certkit.pages.dev. Drop certificate and key files to inspect, match, and export organized bundles -- all processing happens locally via WebAssembly. No files are uploaded.

Install

Homebrew (macOS)
brew install sensiblebit/tap/certkit
Debian/Ubuntu (Linux)

Download the .deb package from the latest release and install:

sudo dpkg -i certkit_*.deb
From source

Requires Go 1.25+.

go build -o certkit ./cmd/certkit/
Shell Completion

certkit supports tab completion for bash, zsh, fish, and PowerShell. Run certkit completion --help for details, or set it up with:

# Bash
source <(certkit completion bash)

# Zsh
source <(certkit completion zsh)

# Fish
certkit completion fish | source

# PowerShell
certkit completion powershell | Out-String | Invoke-Expression

To load completions for every new session, see certkit completion <shell> --help for persistent installation instructions.

Quick Start

See what's in a certificate:

certkit inspect cert.pem

Check if it's valid and not expiring soon:

certkit verify cert.pem --expiry 30d

Build the full chain your web server needs:

certkit bundle cert.pem -o chain.pem

See EXAMPLES.md for a complete walkthrough of every command with real-world scenarios.

Commands

Command What it does
certkit inspect <file> Show what's in a cert, key, or CSR
certkit verify <file> Check chain, key match, and expiry
certkit connect <host> Test a TLS connection and display the certificate chain
certkit bundle <file> Build a certificate chain from a leaf cert
certkit convert <file> Convert between PEM, DER, PKCS#12, JKS, and PKCS#7
certkit sign self-signed Create a self-signed certificate
certkit sign csr <file> Sign a CSR with a CA certificate and key
certkit scan <path> Scan a directory and catalog everything found
certkit keygen Generate a new key pair (and optionally a CSR)
certkit csr Generate a CSR from a template, cert, or existing CSR
certkit ocsp <file> Check certificate revocation status via OCSP
certkit crl <file-or-url> Parse a CRL and check for revoked certificates

License

MIT


Reference

Global Flags
Flag Default Description
--allow-expired false Include expired certificates
--insecure-default-password false Use insecure default password 'changeit' for PKCS#12/JKS export when no explicit password is provided
--json false Output in JSON format
--log-level, -l info Log level: debug, info, warn, error
--password-file File containing passwords, one per line
--passwords, -p Comma-separated passwords for encrypted keys
--verbose, -v false Extended details in output (serial, key info, signature algorithm, key usage, EKU)

Common passwords ("", "password", "changeit", "keypassword") are always tried automatically.

Inspect Flags
Flag Default Description
--allow-private-network false Allow AIA fetches to private/internal endpoints
--format text Output format: text, json
Verify Flags
Flag Default Description
--allow-private-network false Allow AIA/OCSP/CRL fetches to private/internal endpoints
--crl false Check CRL distribution points for revocation
--diagnose false Show diagnostics when chain verification fails
--expiry, -e Check if cert expires within duration (e.g., 30d, 720h)
--format text Output format: text, json
--key Private key file to check against the certificate
--ocsp false Check OCSP revocation status
--trust-store mozilla Trust store: system, mozilla

Chain verification is always performed. When the input contains an embedded private key (PKCS#12, JKS), key match is checked automatically. Use --ocsp and/or --crl to check revocation status (requires network access and a valid chain).

Connect Flags
Flag Default Description
--allow-private-network false Allow AIA/OCSP/CRL fetches to private/internal endpoints
--ciphers false Enumerate all supported cipher suites with security ratings
--crl false Check CRL distribution points for revocation
--format text Output format: text, json
--no-ocsp false Disable automatic OCSP revocation check
--servername Override SNI hostname (defaults to host)

Port defaults to 443 if not specified. OCSP revocation status is checked automatically (best-effort); use --no-ocsp to disable. Use --verbose for extended details (serial, key info, signature algorithm, key usage, EKU).

Bundle Flags
Flag Default Description
--allow-private-network false Allow AIA fetches to private/internal endpoints
--force, -f false Skip chain verification
--format pem Output format: pem, chain, fullchain, p12, jks
--key Private key file (PEM)
--out-file, -o (stdout) Output file
--trust-store mozilla Trust store: system, mozilla
Convert Flags
Flag Default Description
--key Private key file (PEM). Keys are matched to certificates automatically.
--out-file, -o (stdout for PEM) Output file (required for binary formats)
--to (required) Output format: pem, der, p12, jks, p7b

Input format is auto-detected.

Sign Self-Signed Flags
Flag Default Description
--cn (required) Common Name for the certificate
--days 3650 Validity period in days
--is-ca true Set CA:TRUE basic constraint
--key Existing private key file (generates EC P-256 if omitted)
--out-file, -o (stdout) Output file
Sign CSR Flags
Flag Default Description
--ca (required) CA certificate file (PEM)
--ca-key (required) CA private key file (PEM)
--copy-sans true Copy SANs from CSR to issued certificate
--days 365 Validity period in days
--out-file, -o (stdout) Output file
Scan Flags
Flag Default Description
--allow-private-network false Allow AIA fetches to private/internal endpoints
--bundle-path Export bundles to this directory
--config, -c ./bundles.yaml Path to bundle config YAML
--dump-certs Dump all discovered certificates to a single PEM file
--dump-keys Dump all discovered keys to a single PEM file
--duplicates false Export all certificates per bundle, not just the newest
--force, -f false Allow export of untrusted certificate bundles
--format text Output format: text, json
--load-db Load an existing database into memory before scanning
--max-file-size 10485760 Skip files larger than this size in bytes (0 to disable)
--save-db Save the in-memory database to disk after scanning
Keygen Flags
Flag Default Description
--algorithm, -a ecdsa Key algorithm: rsa, ecdsa, ed25519
--bits, -b 4096 RSA key size in bits
--cn Common Name (triggers CSR generation)
--curve P-256 ECDSA curve: P-256, P-384, P-521
--out-path, -o (stdout) Output directory
--sans Comma-separated SANs (triggers CSR generation)
CSR Flags
Flag Default Description
--algorithm, -a ecdsa Key algorithm for generated keys
--bits, -b 4096 RSA key size in bits
--curve P-256 ECDSA curve
--from-cert PEM certificate to use as CSR template
--from-csr Existing PEM CSR to re-sign with a new key
--key Existing private key file (PEM); generates new if omitted
--out-path, -o (stdout) Output directory
--template JSON template file for CSR generation

Exactly one of --template, --from-cert, or --from-csr is required.

OCSP Flags
Flag Default Description
--allow-private-network false Allow OCSP fetches to private/internal endpoints
--format text Output format: text, json
--issuer Issuer certificate file (PEM); auto-resolved from input if omitted

The OCSP responder URL is read from the certificate's AIA extension.

CRL Flags
Flag Default Description
--check Certificate file to check against the CRL
--format text Output format: text, json

Accepts local files (PEM or DER) or HTTP URLs.

Exit Codes
Code Meaning
0 Success
1 General error (bad input, missing file, etc.)
2 Validation failure (chain invalid, key mismatch, expired, revoked)
Bundle Configuration

Bundles are defined in a YAML file that maps certificate Common Names to named bundles. An optional defaultSubject provides fallback X.509 subject fields for CSR generation.

defaultSubject:
  country: [US]
  province: [California]
  locality: [San Diego]
  organization: [Company, Inc.]
  organizationalUnit: [DevOps]

bundles:
  - bundleName: examplecom-tls
    commonNames:
      - "*.example.com"
      - example.com

  - bundleName: exampleio-tls
    commonNames:
      - "*.example.io"
      - example.io
    subject: # overrides defaultSubject for this bundle
      country: [GB]
      province: [London]
      locality: [London]
      organization: [Company UK, Ltd.]
      organizationalUnit: [Platform Engineering]

Bundles without an explicit subject block inherit from defaultSubject. Certificate-to-bundle matching uses exact Common Name comparison against the commonNames list (a CN of *.example.com matches the literal wildcard string, not subdomains).

Bundle Output Files

When running certkit scan --bundle-path, each bundle produces the following files under <dir>/<bundleName>/:

File Contents
<cn>.pem Leaf certificate
<cn>.chain.pem Leaf + intermediates
<cn>.fullchain.pem Leaf + intermediates + root
<cn>.intermediates.pem Intermediate certificates
<cn>.root.pem Root certificate
<cn>.key Private key (PEM, mode 0600)
<cn>.p12 PKCS#12 archive (requires explicit export password via --passwords/--password-file; or --insecure-default-password for changeit, mode 0600)
<cn>.k8s.yaml Kubernetes kubernetes.io/tls Secret (mode 0600)
<cn>.json Certificate metadata
<cn>.yaml Certificate and key metadata (mode 0600)
<cn>.csr Certificate Signing Request
<cn>.csr.json CSR details (subject, SANs, key algorithm)

Wildcard characters in the CN are replaced with _ in filenames (e.g., *.example.com becomes _.example.com). The .intermediates.pem and .root.pem files are only created when those certificates exist in the chain.

Library

The certkit Go package provides reusable certificate utilities:

import "github.com/sensiblebit/certkit"

// Parse certificates and keys
certs, _ := certkit.ParsePEMCertificates(pemData)
key, _ := certkit.ParsePEMPrivateKey(keyPEM)

// Compute identifiers
fingerprint := certkit.CertFingerprint(cert)
colonFP := certkit.CertFingerprintColonSHA256(cert)  // AA:BB:CC format
ski := certkit.CertSKI(cert)

// Check expiry
if certkit.CertExpiresWithin(cert, 30*24*time.Hour) {
    // cert expires within 30 days
}

// Build verified chains (library defaults to system trust store)
opts := certkit.DefaultOptions()
opts.TrustStore = "mozilla" // or "system" (the default)
bundle, _ := certkit.Bundle(ctx, certkit.BundleInput{Leaf: leaf, Options: opts})

// Generate keys
ecKey, _ := certkit.GenerateECKey(elliptic.P256())
rsaKey, _ := certkit.GenerateRSAKey(4096)

// Generate CSRs
csrPEM, keyPEM, _ := certkit.GenerateCSR(leaf, nil) // auto-generates EC P-256 key

// Sign certificates
selfSigned, _ := certkit.CreateSelfSigned(certkit.SelfSignedInput{Signer: caKey, Subject: pkix.Name{CommonName: "My CA"}, IsCA: true})
issued, _ := certkit.SignCSR(certkit.SignCSRInput{CSR: csr, CACert: caCert, CAKey: caKey, Days: 365})

// TLS connection probing
result, _ := certkit.ConnectTLS(ctx, certkit.ConnectTLSInput{Host: "example.com"})

// Revocation checking
ocspResp, _ := certkit.CheckOCSP(ctx, certkit.CheckOCSPInput{Cert: cert, Issuer: issuer})

// PKCS operations
p12, _ := certkit.EncodePKCS12(key, leaf, intermediates, "password")
p7, _ := certkit.EncodePKCS7(certs)
jks, _ := certkit.EncodeJKS(key, leaf, intermediates, "changeit")
How It Works
flowchart TD
    A[Input files / stdin] --> B[Format detection - PEM vs DER]
    B --> C[Parse certs, keys, CSRs<br/>PKCS#12, PKCS#7, JKS, encrypted PEM, PKCS#8, SEC1, Ed25519]
    C --> D[Catalog in MemStore<br/>certificates + keys indexed by SKI]
    D --> E[Resolve AKIs<br/>match legacy SHA-1 AKIs to computed RFC 7093 M1 SKIs]
    E --> F{--bundle-path?}
    F -- yes --> G[Match keys to certs, build chains,<br/>write all output formats per bundle]
    F -- no --> H[Print scan summary]

Expired certificates are always ingested; expiry filtering is output-only (--allow-expired overrides). SKI computation uses RFC 7093 Method 1 (SHA-256 truncated to 160 bits). Non-root certificate AKIs are resolved post-ingestion by matching against a multi-hash lookup (RFC 7093 M1 + legacy SHA-1) of all CA certificates.

Documentation

Overview

Package certkit provides certificate parsing, encoding, identification, chain bundling, PKCS#12/7, and CSR generation utilities.

Index

Constants

This section is empty.

Variables

View Source
var ErrCAKeyMismatch = errors.New("CA key does not match CA certificate")

ErrCAKeyMismatch indicates the signing CA private key does not match the CA certificate.

View Source
var ErrCRLTooLarge = errors.New("CRL data exceeds max size")

ErrCRLTooLarge indicates that CRL input exceeded the maximum allowed size.

View Source
var ErrEmptySANExtension = errors.New("no SAN entries provided")

ErrEmptySANExtension is returned when MarshalSANExtension is called with no SAN entries of any type.

View Source
var ErrUnknownOtherNameType = errors.New("unknown othername type")

ErrUnknownOtherNameType is returned when an OtherName type string is not a recognized label or a valid dotted-decimal OID.

Functions

func CRLContainsCertificate added in v0.8.2

func CRLContainsCertificate(crl *x509.RevocationList, cert *x509.Certificate) bool

CRLContainsCertificate checks if a certificate's serial number appears in the CRL.

func CertAKIEmbedded added in v0.2.1

func CertAKIEmbedded(cert *x509.Certificate) string

CertAKIEmbedded returns the Authority Key Identifier as stored in the certificate extension, as a colon-separated hex string. This matches the issuing CA's embedded SKI and may be SHA-1 or SHA-256. Returns empty string if the extension is not present.

func CertExpiresWithin

func CertExpiresWithin(cert *x509.Certificate, d time.Duration) bool

CertExpiresWithin reports whether the certificate will expire within the given duration from now.

func CertFingerprint

func CertFingerprint(cert *x509.Certificate) string

CertFingerprint returns the SHA-256 fingerprint of a certificate as a lowercase hex string.

func CertFingerprintColonSHA1

func CertFingerprintColonSHA1(cert *x509.Certificate) string

CertFingerprintColonSHA1 returns the SHA-1 fingerprint of a certificate in uppercase colon-separated hex format (AA:BB:CC:...), matching the format used by OpenSSL and browser certificate viewers.

func CertFingerprintColonSHA256

func CertFingerprintColonSHA256(cert *x509.Certificate) string

CertFingerprintColonSHA256 returns the SHA-256 fingerprint of a certificate in uppercase colon-separated hex format (AA:BB:CC:...), matching the format used by OpenSSL and browser certificate viewers.

func CertFingerprintSHA1

func CertFingerprintSHA1(cert *x509.Certificate) string

CertFingerprintSHA1 returns the SHA-1 fingerprint of a certificate as a lowercase hex string. SHA-1 fingerprints are widely used in browser UIs, CT logs, and legacy systems.

func CertSKI added in v0.2.1

func CertSKI(cert *x509.Certificate) string

CertSKI computes a Subject Key Identifier from the certificate's public key per RFC 7093 Section 2 Method 1: the leftmost 160 bits of the SHA-256 hash of the BIT STRING value of subjectPublicKey (excluding tag, length, and unused-bits octet). The result is 20 bytes, the same length as a SHA-1 SKI, ensuring compatibility.

func CertSKIEmbedded added in v0.2.1

func CertSKIEmbedded(cert *x509.Certificate) string

CertSKIEmbedded returns the Subject Key Identifier as stored in the certificate extension, as a colon-separated hex string. This may be SHA-1 (20 bytes) or SHA-256 (32 bytes) depending on the issuing CA. Returns empty string if the extension is not present.

func CertToPEM

func CertToPEM(cert *x509.Certificate) string

CertToPEM encodes a certificate as PEM.

func CheckCT added in v0.8.2

func CheckCT(input CheckCTInput) (*CTResult, []ChainDiagnostic)

CheckCT verifies SCTs from TLS and embedded certificate data against known CT logs.

func ClassifyHosts

func ClassifyHosts(hosts []string) (dnsNames []string, ips []net.IP, uris []*url.URL, emails []string)

ClassifyHosts splits a mixed host list into DNS names, IPs, URIs, and emails. Classification precedence: IP address, email (RFC 5322), URI with scheme+host, then DNS name. Email detection uses mail.ParseAddress with a bare-address guard to reject display-name forms like "John <[email protected]>".

func CollectCertificateSANs added in v0.8.2

func CollectCertificateSANs(cert *x509.Certificate) []string

CollectCertificateSANs returns all Subject Alternative Names from a certificate: DNS names, IP addresses, email addresses, URIs, and OtherName extensions. This is the canonical SAN aggregation used across all CLI commands for CLI-4 consistency.

func ColonHex

func ColonHex(b []byte) string

ColonHex formats a byte slice as colon-separated lowercase hex.

func ComputeSKI added in v0.2.1

func ComputeSKI(pub crypto.PublicKey) ([]byte, error)

ComputeSKI computes a Subject Key Identifier using RFC 7093 Method 1: SHA-256 of subjectPublicKey BIT STRING bytes, truncated to 160 bits (20 bytes).

func ComputeSKILegacy added in v0.2.1

func ComputeSKILegacy(pub crypto.PublicKey) ([]byte, error)

ComputeSKILegacy computes a Subject Key Identifier using the RFC 5280 method: SHA-1 of subjectPublicKey BIT STRING bytes (20 bytes). Used only for AKI cross-matching with legacy certificates.

func CreateSelfSigned added in v0.8.2

func CreateSelfSigned(input SelfSignedInput) (*x509.Certificate, error)

CreateSelfSigned generates a self-signed certificate from the given input. The certificate is created with KeyUsageCertSign and KeyUsageCRLSign when IsCA is true, and KeyUsageDigitalSignature otherwise.

func DecodeJKS

func DecodeJKS(data []byte, passwords []string) ([]*x509.Certificate, []crypto.PrivateKey, error)

DecodeJKS decodes a Java KeyStore (JKS) and returns the certificates and private keys it contains. Passwords are tried in order to open the store. For private key entries, all passwords are tried independently since the key password may differ from the store password.

TrustedCertificateEntry entries yield certificates. PrivateKeyEntry entries yield PKCS#8 private keys and their certificate chains. Individual entry errors are skipped; an error is returned only if the store cannot be loaded or no usable entries are found.

func DecodePKCS7

func DecodePKCS7(derData []byte) ([]*x509.Certificate, error)

DecodePKCS7 decodes a DER-encoded PKCS#7 bundle and returns the certificates it contains. Returns an error if decoding fails or the bundle contains no certificates.

func DecodePKCS12

func DecodePKCS12(pfxData []byte, password string) (crypto.PrivateKey, *x509.Certificate, []*x509.Certificate, error)

DecodePKCS12 decodes a PKCS#12/PFX bundle and returns the private key, leaf certificate, and CA certificates. Returns an error if decoding fails.

func DeduplicatePasswords added in v0.7.0

func DeduplicatePasswords(extra []string) []string

DeduplicatePasswords merges additional passwords with the defaults and removes duplicates while preserving order. Defaults come first, followed by any extra passwords not already in the list.

func DefaultPasswords

func DefaultPasswords() []string

DefaultPasswords returns the list of passwords tried by default when decrypting password-protected PEM blocks or PKCS#12 files. Returns a fresh copy each call.

func EncodeJKS

func EncodeJKS(privateKey crypto.PrivateKey, leaf *x509.Certificate, caCerts []*x509.Certificate, password string) ([]byte, error)

EncodeJKS creates a Java KeyStore (JKS) containing a private key entry with its certificate chain. The leaf certificate and intermediates form the chain stored under the alias "server". The same password protects both the store and the key entry (standard Java convention).

func EncodeJKSEntries added in v0.8.2

func EncodeJKSEntries(entries []JKSEntry, password string) ([]byte, error)

EncodeJKSEntries creates a Java KeyStore (JKS) containing one or more private key entries, each with its certificate chain. Aliases are sanitized to lowercase alphanumeric+hyphen form. Duplicate aliases get a numeric suffix (e.g. "server", "server-2"). The same password protects both the store and all key entries (standard Java convention).

func EncodePKCS7

func EncodePKCS7(certs []*x509.Certificate) ([]byte, error)

EncodePKCS7 creates a certs-only PKCS#7/P7B bundle from a certificate chain. Returns the DER-encoded PKCS#7 SignedData structure.

func EncodePKCS12

func EncodePKCS12(privateKey crypto.PrivateKey, leaf *x509.Certificate, caCerts []*x509.Certificate, password string) ([]byte, error)

EncodePKCS12 creates a PKCS#12/PFX bundle from a private key, leaf cert, CA chain, and password. Returns the DER-encoded PKCS#12 data. Normalizes Ed25519 pointer form to value form before encoding.

func EncodePKCS12Legacy

func EncodePKCS12Legacy(privateKey crypto.PrivateKey, leaf *x509.Certificate, caCerts []*x509.Certificate, password string) ([]byte, error)

EncodePKCS12Legacy creates a PKCS#12/PFX bundle using the legacy RC2 cipher for compatibility with older Java keystores. Returns the DER-encoded PKCS#12 data. Normalizes Ed25519 pointer form to value form before encoding.

func FetchAIACertificates

func FetchAIACertificates(ctx context.Context, input FetchAIACertificatesInput) ([]*x509.Certificate, []string)

FetchAIACertificates follows AIA CA Issuers URLs to fetch intermediate certificates.

func FetchCRL added in v0.8.2

func FetchCRL(ctx context.Context, input FetchCRLInput) ([]byte, error)

FetchCRL downloads a CRL from an HTTP or HTTPS URL. By default, the URL is validated against SSRF (literal and DNS-resolved private/loopback/link-local/unspecified IPs are blocked). Set AllowPrivateNetworks to bypass this for user-provided URLs. The response is limited to 10 MB.

func FetchLeafFromURL

func FetchLeafFromURL(ctx context.Context, input FetchLeafFromURLInput) (*x509.Certificate, error)

FetchLeafFromURL connects to the given HTTPS URL via TLS and returns the leaf (server) certificate from the handshake.

func FormatCRLInfo added in v0.8.2

func FormatCRLInfo(info *CRLInfo) string

FormatCRLInfo formats CRL information as human-readable text.

func FormatCRLLine added in v0.8.2

func FormatCRLLine(r *CRLCheckResult) string

FormatCRLLine formats a CRLCheckResult as a single line for connect output.

func FormatCRLStatusLine added in v0.8.2

func FormatCRLStatusLine(prefix string, r *CRLCheckResult) string

FormatCRLStatusLine formats a CRLCheckResult as a single line with the given label prefix. Both FormatCRLLine and internal/verify.go delegate to this to avoid duplicating status-to-text logic.

func FormatCTLine added in v0.8.2

func FormatCTLine(r *CTResult) string

FormatCTLine formats a one-line Certificate Transparency summary.

func FormatCipherRatingLine added in v0.8.2

func FormatCipherRatingLine(r *CipherScanResult) string

FormatCipherRatingLine formats a one-line summary for the connect header block, positioned alongside Host/Protocol/OCSP etc.

func FormatCipherScanResult added in v0.8.2

func FormatCipherScanResult(r *CipherScanResult) string

FormatCipherScanResult formats the cipher suite list as human-readable text.

func FormatConnectResult added in v0.8.2

func FormatConnectResult(r *ConnectResult) string

FormatConnectResult formats a ConnectResult as human-readable text.

func FormatDN added in v0.8.1

func FormatDN(name pkix.Name) string

FormatDN formats a pkix.Name as a Distinguished Name string in ASN.1 DER order, matching the display order used by OpenSSL. When name.Names is populated (always the case for certificates parsed from DER/PEM), attributes are emitted in their original encoded order with human-readable labels. Unknown OIDs are rendered as dotted-decimal 1.2.3.4=#hex values. Multi-valued RDNs are flattened because pkix.Name does not preserve SET boundaries; prefer FormatDNFromRaw when raw DER is available. When name.Names is empty (e.g. a pkix.Name constructed programmatically without setting Names), it falls back to pkix.Name.String().

func FormatDNFromRaw added in v0.8.2

func FormatDNFromRaw(raw []byte, fallback pkix.Name) string

FormatDNFromRaw formats a Distinguished Name from the raw DER-encoded RDNSequence (e.g. Certificate.RawSubject/RawIssuer). When raw is empty or unparsable, it falls back to FormatDN.

func FormatEKUOIDs added in v0.8.1

func FormatEKUOIDs(raw []byte) []string

FormatEKUOIDs returns human-readable names for EKU OIDs extracted from raw ASN.1 extension bytes. This is needed for CSRs where Go does not populate ExtKeyUsage typed fields.

func FormatEKUs added in v0.8.1

func FormatEKUs(ekus []x509.ExtKeyUsage) []string

FormatEKUs returns human-readable names for extended key usages.

func FormatKeyUsage added in v0.8.1

func FormatKeyUsage(ku x509.KeyUsage) []string

FormatKeyUsage returns human-readable names for key usage bits.

func FormatKeyUsageBitString added in v0.8.1

func FormatKeyUsageBitString(raw []byte) []string

FormatKeyUsageBitString returns human-readable names for key usage bits extracted from a raw ASN.1 BIT STRING extension value. This is needed for CSRs where Go does not populate KeyUsage typed fields.

func FormatOCSPLine added in v0.8.2

func FormatOCSPLine(r *OCSPResult) string

FormatOCSPLine formats an OCSPResult as a single line for connect output.

func FormatOCSPResult added in v0.8.2

func FormatOCSPResult(r *OCSPResult) string

FormatOCSPResult formats an OCSPResult as human-readable text.

func FormatOCSPStatusLine added in v0.8.2

func FormatOCSPStatusLine(prefix string, r *OCSPResult) string

FormatOCSPStatusLine formats an OCSPResult as a single line with the given label prefix (e.g. "OCSP: " for connect output, " OCSP: " for verify output). Both FormatOCSPLine and internal/verify.go delegate to this to avoid duplicating status-to-text logic.

func FormatSerialNumber added in v0.8.2

func FormatSerialNumber(serial *big.Int) string

FormatSerialNumber formats a certificate serial number as 0x-prefixed hex. Returns an empty string when the serial is nil.

func GenerateCSR

func GenerateCSR(leaf *x509.Certificate, privateKey crypto.PrivateKey) (csrPEM string, keyPEM string, err error)

GenerateCSR creates a Certificate Signing Request that copies Subject, DNSNames, IPAddresses, and URIs from the given leaf certificate. If privateKey is nil, a new EC P-256 key is generated. Returns the PEM-encoded CSR and, if a key was auto-generated, its PEM-encoded PKCS#8 private key (empty string if caller provided the key).

func GenerateCSRFromCSR

func GenerateCSRFromCSR(source *x509.CertificateRequest, signer crypto.Signer) (string, error)

GenerateCSRFromCSR creates a new CSR using an existing CSR as template, signed by the provided key. String-typed OtherName SAN entries from the source CSR are preserved; binary-typed OtherNames are silently skipped.

func GenerateCSRFromTemplate

func GenerateCSRFromTemplate(tmpl *CSRTemplate, signer crypto.Signer) (string, error)

GenerateCSRFromTemplate creates a PEM-encoded CSR from a template and signer.

When OtherNames are present, the entire SAN extension is built via MarshalSANExtension and placed in ExtraExtensions. The typed SAN fields (DNSNames, IPAddresses, etc.) are left nil on the CSR template to avoid Go generating a duplicate SAN extension.

func GenerateECKey

func GenerateECKey(curve elliptic.Curve) (*ecdsa.PrivateKey, error)

GenerateECKey generates a new ECDSA private key on the given curve.

func GenerateEd25519Key

func GenerateEd25519Key() (ed25519.PublicKey, ed25519.PrivateKey, error)

GenerateEd25519Key generates a new Ed25519 key pair.

func GenerateRSAKey

func GenerateRSAKey(bits int) (*rsa.PrivateKey, error)

GenerateRSAKey generates a new RSA private key with the given bit size.

func GetCertificateType

func GetCertificateType(cert *x509.Certificate) string

GetCertificateType determines if a certificate is root, intermediate, or leaf.

func GetPublicKey

func GetPublicKey(priv crypto.PrivateKey) (crypto.PublicKey, error)

GetPublicKey extracts the public key from a private key via crypto.Signer.

func IsIssuedByMozillaRoot added in v0.7.0

func IsIssuedByMozillaRoot(cert *x509.Certificate) bool

IsIssuedByMozillaRoot reports whether the certificate's issuer matches a Mozilla root certificate's subject (by raw ASN.1 bytes). This is used as a performance optimization to skip AIA fetching when the issuer is a well-known root — it is NOT a trust decision. Trust verification requires full chain validation via VerifyChainTrust.

func IsMozillaRoot added in v0.8.0

func IsMozillaRoot(cert *x509.Certificate) bool

IsMozillaRoot reports whether the certificate matches a Mozilla root certificate by both Subject (raw ASN.1 bytes) and public key (marshaled PKIX). This identifies self-signed roots and cross-signed variants that share the same key pair. A Subject-only match is insufficient because an attacker could forge the Subject; the public key check ensures the certificate holds the same key as the genuine root.

AKI (Authority Key Identifier) is intentionally not checked: cross-signed roots have a different AKI (pointing to the cross-signer) than the self-signed version, and the cross-signer may have been removed from the Mozilla trust store. The public key match is cryptographically sufficient.

func IsPEM

func IsPEM(data []byte) bool

IsPEM returns true if the data appears to contain PEM-encoded content.

func KeyAlgorithmName

func KeyAlgorithmName(key crypto.PrivateKey) string

KeyAlgorithmName returns a human-readable name for a private key's algorithm.

func KeyMatchesCert

func KeyMatchesCert(priv crypto.PrivateKey, cert *x509.Certificate) (bool, error)

KeyMatchesCert reports whether a private key corresponds to the public key in a certificate. Uses the Equal method available on all standard public key types since Go 1.20, which handles cross-type mismatches by returning false.

func MarshalPrivateKeyToPEM

func MarshalPrivateKeyToPEM(key crypto.PrivateKey) (string, error)

MarshalPrivateKeyToPEM marshals a private key to PKCS#8 PEM format. Supports ECDSA, RSA, and Ed25519 keys. Normalizes Ed25519 pointer form to value form before marshaling.

func MarshalPublicKeyToPEM

func MarshalPublicKeyToPEM(pub crypto.PublicKey) (string, error)

MarshalPublicKeyToPEM marshals a public key to PKIX PEM format. Supports RSA, ECDSA, and Ed25519 public keys.

func MarshalSANExtension added in v0.8.2

func MarshalSANExtension(input MarshalSANExtensionInput) (pkix.Extension, error)

MarshalSANExtension builds a complete Subject Alternative Name extension (OID 2.5.29.17) containing all GeneralName types from the input. The returned extension can be used in x509.Certificate.ExtraExtensions or x509.CertificateRequest.ExtraExtensions.

When OtherNames are present, callers must nil out the typed SAN fields (DNSNames, IPAddresses, etc.) on the certificate/CSR template to avoid Go's x509 package generating a duplicate SAN extension.

func MozillaRootPEM added in v0.7.0

func MozillaRootPEM() []byte

MozillaRootPEM returns the raw PEM-encoded Mozilla root certificate bundle.

func MozillaRootPool added in v0.7.0

func MozillaRootPool() (*x509.CertPool, error)

MozillaRootPool returns a shared x509.CertPool containing the embedded Mozilla root certificates. The pool is initialized once and cached for the lifetime of the process. Returns an error if the embedded PEM bundle cannot be parsed.

func MozillaRootSubjects added in v0.7.0

func MozillaRootSubjects() map[string]bool

MozillaRootSubjects returns a set of raw ASN.1 subject byte strings from all Mozilla root certificates. The result is initialized once and cached for the lifetime of the process.

The returned map is shared and must not be modified by callers. We intentionally return the backing map directly rather than a defensive copy because all callers perform read-only lookups, and copying ~150 entries on every call would violate PERF-2 for no practical safety gain.

func ParseCRL added in v0.8.2

func ParseCRL(data []byte) (*x509.RevocationList, error)

ParseCRL parses a CRL from PEM or DER data. Returns the parsed RevocationList from the stdlib.

func ParseCertificatesAny added in v0.7.5

func ParseCertificatesAny(data []byte) ([]*x509.Certificate, error)

ParseCertificatesAny attempts to parse certificates from raw bytes, trying DER encoding first (single cert, most common for AIA .cer responses), then PEM (may contain multiple certs), then PKCS#7/P7C (common for AIA .p7c responses from DISA, FPKI, and bridge CAs).

func ParseOtherNameSANs added in v0.8.1

func ParseOtherNameSANs(extensions []pkix.Extension) []string

ParseOtherNameSANs extracts SAN entries that Go's x509 package silently drops: OtherName (tag 0), DirectoryName (tag 4), and RegisteredID (tag 8). Returns formatted strings like "UPN:[email protected]" or "OtherName(1.2.3.4):value". Pass the raw extensions list from a certificate or CSR.

func ParsePEMCertificate

func ParsePEMCertificate(pemData []byte) (*x509.Certificate, error)

ParsePEMCertificate parses a single certificate from PEM data.

func ParsePEMCertificateRequest

func ParsePEMCertificateRequest(pemData []byte) (*x509.CertificateRequest, error)

ParsePEMCertificateRequest parses a single certificate request from PEM data.

func ParsePEMCertificates

func ParsePEMCertificates(pemData []byte) ([]*x509.Certificate, error)

ParsePEMCertificates parses all certificates from a PEM bundle.

func ParsePEMPrivateKey

func ParsePEMPrivateKey(pemData []byte) (crypto.PrivateKey, error)

ParsePEMPrivateKey parses a PEM-encoded private key (PKCS#1, PKCS#8, or EC). For "PRIVATE KEY" blocks it tries PKCS#8 first, then falls back to PKCS#1 and EC parsers to handle mislabeled keys (e.g., from pkcs12.ToPEM).

func ParsePEMPrivateKeyWithPasswords

func ParsePEMPrivateKeyWithPasswords(pemData []byte, passwords []string) (crypto.PrivateKey, error)

ParsePEMPrivateKeyWithPasswords tries to parse a PEM-encoded private key. It first attempts unencrypted parsing via ParsePEMPrivateKey. If that fails and the PEM block is encrypted (legacy RFC 1423), it tries each password in order. Returns the first successfully decrypted key, or an error if all passwords fail.

func ParsePEMPrivateKeys added in v0.8.2

func ParsePEMPrivateKeys(pemData []byte, passwords []string) ([]crypto.PrivateKey, error)

ParsePEMPrivateKeys parses all private keys from a PEM bundle, trying each password for encrypted blocks. Non-key PEM blocks (e.g., CERTIFICATE) are silently skipped. Returns an error if a key block fails to parse or if no keys are found at all.

func PublicKeyAlgorithmName

func PublicKeyAlgorithmName(key crypto.PublicKey) string

PublicKeyAlgorithmName returns a human-readable name for a public key's algorithm.

func ReadCRLFile added in v0.8.2

func ReadCRLFile(path string) ([]byte, error)

ReadCRLFile reads a local CRL file with the same hard size cap as FetchCRL.

func ResolveOtherNameOID added in v0.8.2

func ResolveOtherNameOID(s string) (asn1.ObjectIdentifier, error)

ResolveOtherNameOID resolves a human-readable label ("UPN", "SRV") or dotted-decimal OID string ("1.3.6.1.4.1.311.20.2.3") to an asn1.ObjectIdentifier.

func SelectIssuerCertificate added in v0.8.2

func SelectIssuerCertificate(cert *x509.Certificate, candidates []*x509.Certificate) *x509.Certificate

SelectIssuerCertificate chooses the best issuer for cert from candidates. It requires both issuer DN match and a valid signature relationship, and prefers AKI/SKI matches when available. Returns nil when no candidate meets those criteria.

func SignCSR added in v0.8.2

func SignCSR(input SignCSRInput) (*x509.Certificate, error)

SignCSR signs a certificate signing request using the provided CA certificate and key. Returns the issued certificate.

func SortDiagnostics added in v0.8.2

func SortDiagnostics(diags []ChainDiagnostic)

SortDiagnostics sorts diagnostics: errors before warnings, then alphabetically by check name within each group for stable output order.

func ValidateAIAURL added in v0.8.0

func ValidateAIAURL(rawURL string) error

ValidateAIAURL checks whether a URL is safe to fetch for AIA, OCSP, and CRL requests. It rejects non-HTTP(S) schemes plus literal and DNS-resolved private/loopback/link-local/unspecified addresses.

func ValidateAIAURLWithOptions added in v0.8.2

func ValidateAIAURLWithOptions(ctx context.Context, input ValidateAIAURLInput) error

ValidateAIAURLWithOptions checks whether a URL is safe to fetch for AIA, OCSP, and CRL HTTP requests.

By default, it rejects non-HTTP(S) schemes plus literal and DNS-resolved private/loopback/link-local/unspecified addresses to reduce SSRF risk. Set AllowPrivateNetworks to bypass IP restrictions. This check does not fully prevent DNS-rebind TOCTOU attacks between validation-time DNS and dial-time DNS.

func VerifyCSR

func VerifyCSR(csr *x509.CertificateRequest) error

VerifyCSR checks that the signature on a certificate signing request is valid.

func VerifyChainTrust added in v0.8.0

func VerifyChainTrust(input VerifyChainTrustInput) bool

VerifyChainTrust reports whether the given certificate chains to a trusted root. Cross-signed roots (same Subject and public key as a Mozilla root) are trusted directly. For expired certificates, verification is performed at a time just after the certificate's NotBefore to determine if the chain was ever valid — this is more robust than checking just before NotAfter, because intermediates that expired between issuance and the leaf's expiry will still be valid at NotBefore time.

Known limitation: if an intermediate expired before the leaf's NotBefore, the time-shifted verification will still fail because the intermediate is invalid at the leaf's issuance time. This is an uncommon edge case in practice (intermediates outlive the leaves they sign).

Types

type BundleInput added in v0.8.2

type BundleInput struct {
	// Leaf is the end-entity certificate to resolve.
	Leaf *x509.Certificate
	// Options configures chain resolution.
	Options BundleOptions
}

BundleInput holds parameters for Bundle.

type BundleOptions

type BundleOptions struct {
	// ExtraIntermediates are additional intermediates to consider during chain building.
	ExtraIntermediates []*x509.Certificate
	// FetchAIA enables fetching intermediate certificates via AIA CA Issuers URLs.
	FetchAIA bool
	// AIATimeout is the HTTP timeout for AIA fetches.
	AIATimeout time.Duration
	// AIAMaxDepth is the maximum number of AIA hops to follow.
	AIAMaxDepth int
	// TrustStore selects the root certificate pool: "system", "mozilla", or "custom".
	TrustStore string
	// CustomRoots are root certificates used when TrustStore is "custom".
	CustomRoots []*x509.Certificate
	// Verify enables chain verification against the trust store.
	Verify bool
	// ExcludeRoot omits the root certificate from the result.
	ExcludeRoot bool
	// AllowPrivateNetworks allows AIA fetches to private/internal endpoints.
	AllowPrivateNetworks bool
}

BundleOptions configures chain resolution.

func DefaultOptions

func DefaultOptions() BundleOptions

DefaultOptions returns sensible defaults.

type BundleResult

type BundleResult struct {
	// Leaf is the end-entity certificate.
	Leaf *x509.Certificate
	// Intermediates are the CA certificates between the leaf and root.
	Intermediates []*x509.Certificate
	// Roots are the trust anchor certificates (typically one).
	Roots []*x509.Certificate
	// Warnings are non-fatal issues found during chain resolution.
	Warnings []string
}

BundleResult holds the resolved chain and metadata.

func Bundle

func Bundle(ctx context.Context, input BundleInput) (*BundleResult, error)

Bundle resolves the full certificate chain for a leaf certificate.

type CRLCheckResult added in v0.8.2

type CRLCheckResult struct {
	// Status is the check result: "good", "revoked", or "unavailable".
	// Unlike OCSPResult's "unknown" (an explicit responder status), "unavailable"
	// means the CRL could not be fetched, parsed, or verified.
	Status string `json:"status"`
	// URL is the CRL distribution point that was fetched.
	URL string `json:"url,omitempty"`
	// Detail provides context when Status is "unavailable" (the error message)
	// or "revoked" (the serial number).
	Detail string `json:"detail,omitempty"`
}

CRLCheckResult contains the result of a CRL revocation check during a TLS connection probe.

func CheckLeafCRL added in v0.8.2

func CheckLeafCRL(ctx context.Context, input CheckLeafCRLInput) *CRLCheckResult

CheckLeafCRL fetches the first HTTP CRL distribution point and checks whether the leaf certificate is revoked. The CRL signature is verified against the issuer certificate. Returns a best-effort result (never nil when called, but Status may be "unavailable").

type CRLInfo added in v0.8.2

type CRLInfo struct {
	// Issuer is the CRL issuer distinguished name.
	Issuer string `json:"issuer"`
	// ThisUpdate is when the CRL was generated (RFC 3339).
	ThisUpdate string `json:"this_update"`
	// NextUpdate is when the CRL expires (RFC 3339).
	NextUpdate string `json:"next_update"`
	// NumEntries is the number of revoked certificate entries.
	NumEntries int `json:"num_entries"`
	// SignatureAlgorithm is the algorithm used to sign the CRL.
	SignatureAlgorithm string `json:"signature_algorithm"`

	// CRLNumber is the CRL sequence number (omitted when not present).
	CRLNumber string `json:"crl_number,omitempty"`
	// AKI is the authority key identifier (omitted when not present).
	AKI string `json:"authority_key_id,omitempty"`
}

CRLInfo contains parsed CRL details for display.

func CRLInfoFromList added in v0.8.2

func CRLInfoFromList(crl *x509.RevocationList) *CRLInfo

CRLInfoFromList extracts display information from a parsed RevocationList.

type CSRSubject

type CSRSubject struct {
	CommonName         string   `json:"common_name"`
	Organization       []string `json:"organization,omitempty"`
	OrganizationalUnit []string `json:"organizational_unit,omitempty"`
	Country            []string `json:"country,omitempty"`
	Province           []string `json:"province,omitempty"`
	Locality           []string `json:"locality,omitempty"`
}

CSRSubject holds the subject fields for a CSR template.

type CSRTemplate

type CSRTemplate struct {
	// Subject contains the distinguished name fields for the CSR.
	Subject CSRSubject `json:"subject"`
	// Hosts lists the DNS names, IP addresses, URIs, and email addresses for SANs.
	Hosts []string `json:"hosts"`
	// OtherNames lists OtherName SAN entries (e.g. UPN for mTLS user certs).
	OtherNames []CSRTemplateOtherName `json:"other_names,omitempty"`
}

CSRTemplate is a JSON-serializable template for CSR generation.

func ParseCSRTemplate

func ParseCSRTemplate(data []byte) (*CSRTemplate, error)

ParseCSRTemplate unmarshals JSON data into a CSRTemplate.

type CSRTemplateOtherName added in v0.8.2

type CSRTemplateOtherName struct {
	// Type is a well-known label ("UPN", "SRV", "XMPP", "SmtpUTF8Mailbox")
	// or a dotted-decimal OID string.
	Type string `json:"type"`
	// Value is the string value for the OtherName entry.
	Value string `json:"value"`
}

CSRTemplateOtherName represents an OtherName SAN entry in a CSR template.

type CTResult added in v0.8.2

type CTResult struct {
	// Status is the aggregate result: ok, missing, unavailable, invalid, unknown-log, or mixed.
	Status string `json:"status"`
	// Total is the number of SCT entries processed.
	Total int `json:"total"`
	// Valid is the number of SCTs successfully verified.
	Valid int `json:"valid"`
	// Invalid is the number of malformed or unverifiable SCTs.
	Invalid int `json:"invalid"`
	// UnknownLog is the number of SCTs for logs not present in the CT log list.
	UnknownLog int `json:"unknown_log"`
	// Unavailable is the number of SCTs that could not be verified due to missing CT data.
	Unavailable int `json:"unavailable"`
	// SCTs are the per-SCT verification outcomes.
	SCTs []SCTInfo `json:"scts,omitempty"`
}

CTResult summarizes Certificate Transparency verification outcomes.

type ChainDiagnostic added in v0.8.2

type ChainDiagnostic struct {
	// Check is the diagnostic identifier (e.g. "root-in-chain", "duplicate-cert", "missing-intermediate").
	Check string `json:"check"`
	// Status is the severity level: "warn" for configuration issues, "error" for verification failures.
	Status string `json:"status"`
	// Detail is a human-readable description of the issue.
	Detail string `json:"detail"`
}

ChainDiagnostic describes a single chain configuration issue found during connection probing.

func DiagnoseCipherScan added in v0.8.2

func DiagnoseCipherScan(r *CipherScanResult) []ChainDiagnostic

DiagnoseCipherScan inspects cipher scan results and returns specific, actionable diagnostics for deprecated protocols, weak cipher modes, and insecure key exchange.

func DiagnoseConnectChain added in v0.8.2

func DiagnoseConnectChain(input DiagnoseConnectChainInput) []ChainDiagnostic

DiagnoseConnectChain inspects a server-presented certificate chain for misconfigurations: root certificates included in the chain (wastes bandwidth, per RFC 8446 §4.4.2) and duplicate certificates.

func DiagnoseNegotiatedCipher added in v0.8.2

func DiagnoseNegotiatedCipher(protocol, cipherSuite string) []ChainDiagnostic

DiagnoseNegotiatedCipher returns diagnostics for the cipher suite and protocol version that were actually negotiated during the TLS handshake. This catches issues like CBC mode or deprecated TLS versions even without a full --ciphers scan.

func DiagnoseVerifyError added in v0.8.2

func DiagnoseVerifyError(verifyErr error) []ChainDiagnostic

DiagnoseVerifyError returns diagnostics derived from a chain verification error. Currently detects hostname mismatches (x509.HostnameError).

type CheckCTInput added in v0.8.2

type CheckCTInput struct {
	// Chain is the certificate chain to verify SCTs against (leaf first).
	Chain []*x509.Certificate
	// TLSSCTs are serialized SCTs from the TLS handshake extension.
	TLSSCTs [][]byte
	// LogList overrides the embedded CT log list when provided.
	LogList []byte
}

CheckCTInput contains parameters for Certificate Transparency verification.

type CheckLeafCRLInput added in v0.8.2

type CheckLeafCRLInput struct {
	// Leaf is the certificate to check for revocation.
	Leaf *x509.Certificate
	// Issuer is the issuer certificate used to verify the CRL signature.
	Issuer *x509.Certificate
	// Timeout is the timeout for fetching the CRL (default: 5s).
	Timeout time.Duration
	// AllowPrivateNetworks allows CRL fetches to private/internal endpoints.
	AllowPrivateNetworks bool
}

CheckLeafCRLInput holds parameters for CheckLeafCRL.

type CheckOCSPInput added in v0.8.2

type CheckOCSPInput struct {
	// Cert is the certificate to check.
	Cert *x509.Certificate
	// Issuer is the issuer certificate (used to build the OCSP request).
	Issuer *x509.Certificate
	// AllowPrivateNetworks allows OCSP requests to private/internal endpoints.
	AllowPrivateNetworks bool
}

CheckOCSPInput contains parameters for an OCSP revocation check.

type CipherProbeResult added in v0.8.2

type CipherProbeResult struct {
	// Name is the IANA cipher suite name (e.g. "TLS_AES_128_GCM_SHA256").
	Name string `json:"name"`
	// ID is the numeric cipher suite identifier.
	ID uint16 `json:"id"`
	// Version is the TLS version string (e.g. "TLS 1.3").
	Version string `json:"version"`
	// KeyExchange is the key exchange mechanism (e.g. "ECDHE", "RSA").
	KeyExchange string `json:"key_exchange"`
	// Rating is the security quality assessment.
	Rating CipherRating `json:"rating"`
}

CipherProbeResult describes a single cipher suite accepted by the server.

type CipherRating added in v0.8.2

type CipherRating string

CipherRating indicates the security quality of a cipher suite.

const (
	// CipherRatingGood indicates TLS 1.3 suites or TLS 1.2 ECDHE+AEAD (GCM, ChaCha20-Poly1305).
	CipherRatingGood CipherRating = "good"
	// CipherRatingWeak indicates cipher suites that should be disabled:
	// anything in Go's InsecureCipherSuites(), CBC-mode ciphers, or non-ECDHE key exchange.
	CipherRatingWeak CipherRating = "weak"
)

func RateCipherSuite added in v0.8.2

func RateCipherSuite(cipherID uint16, tlsVersion uint16) CipherRating

RateCipherSuite returns the security rating for a cipher suite at a given TLS version.

type CipherScanResult added in v0.8.2

type CipherScanResult struct {
	// SupportedVersions lists the TLS versions the server supports (e.g. ["TLS 1.3", "TLS 1.2"]).
	SupportedVersions []string `json:"supported_versions"`
	// Ciphers lists all accepted cipher suites, sorted by version (descending) then rating.
	Ciphers []CipherProbeResult `json:"ciphers"`
	// QUICProbed is true when QUIC/UDP cipher probing was attempted.
	QUICProbed bool `json:"quic_probed"`
	// QUICCiphers lists TLS 1.3 cipher suites accepted over QUIC/UDP.
	QUICCiphers []CipherProbeResult `json:"quic_ciphers,omitempty"`
	// KeyExchanges lists accepted key exchange groups (classical and post-quantum).
	KeyExchanges []KeyExchangeProbeResult `json:"key_exchanges,omitempty"`
	// OverallRating is the worst rating among all accepted ciphers.
	// Empty when no ciphers were detected (omitted from JSON).
	OverallRating CipherRating `json:"overall_rating,omitempty"`
}

CipherScanResult contains the results of a cipher suite enumeration.

func ScanCipherSuites added in v0.8.2

func ScanCipherSuites(ctx context.Context, input ScanCipherSuitesInput) (*CipherScanResult, error)

ScanCipherSuites probes a TLS server to enumerate all supported cipher suites and key exchange groups. TLS 1.3 ciphers are probed using raw ClientHello packets (all 5 RFC 8446 suites). TLS 1.0–1.2 ciphers are probed using Go's crypto/tls with a single-cipher config. Key exchange groups are probed via raw ClientHello with individual named groups. All probes run concurrently.

type ClientAuthInfo added in v0.8.2

type ClientAuthInfo struct {
	// Requested is true when the server sent a CertificateRequest.
	Requested bool `json:"requested"`
	// AcceptableCAs are the DN strings of CAs the server trusts for client certs.
	AcceptableCAs []string `json:"acceptable_cas,omitempty"`
	// SignatureSchemes are the signature algorithms the server will accept.
	SignatureSchemes []string `json:"signature_schemes,omitempty"`
}

ClientAuthInfo describes the server's client certificate request (mTLS).

type ConnectResult added in v0.8.2

type ConnectResult struct {
	// Host is the hostname that was connected to.
	Host string `json:"host"`
	// Port is the TCP port that was connected to.
	Port string `json:"port"`
	// Protocol is the negotiated TLS version (e.g. "TLS 1.3").
	Protocol string `json:"protocol"`
	// CipherSuite is the negotiated cipher suite name.
	CipherSuite string `json:"cipher_suite"`
	// ServerName is the SNI value sent.
	ServerName string `json:"server_name"`
	// ALPN is the negotiated application protocol (e.g. "h2", "http/1.1").
	ALPN string `json:"alpn,omitempty"`
	// ClientAuth describes whether the server requested a client certificate (mTLS).
	ClientAuth *ClientAuthInfo `json:"client_auth,omitempty"`
	// PeerChain is the certificate chain presented by the server.
	PeerChain []*x509.Certificate `json:"-"`
	// TLSSCTs contains serialized SCTs from the TLS handshake extension.
	TLSSCTs [][]byte `json:"-"`
	// VerifiedChains contains the verified certificate chains.
	VerifiedChains [][]*x509.Certificate `json:"-"`
	// VerifyError is non-empty if chain verification failed.
	VerifyError string `json:"verify_error,omitempty"`
	// Diagnostics contains chain configuration warnings (root-in-chain, duplicate-cert, missing-intermediate).
	Diagnostics []ChainDiagnostic `json:"diagnostics,omitempty"`
	// AIAFetched is true when missing intermediates were successfully fetched via AIA.
	AIAFetched bool `json:"aia_fetched,omitempty"`
	// OCSP contains the leaf certificate's OCSP revocation status.
	// Nil only when OCSP is explicitly disabled (DisableOCSP is true).
	// Status "skipped" means preconditions were not met (no issuer in chain,
	// or no OCSP responder URL). Status "unavailable" means the query was
	// attempted but failed (network error, parse error, etc.).
	OCSP *OCSPResult `json:"ocsp,omitempty"`
	// CRL contains the leaf certificate's CRL revocation status.
	// Nil when CRL checking is not requested (CheckCRL is false).
	CRL *CRLCheckResult `json:"crl,omitempty"`
	// CipherScan contains the cipher suite enumeration results.
	// Nil when cipher scanning is not requested.
	CipherScan *CipherScanResult `json:"cipher_scan,omitempty"`
	// CT contains Certificate Transparency verification results.
	CT *CTResult `json:"ct,omitempty"`
	// LegacyProbe is true when the certificate chain was obtained via a raw
	// TLS handshake (legacy fallback) because Go's crypto/tls could not
	// negotiate any cipher suite. The chain is still valid for inspection
	// but no full TLS connection was established.
	LegacyProbe bool `json:"legacy_probe,omitempty"`
}

ConnectResult contains the results of a TLS connection probe.

func ConnectTLS added in v0.8.2

func ConnectTLS(ctx context.Context, input ConnectTLSInput) (*ConnectResult, error)

ConnectTLS connects to a TLS server and returns connection details including the negotiated protocol, cipher suite, and peer certificate chain.

type ConnectTLSInput added in v0.8.2

type ConnectTLSInput struct {
	// Host is the hostname or IP to connect to.
	Host string
	// Port is the TCP port (default: "443").
	Port string
	// ConnectTimeout is used when ctx has no deadline (default: 10s).
	ConnectTimeout time.Duration
	// ServerName overrides the SNI hostname (defaults to Host).
	ServerName string
	// DisableAIA disables automatic AIA certificate fetching when chain verification fails.
	DisableAIA bool
	// AIATimeout is the timeout for AIA certificate fetching (default: 5s).
	AIATimeout time.Duration
	// DisableOCSP disables the automatic best-effort OCSP check on the leaf certificate.
	DisableOCSP bool
	// OCSPTimeout is the timeout for OCSP checking (default: 5s).
	OCSPTimeout time.Duration
	// CheckCRL enables CRL-based revocation checking on the leaf certificate.
	CheckCRL bool
	// CRLTimeout is the timeout for CRL fetching (default: 5s).
	CRLTimeout time.Duration
	// RootCAs overrides system roots for chain verification. When nil,
	// the system root pool is used. Useful for testing against private CAs.
	RootCAs *x509.CertPool
	// AllowPrivateNetworks allows AIA/OCSP/CRL fetches to private/internal endpoints.
	AllowPrivateNetworks bool
}

ConnectTLSInput contains parameters for a TLS connection probe.

type DecodedJKSKeyEntry added in v0.8.2

type DecodedJKSKeyEntry struct {
	Alias string
	Key   crypto.PrivateKey
	Chain []*x509.Certificate
}

DecodedJKSKeyEntry represents one decoded JKS PrivateKeyEntry with its alias and certificate chain.

func DecodeJKSKeyEntries added in v0.8.2

func DecodeJKSKeyEntries(data []byte, passwords []string) ([]DecodedJKSKeyEntry, []*x509.Certificate, error)

DecodeJKSKeyEntries decodes a Java KeyStore (JKS) and returns decoded private key entries (with alias + chain) and trusted-certificate entries. Passwords are tried in order to open the store, and each private key entry is attempted with all provided passwords to support different store/key passwords.

type DiagnoseConnectChainInput added in v0.8.2

type DiagnoseConnectChainInput struct {
	// PeerChain is the certificate chain presented by the server.
	PeerChain []*x509.Certificate
}

DiagnoseConnectChainInput contains parameters for diagnosing a TLS peer chain.

type FetchAIACertificatesInput added in v0.8.2

type FetchAIACertificatesInput struct {
	// Cert is the leaf or intermediate whose AIA URLs will be followed.
	Cert *x509.Certificate
	// Timeout is the HTTP request timeout for AIA fetches.
	Timeout time.Duration
	// MaxDepth is the maximum number of AIA hops to follow.
	MaxDepth int
	// AllowPrivateNetworks allows AIA fetches to private/internal endpoints.
	AllowPrivateNetworks bool
}

FetchAIACertificatesInput holds parameters for FetchAIACertificates.

type FetchCRLInput added in v0.8.2

type FetchCRLInput struct {
	// URL is the HTTP or HTTPS URL to download the CRL from.
	URL string
	// AllowPrivateNetworks bypasses SSRF validation for the initial URL and
	// redirects. Set to true when the URL is user-provided (CLI), false when
	// it comes from a certificate extension (automated revocation checking).
	AllowPrivateNetworks bool
}

FetchCRLInput holds parameters for FetchCRL.

type FetchLeafFromURLInput added in v0.8.2

type FetchLeafFromURLInput struct {
	// URL is the HTTPS URL to connect to.
	URL string
	// Timeout controls the TCP/TLS dial timeout.
	Timeout time.Duration
}

FetchLeafFromURLInput holds parameters for FetchLeafFromURL.

type JKSEntry added in v0.8.2

type JKSEntry struct {
	PrivateKey crypto.PrivateKey
	Leaf       *x509.Certificate
	CACerts    []*x509.Certificate
	Alias      string
}

JKSEntry describes a single private key entry for EncodeJKSEntries.

type KeyExchangeProbeResult added in v0.8.2

type KeyExchangeProbeResult struct {
	// Name is the human-readable group name (e.g. "X25519", "X25519MLKEM768").
	Name string `json:"name"`
	// ID is the TLS CurveID / NamedGroup identifier.
	ID uint16 `json:"id"`
	// PostQuantum is true for hybrid post-quantum key exchange mechanisms.
	PostQuantum bool `json:"post_quantum,omitempty"`
}

KeyExchangeProbeResult describes a single key exchange group accepted by the server.

type MarshalSANExtensionInput added in v0.8.2

type MarshalSANExtensionInput struct {
	DNSNames       []string
	EmailAddresses []string
	IPAddresses    []net.IP
	URIs           []*url.URL
	OtherNames     []OtherNameSAN
}

MarshalSANExtensionInput holds all SAN types for building a complete SubjectAltName extension. Use this when OtherName entries are needed alongside standard SAN types.

type OCSPResult added in v0.8.2

type OCSPResult struct {
	// Status is "good", "revoked", "unknown", "unavailable", or "skipped".
	Status string `json:"status"`
	// SerialNumber is the certificate serial in hex.
	SerialNumber string `json:"serial,omitempty"`
	// URL is the OCSP responder that was queried.
	URL string `json:"url,omitempty"`
	// ThisUpdate is when the OCSP response was generated (RFC 3339).
	ThisUpdate string `json:"this_update,omitempty"`
	// NextUpdate is when the OCSP response expires (RFC 3339).
	NextUpdate string `json:"next_update,omitempty"`
	// RevokedAt is the revocation time in RFC 3339 (only set when Status is "revoked").
	RevokedAt *string `json:"revoked_at,omitempty"`
	// RevocationReason is the reason code (only set when Status is "revoked").
	RevocationReason *string `json:"revocation_reason,omitempty"`
	// Detail provides context when Status is "skipped" or "unavailable".
	Detail string `json:"detail,omitempty"`
}

OCSPResult contains the OCSP response details.

func CheckOCSP added in v0.8.2

func CheckOCSP(ctx context.Context, input CheckOCSPInput) (*OCSPResult, error)

CheckOCSP queries the OCSP responder for a certificate's revocation status. The OCSP responder URL is read from the certificate's AIA extension.

type OtherNameSAN added in v0.8.2

type OtherNameSAN struct {
	OID   asn1.ObjectIdentifier
	Value string
}

OtherNameSAN represents a single OtherName entry in a Subject Alternative Name extension. OID identifies the type (e.g. UPN, SRV) and Value holds the string representation.

type SCTInfo added in v0.8.2

type SCTInfo struct {
	// Source indicates whether the SCT came from the TLS extension or the cert.
	Source string `json:"source"`
	// LogID is the base64-encoded SHA-256 hash of the SCT log key.
	LogID string `json:"log_id,omitempty"`
	// LogName is the human-readable name from the CT log list.
	LogName string `json:"log_name,omitempty"`
	// Timestamp is the SCT timestamp in RFC 3339 format.
	Timestamp string `json:"timestamp,omitempty"`
	// Status indicates this SCT outcome: valid, invalid, unknown-log, or unavailable.
	Status string `json:"status"`
	// Detail contains optional context about the SCT outcome.
	Detail string `json:"detail,omitempty"`
}

SCTInfo describes a single SCT verification result.

type ScanCipherSuitesInput added in v0.8.2

type ScanCipherSuitesInput struct {
	// Host is the hostname or IP to connect to.
	Host string
	// Port is the TCP port (default: "443").
	Port string
	// ServerName overrides the SNI hostname (defaults to Host).
	ServerName string
	// Concurrency is the maximum number of parallel probe connections (default: 10).
	Concurrency int
	// ProbeQUIC enables QUIC/UDP cipher probing alongside TCP.
	ProbeQUIC bool
}

ScanCipherSuitesInput contains parameters for ScanCipherSuites.

type SelfSignedInput added in v0.8.2

type SelfSignedInput struct {
	// Signer is the private key used to sign the certificate.
	Signer crypto.Signer
	// Subject is the distinguished name for the certificate.
	Subject pkix.Name
	// Days is the validity period in days (default: 3650).
	Days int
	// IsCA sets the CA basic constraint.
	IsCA bool
}

SelfSignedInput contains parameters for self-signed certificate generation.

type SignCSRInput added in v0.8.2

type SignCSRInput struct {
	// CSR is the certificate signing request to sign.
	CSR *x509.CertificateRequest
	// CACert is the CA certificate used as the issuer.
	CACert *x509.Certificate
	// CAKey is the CA's private key used to sign.
	CAKey crypto.Signer
	// Days is the validity period in days (default: 365).
	Days int
	// CopySANs copies DNS names, IP addresses, email addresses, and URIs
	// from the CSR to the issued certificate.
	CopySANs bool
}

SignCSRInput contains parameters for signing a CSR with a CA.

type ValidateAIAURLInput added in v0.8.2

type ValidateAIAURLInput struct {
	// URL is the candidate URL to validate.
	URL string
	// AllowPrivateNetworks bypasses private/internal IP checks.
	AllowPrivateNetworks bool
	// contains filtered or unexported fields
}

ValidateAIAURLInput holds parameters for ValidateAIAURLWithOptions.

type VerifyChainTrustInput added in v0.8.0

type VerifyChainTrustInput struct {
	Cert          *x509.Certificate
	Roots         *x509.CertPool
	Intermediates *x509.CertPool
}

VerifyChainTrustInput holds parameters for VerifyChainTrust.

Directories

Path Synopsis
cmd
certkit command
wasm command
Package main implements a WASM build of certkit for browser-based certificate processing.
Package main implements a WASM build of certkit for browser-based certificate processing.
certstore
Package certstore provides a shared certificate and key processing pipeline used by both the CLI and WASM builds.
Package certstore provides a shared certificate and key processing pipeline used by both the CLI and WASM builds.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL