Documentation
¶
Overview ¶
Package certkit provides certificate parsing, encoding, identification, chain bundling, PKCS#12/7, and CSR generation utilities.
Index ¶
- func CertAKIEmbedded(cert *x509.Certificate) string
- func CertExpiresWithin(cert *x509.Certificate, d time.Duration) bool
- func CertFingerprint(cert *x509.Certificate) string
- func CertFingerprintColonSHA1(cert *x509.Certificate) string
- func CertFingerprintColonSHA256(cert *x509.Certificate) string
- func CertFingerprintSHA1(cert *x509.Certificate) string
- func CertSKI(cert *x509.Certificate) string
- func CertSKIEmbedded(cert *x509.Certificate) string
- func CertToPEM(cert *x509.Certificate) string
- func ClassifyHosts(hosts []string) (dnsNames []string, ips []net.IP, uris []*url.URL, emails []string)
- func ColonHex(b []byte) string
- func ComputeSKI(pub crypto.PublicKey) ([]byte, error)
- func ComputeSKILegacy(pub crypto.PublicKey) ([]byte, error)
- func DecodeJKS(data []byte, passwords []string) ([]*x509.Certificate, []crypto.PrivateKey, error)
- func DecodePKCS7(derData []byte) ([]*x509.Certificate, error)
- func DecodePKCS12(pfxData []byte, password string) (crypto.PrivateKey, *x509.Certificate, []*x509.Certificate, error)
- func DeduplicatePasswords(extra []string) []string
- func DefaultPasswords() []string
- func EncodeJKS(privateKey crypto.PrivateKey, leaf *x509.Certificate, ...) ([]byte, error)
- func EncodePKCS7(certs []*x509.Certificate) ([]byte, error)
- func EncodePKCS12(privateKey crypto.PrivateKey, leaf *x509.Certificate, ...) ([]byte, error)
- func EncodePKCS12Legacy(privateKey crypto.PrivateKey, leaf *x509.Certificate, ...) ([]byte, error)
- func FetchAIACertificates(ctx context.Context, cert *x509.Certificate, timeout time.Duration, ...) ([]*x509.Certificate, []string)
- func FetchLeafFromURL(ctx context.Context, rawURL string, timeout time.Duration) (*x509.Certificate, error)
- func FormatDN(name pkix.Name) string
- func FormatEKUOIDs(raw []byte) []string
- func FormatEKUs(ekus []x509.ExtKeyUsage) []string
- func FormatKeyUsage(ku x509.KeyUsage) []string
- func FormatKeyUsageBitString(raw []byte) []string
- func GenerateCSR(leaf *x509.Certificate, privateKey crypto.PrivateKey) (csrPEM string, keyPEM string, err error)
- func GenerateCSRFromCSR(source *x509.CertificateRequest, signer crypto.Signer) (string, error)
- func GenerateCSRFromTemplate(tmpl *CSRTemplate, signer crypto.Signer) (string, error)
- func GenerateECKey(curve elliptic.Curve) (*ecdsa.PrivateKey, error)
- func GenerateEd25519Key() (ed25519.PublicKey, ed25519.PrivateKey, error)
- func GenerateRSAKey(bits int) (*rsa.PrivateKey, error)
- func GetCertificateType(cert *x509.Certificate) string
- func GetPublicKey(priv crypto.PrivateKey) (crypto.PublicKey, error)
- func IsIssuedByMozillaRoot(cert *x509.Certificate) bool
- func IsMozillaRoot(cert *x509.Certificate) bool
- func IsPEM(data []byte) bool
- func KeyAlgorithmName(key crypto.PrivateKey) string
- func KeyMatchesCert(priv crypto.PrivateKey, cert *x509.Certificate) (bool, error)
- func MarshalPrivateKeyToPEM(key crypto.PrivateKey) (string, error)
- func MarshalPublicKeyToPEM(pub crypto.PublicKey) (string, error)
- func MozillaRootPEM() []byte
- func MozillaRootPool() (*x509.CertPool, error)
- func MozillaRootSubjects() map[string]bool
- func ParseCertificatesAny(data []byte) ([]*x509.Certificate, error)
- func ParseOtherNameSANs(extensions []pkix.Extension) []string
- func ParsePEMCertificate(pemData []byte) (*x509.Certificate, error)
- func ParsePEMCertificateRequest(pemData []byte) (*x509.CertificateRequest, error)
- func ParsePEMCertificates(pemData []byte) ([]*x509.Certificate, error)
- func ParsePEMPrivateKey(pemData []byte) (crypto.PrivateKey, error)
- func ParsePEMPrivateKeyWithPasswords(pemData []byte, passwords []string) (crypto.PrivateKey, error)
- func PublicKeyAlgorithmName(key crypto.PublicKey) string
- func ValidateAIAURL(rawURL string) error
- func VerifyCSR(csr *x509.CertificateRequest) error
- func VerifyChainTrust(input VerifyChainTrustInput) bool
- type BundleOptions
- type BundleResult
- type CSRSubject
- type CSRTemplate
- type VerifyChainTrustInput
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
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 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 ComputeSKI ¶ added in v0.2.1
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
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 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
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 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, cert *x509.Certificate, timeout time.Duration, maxDepth int) ([]*x509.Certificate, []string)
FetchAIACertificates follows AIA CA Issuers URLs to fetch intermediate certificates.
func FetchLeafFromURL ¶
func FetchLeafFromURL(ctx context.Context, rawURL string, timeout time.Duration) (*x509.Certificate, error)
FetchLeafFromURL connects to the given HTTPS URL via TLS and returns the leaf (server) certificate from the handshake.
func FormatDN ¶ added in v0.8.1
FormatDN formats a pkix.Name as a Distinguished Name string. Unlike pkix.Name.String(), it renders the emailAddress OID (1.2.840.113549.1.9.1) and serialNumber OID (2.5.4.5) with their standard labels instead of raw OID=#hex notation.
func FormatEKUOIDs ¶ added in v0.8.1
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
FormatKeyUsage returns human-readable names for key usage bits.
func FormatKeyUsageBitString ¶ added in v0.8.1
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 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 ¶
GenerateCSRFromCSR creates a new CSR using an existing CSR as template, signed by the provided key.
func GenerateCSRFromTemplate ¶
func GenerateCSRFromTemplate(tmpl *CSRTemplate, signer crypto.Signer) (string, error)
GenerateCSRFromTemplate creates a PEM-encoded CSR from a template and signer.
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 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 ¶
MarshalPublicKeyToPEM marshals a public key to PKIX PEM format. Supports RSA, ECDSA, and Ed25519 public keys.
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
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
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 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
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 PublicKeyAlgorithmName ¶
PublicKeyAlgorithmName returns a human-readable name for a public key's algorithm.
func ValidateAIAURL ¶ added in v0.8.0
ValidateAIAURL checks whether a URL is safe to fetch for AIA certificate resolution. It rejects non-HTTP(S) schemes and literal private/loopback/ link-local IP addresses to prevent SSRF.
Known limitation: hostnames that resolve to private IPs are intentionally allowed. This means DNS rebinding (a hostname resolving to a public IP at validation time, then to a private IP at connection time) is theoretically possible. We accept this because:
- certkit is a short-lived CLI process — the window between ValidateAIAURL and the HTTP request is ~2ms, making rebinding impractical to exploit.
- Blocking hostnames that resolve to private IPs would break legitimate internal CAs whose AIA endpoints are on private networks.
- Adding net.Dialer.Control to check resolved IPs doesn't help: if we allow private IPs for internal CAs, the check is the same TOCTOU race.
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 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
}
BundleOptions configures chain resolution.
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, leaf *x509.Certificate, opts BundleOptions) (*BundleResult, error)
Bundle resolves the full certificate chain for a leaf certificate.
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"`
}
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 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. |