pki

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: May 1, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package pki provides Certificate Authority operations on top of an IronHand vault session. A vault can be initialised as a CA; certificates are then issued, revoked, renewed and tracked as regular vault items while CA state lives in reserved items protected from the normal CRUD API.

Index

Constants

View Source
const (
	FieldSubject           = "subject"
	FieldIssuer            = "issuer"
	FieldSerialNumber      = "serial_number"
	FieldNotBefore         = "not_before"
	FieldNotAfter          = "not_after"
	FieldCertificate       = "certificate"
	FieldPrivateKey        = "private_key"
	FieldChain             = "chain"
	FieldFingerprintSHA256 = "fingerprint_sha256"
	FieldKeyAlgorithm      = "key_algorithm"
	FieldStatus            = "status"
	FieldIssuedByCA        = "issued_by_ca"
	FieldPreviousItemID    = "previous_item_id"
	FieldNotes             = "notes"
)
View Source
const (
	StatusActive  = "active"
	StatusExpired = "expired"
	StatusRevoked = "revoked"
)

Certificate status values.

View Source
const PKCS11Prefix = "PKCS11:"

PKCS11Prefix is the string prefix stored in vault fields to identify PKCS#11-managed keys. Available regardless of build tag for reference by other packages.

Variables

View Source
var (
	// ErrNotCA is returned when a CA operation is attempted on a vault that
	// has not been initialised as a CA.
	ErrNotCA = errors.New("vault is not initialized as a CA")

	// ErrAlreadyCA is returned when InitCA is called on a vault that already
	// has CA state.
	ErrAlreadyCA = errors.New("vault is already initialized as a CA")

	// ErrCertNotFound is returned when the referenced certificate item does
	// not exist in the vault.
	ErrCertNotFound = errors.New("certificate item not found")

	// ErrCertAlreadyRevoked is returned when attempting to revoke a
	// certificate that is already revoked.
	ErrCertAlreadyRevoked = errors.New("certificate is already revoked")

	// ErrInvalidPEM is returned when PEM data cannot be decoded or parsed.
	ErrInvalidPEM = errors.New("invalid PEM data")

	// ErrNotCertificateItem is returned when an operation that requires a
	// certificate item is invoked on an item of a different type.
	ErrNotCertificateItem = errors.New("item is not a certificate")

	// ErrNoCRL is returned when no cached CRL has been generated yet.
	ErrNoCRL = errors.New("no CRL has been generated")
)
View Source
var ErrKeyNotExportable = fmt.Errorf("private key is not exportable")

ErrKeyNotExportable is returned by KeyStore.ExportPEM when the backing store does not allow private key material to leave the device (e.g. HSM).

View Source
var ErrKeyNotFound = fmt.Errorf("key not found")

ErrKeyNotFound is returned when the referenced key ID does not exist.

Functions

func GenerateCRL

func GenerateCRL(ctx context.Context, session *vault.Session, ks KeyStore) ([]byte, error)

GenerateCRL creates a Certificate Revocation List from the CA's revocation entries. The CRL is signed with the CA key (via the provided KeyStore, or a default SoftwareKeyStore when ks is nil) and returned as PEM-encoded bytes.

func GetCACertificate

func GetCACertificate(ctx context.Context, session *vault.Session) (string, error)

GetCACertificate returns the CA certificate PEM string.

func InitCA

func InitCA(ctx context.Context, session *vault.Session, subject pkix.Name, validityYears int, isIntermediate bool, ks KeyStore) error

InitCA initialises a vault as a Certificate Authority. It generates a keypair via the provided KeyStore (or a default SoftwareKeyStore when ks is nil), creates a self-signed root CA certificate, and stores CA cert + key + state in reserved items.

func IsReservedItemID

func IsReservedItemID(itemID string) bool

IsReservedItemID reports whether itemID is reserved by the PKI subsystem.

func IssueCertificate

func IssueCertificate(ctx context.Context, session *vault.Session, req IssueCertRequest, ks KeyStore) (string, error)

IssueCertificate generates a new keypair via the provided KeyStore (or a default SoftwareKeyStore when ks is nil), creates a certificate signed by the vault's CA, stores it as a regular vault item, and returns the item ID.

func LoadCRL

func LoadCRL(ctx context.Context, session *vault.Session) ([]byte, error)

LoadCRL returns the most recently generated (cached) CRL PEM bytes. It returns ErrNoCRL if no CRL has been generated yet, and ErrNotCA if the vault is not initialised as a CA.

func ParseCertificatePEM

func ParseCertificatePEM(certPEM string) (map[string]string, error)

ParseCertificatePEM decodes a PEM certificate and returns a map of well-known field values extracted from the parsed x509 certificate.

func RenewCertificate

func RenewCertificate(ctx context.Context, session *vault.Session, itemID string, validityDays int, ks KeyStore) (string, error)

RenewCertificate re-issues a certificate with the same parameters but a new serial number and validity period. The old certificate is revoked with reason Superseded (4). Returns the new item ID. The KeyStore parameter may be nil to use the default SoftwareKeyStore.

func ReservedItemIDs

func ReservedItemIDs() []string

ReservedItemIDs returns the set of reserved item IDs used by the PKI subsystem. The API layer uses this to block user-facing CRUD access.

func RevokeCertificate

func RevokeCertificate(ctx context.Context, session *vault.Session, itemID string, reason int) error

RevokeCertificate marks a certificate item as revoked and adds it to the CA's revocation list. The reason parameter is an x509 CRL reason code (0 = Unspecified, 1 = KeyCompromise, 4 = Superseded, etc.).

func SignCSR

func SignCSR(ctx context.Context, session *vault.Session, csrPEM string, validityDays int, extKeyUsages []x509.ExtKeyUsage, ks KeyStore) (string, error)

SignCSR signs an externally-generated Certificate Signing Request with the CA's key (via the provided KeyStore, or a default SoftwareKeyStore when ks is nil), stores the issued certificate as a vault item (without a private key, since the requester keeps their own), and returns the item ID.

Types

type CAInfo

type CAInfo struct {
	IsCA           bool   `json:"is_ca"`
	IsIntermediate bool   `json:"is_intermediate"`
	Subject        string `json:"subject"`
	NotBefore      string `json:"not_before"`
	NotAfter       string `json:"not_after"`
	NextSerial     int64  `json:"next_serial"`
	CRLNumber      int64  `json:"crl_number"`
	CertCount      int    `json:"cert_count"`
}

CAInfo is the public information about a CA vault, returned to API callers.

func GetCAInfo

func GetCAInfo(ctx context.Context, session *vault.Session) (*CAInfo, error)

GetCAInfo returns public metadata about the CA vault.

type CAState

type CAState struct {
	IsCA           bool   `json:"is_ca"`
	IsIntermediate bool   `json:"is_intermediate"`
	NextSerial     int64  `json:"next_serial"`
	Subject        string `json:"subject"`
	NotBefore      string `json:"not_before"`
	NotAfter       string `json:"not_after"`
	CRLNumber      int64  `json:"crl_number"`
}

CAState is the persistent metadata for a CA vault.

type IssueCertRequest

type IssueCertRequest struct {
	Subject        pkix.Name
	ValidityDays   int
	KeyUsages      x509.KeyUsage
	ExtKeyUsages   []x509.ExtKeyUsage
	DNSNames       []string
	IPAddresses    []net.IP
	EmailAddresses []string
}

IssueCertRequest holds the parameters for issuing a new certificate.

type KeyStore

type KeyStore interface {
	// GenerateKey creates a new signing key and returns an opaque identifier.
	// The caller must not assume anything about the key material — for HSM/KMS
	// backends the private key never leaves the hardware.
	GenerateKey() (keyID string, err error)

	// Signer returns a [crypto.Signer] for the key identified by keyID.
	// The returned Signer is used by x509.CreateCertificate and
	// x509.CreateRevocationList, which only need the Sign method and
	// Public() for embedding the public key in certificates.
	//
	// For software keys this wraps the *ecdsa.PrivateKey; for HSM/KMS
	// implementations it delegates signing to the external device.
	Signer(keyID string) (crypto.Signer, error)

	// ExportPEM returns the private key in PEM-encoded PKCS8 or SEC1 format.
	// HSM/KMS implementations may return ErrKeyNotExportable, or a reference
	// string (e.g. "PKCS11:<label>") that ImportPEM can later interpret.
	ExportPEM(keyID string) (string, error)

	// ImportPEM loads a PEM-encoded private key into the store and returns
	// its key ID. This is used when reading existing keys from vault storage.
	// HSM/KMS implementations may return ErrKeyNotExportable for real PEM data,
	// or interpret reference strings produced by their own ExportPEM.
	ImportPEM(pemData string) (keyID string, err error)

	// Delete removes the key identified by keyID from the store.
	// For software stores this is a no-op (vault manages lifecycle).
	// For HSM/KMS this might schedule key destruction.
	Delete(keyID string) error
}

KeyStore abstracts private-key operations so that the PKI subsystem can work with software keys stored in the vault, HSM-backed keys, or cloud KMS keys without changing calling code.

Each KeyStore implementation is responsible for generating, storing, and signing with private keys. A KeyID uniquely identifies a key managed by the store; its format is implementation-defined (e.g. a vault item ID, an HSM slot reference, or a KMS key ARN).

type PKCS11Config

type PKCS11Config struct {
	ModulePath string
	TokenLabel string
	PIN        string
	SlotNumber *int
}

PKCS11Config holds the configuration for connecting to a PKCS#11 token. This is a placeholder when the pkcs11 build tag is not set.

type PKCS11KeyStore

type PKCS11KeyStore struct{}

PKCS11KeyStore is a placeholder type when the pkcs11 build tag is not set. It implements KeyStore so that the server CLI compiles without CGo, but all methods return errors directing the user to rebuild with -tags pkcs11.

func NewPKCS11KeyStore

func NewPKCS11KeyStore(_ PKCS11Config) (*PKCS11KeyStore, error)

NewPKCS11KeyStore returns an error when compiled without the pkcs11 build tag. Rebuild with: go build -tags pkcs11

func (*PKCS11KeyStore) Close

func (p *PKCS11KeyStore) Close() error

Close is a no-op for the stub.

func (*PKCS11KeyStore) Delete

func (p *PKCS11KeyStore) Delete(_ string) error

func (*PKCS11KeyStore) ExportPEM

func (p *PKCS11KeyStore) ExportPEM(_ string) (string, error)

func (*PKCS11KeyStore) GenerateKey

func (p *PKCS11KeyStore) GenerateKey() (string, error)

func (*PKCS11KeyStore) ImportPEM

func (p *PKCS11KeyStore) ImportPEM(_ string) (string, error)

func (*PKCS11KeyStore) Signer

func (p *PKCS11KeyStore) Signer(_ string) (crypto.Signer, error)

type RevocationEntry

type RevocationEntry struct {
	SerialNumber string `json:"serial_number"`
	RevokedAt    string `json:"revoked_at"`
	Reason       int    `json:"reason"`
	ItemID       string `json:"item_id"`
}

RevocationEntry records a single revoked certificate.

type SoftwareKeyStore

type SoftwareKeyStore struct {
	// contains filtered or unexported fields
}

SoftwareKeyStore holds ECDSA P-256 private keys in memory. Keys are identified by an opaque string generated at creation time. This is the default KeyStore used when no HSM/KMS is configured.

Keys in this store are ephemeral — the caller (typically the PKI layer) is responsible for persisting them in the vault via ExportPEM/ImportPEM.

func NewSoftwareKeyStore

func NewSoftwareKeyStore() *SoftwareKeyStore

NewSoftwareKeyStore returns a SoftwareKeyStore ready for use.

func (*SoftwareKeyStore) Delete

func (s *SoftwareKeyStore) Delete(keyID string) error

Delete removes the key from memory.

func (*SoftwareKeyStore) ExportPEM

func (s *SoftwareKeyStore) ExportPEM(keyID string) (string, error)

ExportPEM encodes the private key as SEC1 "EC PRIVATE KEY" PEM.

func (*SoftwareKeyStore) GenerateKey

func (s *SoftwareKeyStore) GenerateKey() (string, error)

GenerateKey creates a new ECDSA P-256 key pair.

func (*SoftwareKeyStore) ImportPEM

func (s *SoftwareKeyStore) ImportPEM(pemData string) (string, error)

ImportPEM parses an EC private key PEM block and stores it.

func (*SoftwareKeyStore) Signer

func (s *SoftwareKeyStore) Signer(keyID string) (crypto.Signer, error)

Signer returns the *ecdsa.PrivateKey (which implements crypto.Signer).

Jump to

Keyboard shortcuts

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