certutil

package
v0.8.1 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2026 License: AGPL-3.0 Imports: 14 Imported by: 0

Documentation

Overview

Package certutil provides common helper functions shared across the ratls project: serial number generation, fingerprinting, PEM encoding, and more.

Index

Constants

View Source
const LeafValiditySkew = 5 * time.Minute

LeafValiditySkew is the single bounded clock-skew allowance every certificate-sourced verification path grants NotBefore: a leaf issued up to this long in the verifier's future is accepted, anything further is not. NotAfter gets no allowance — an expired certificate is expired. 5 minutes covers realistic clock drift between an issuing TEE and a verifying operator machine without meaningfully extending a stolen-cert window.

Variables

View Source
var OIDAttestationDigest = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 66378, 1, 2}

OIDAttestationDigest marks issued certificates with a SHA-256 of the attestation evidence that authorized issuance — an audit-trail extension shared between the CDS HTTP signer and the in-process issuer.

Functions

func AppendAttestationDigest

func AppendAttestationDigest(tmpl *x509.Certificate, digest []byte) error

AppendAttestationDigest stamps an OIDAttestationDigest extension carrying the given digest onto tmpl. No-op when digest is empty.

func CertFingerprint

func CertFingerprint(raw []byte) string

CertFingerprint returns the lowercase hex SHA-256 fingerprint of raw certificate bytes (DER or x509.Certificate.Raw).

func CheckValidity

func CheckValidity(cert *x509.Certificate, now time.Time) error

CheckValidity enforces the validity window every certificate-sourced trust decision shares: NotBefore may sit up to LeafValiditySkew in now's future (clock drift between issuer and verifier), NotAfter gets no allowance. It is the single implementation of that window — call it rather than re-deriving the comparison, so the skew policy cannot drift between sites.

func EncodeCertPEM

func EncodeCertPEM(certDER []byte) []byte

EncodeCertPEM encodes DER certificate bytes as a PEM block.

func GenerateSerial

func GenerateSerial() (*big.Int, error)

GenerateSerial returns a cryptographically random 128-bit serial number suitable for X.509 certificates.

func LoadCertificateFile

func LoadCertificateFile(path string) (*x509.Certificate, error)

LoadCertificateFile reads a PEM file and parses the first certificate.

func LoadECPrivateKeyFile

func LoadECPrivateKeyFile(path string) (*ecdsa.PrivateKey, error)

LoadECPrivateKeyFile reads a PEM file and parses the EC private key.

func LoadPEMCertificatesFile

func LoadPEMCertificatesFile(path string) ([]*x509.Certificate, error)

LoadPEMCertificatesFile reads a PEM file and parses all CERTIFICATE blocks.

func MarshalECKeyPEM

func MarshalECKeyPEM(key *ecdsa.PrivateKey) ([]byte, error)

MarshalECKeyPEM marshals an EC private key to PKCS#8 PEM format. PKCS#8 ("PRIVATE KEY" header) is what CDS and the rest of the stack expect; SEC 1 ("EC PRIVATE KEY") fails to parse with x509.ParsePKCS8PrivateKey.

func NewCATemplate

func NewCATemplate(serial *big.Int, commonName string, notAfter time.Time) *x509.Certificate

NewCATemplate returns an x509.Certificate template for a self-signed CA with the given serial number, subject common name, and expiry time.

func NewJSONLogger

func NewJSONLogger(levelStr string) (*slog.Logger, error)

NewJSONLogger creates a JSON slog.Logger writing to stdout at the given level string. An empty string selects info; any other value must be one of debug, info, warn, error (case-insensitive) or an error is returned, so a typo fails at startup rather than silently logging at info.

func NewJSONLoggerTo

func NewJSONLoggerTo(w io.Writer, levelStr string) (*slog.Logger, error)

NewJSONLoggerTo is NewJSONLogger with an explicit writer, for commands that must keep stdout reserved for machine-readable output and send diagnostics to stderr.

func NewLeafTemplate

func NewLeafTemplate(commonName string, ttl time.Duration) (*x509.Certificate, error)

NewLeafTemplate returns the canonical x509 leaf-certificate template used by the c8s issuers: digital-signature key usage and Server+Client extended key usage, anchored at time.Now() with the given TTL. Callers populate DNSNames / IPAddresses on the returned template themselves so SAN policy stays at the call site.

func ParseCertificatePEM

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

ParseCertificatePEM parses a PEM-encoded certificate, returning the first CERTIFICATE block found. Use LoadCertificateFile for file-based loading.

func ParseECPrivateKey

func ParseECPrivateKey(data []byte) (*ecdsa.PrivateKey, error)

ParseECPrivateKey parses a PEM-encoded EC private key, trying PKCS8 first then SEC 1 (EC) format.

func ParsePEMCertificates

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

ParsePEMCertificates parses all CERTIFICATE PEM blocks from data and returns the parsed certificates. It returns an error if no certificate blocks are found.

func TrimExpiredCABundle

func TrimExpiredCABundle(certs []*x509.Certificate, cutoff time.Time) (kept, dropped []*x509.Certificate)

TrimExpiredCABundle returns the subset of certs whose NotAfter is after cutoff. The dropped certs are returned in dropped — callers typically log their fingerprints. Order is preserved relative to the input.

Types

type BodyAuthentication

type BodyAuthentication int

BodyAuthentication classifies what AuthenticateLeafBody proved about a certificate's body fields. It is a named type rather than a bool because the zero value — "nothing here authenticated it" — is the one a caller must never treat as a pass: x509.ParseCertificate verifies no signature at all, so an Issuer DN that differs from the Subject by one byte is enough to skip the self-signature check with an arbitrary Signature field.

const (
	// BodyCAVouched means the certificate is not self-issued: its body is
	// vouched only by whoever signed it, and NOTHING in AuthenticateLeafBody
	// checked that signature. Until the caller verifies the issuing chain (or
	// holds live proof the presenter controls the attested key), every body
	// field — subject, serial, NotAfter, the CA-vouched extensions — is
	// attacker-choosable under a genuine attestation extension. This is the
	// zero value so a discarded classification fails closed.
	BodyCAVouched BodyAuthentication = iota
	// BodySelfSigned means the certificate is self-issued and its body
	// verified under its own embedded (attested) key, so the attestation that
	// binds the key transitively covers the whole body.
	BodySelfSigned
)

func AuthenticateLeafBody

func AuthenticateLeafBody(cert *x509.Certificate, now time.Time) (BodyAuthentication, error)

AuthenticateLeafBody enforces the certificate-body checks shared by every path that verifies a certificate-embedded attestation:

  • validity: NotBefore within LeafValiditySkew, NotAfter with no allowance. A nonce-free attested certificate is replayable for as long as it validates, so once the body is authenticated the validity window is the only freshness bound these paths have — skipping it would make the replay window unbounded. Note the ordering: the window bounds nothing on its own, since an unauthenticated body's NotAfter is chosen by whoever wrote the bytes.
  • self-issued certificates (RawIssuer == RawSubject) must verify their own signature with their embedded key. The attestation extension binds only the public key, so without this check any field outside the key — subject, serial, validity, other extensions — could be rewritten under a genuine attestation and still verify.

The returned BodyAuthentication says which of those two states the caller is in. BodyCAVouched is NOT a pass: it means the caller still owes the body an authentication step (a verified chain, or proof of possession of the attested key) before trusting anything the body says.

The validity window is CheckValidity's, so the skew policy has one implementation shared with every other certificate-sourced trust decision.

func (BodyAuthentication) String

func (b BodyAuthentication) String() string

Jump to

Keyboard shortcuts

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