keystore

package
v0.16.0 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package keystore implements envelope encryption for CA private key material persisted in SQLite. Each CA gets a fresh data-encryption key (DEK) wrapped under a process-wide master key (KEK) supplied through NEBULA_MGMT_MASTER_KEY. AES-256-GCM is used for both wraps.

See docs/adr/0002-per-operator-cas.md §4.1 for the design rationale.

Index

Constants

View Source
const (
	// MasterKeySize is the expected size of the unwrapped master key, in bytes.
	MasterKeySize = 32
	// DEKSize is the size of a per-CA data-encryption key.
	DEKSize = 32
	// NonceSize is the GCM nonce length used everywhere in this package.
	NonceSize = 12
)

Variables

View Source
var ErrInvalidMasterKey = errors.New("master key must be 32 random bytes, base64-encoded")

ErrInvalidMasterKey is returned when the configured master key has the wrong length or fails to base64-decode.

Functions

func OpenWithDEK

func OpenWithDEK(dek []byte, w WrappedBlob, aad []byte) ([]byte, error)

OpenWithDEK decrypts a WrappedBlob using the given DEK and the aad it was sealed with (nil only for pre-binding legacy envelopes).

func Zeroize

func Zeroize(b []byte)

Zeroize overwrites b with zeros. Use immediately after the plaintext material is no longer required. Uses the clear builtin (Go 1.21+) which the spec guarantees will not be optimized away (#297).

Types

type Master

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

Master wraps the process-wide AEAD instance for the KEK.

func NewMaster

func NewMaster(raw []byte) (*Master, error)

NewMaster builds a Master from raw 32-byte material.

func NewMasterFromBase64

func NewMasterFromBase64(b64 string) (*Master, error)

NewMasterFromBase64 builds a Master from a base64-encoded 32-byte key. The decoded bytes are copied into the AEAD key schedule by NewMaster, so the transient plaintext copy is zeroized before returning rather than left on the heap for the GC to reclaim (and possibly reuse).

func (*Master) GenerateDEK

func (m *Master) GenerateDEK(aad []byte) (plaintext []byte, wrapped WrappedKey, err error)

GenerateDEK returns a fresh DEK plus its master-key-wrapped form, with the wrap bound to aad (the owning CA's ID — see WrapDEK). Callers MUST zeroise the returned plaintext DEK as soon as it is no longer needed.

func (*Master) UnwrapDEK

func (m *Master) UnwrapDEK(w WrappedKey, aad []byte) ([]byte, error)

UnwrapDEK decrypts a DEK previously wrapped with WrapDEK under the same aad. The returned plaintext lives only until the caller zeroises it. Pass nil aad only for envelopes written before the binding existed (see the legacy fallback in pki.CAResolver.LoadByID).

func (*Master) WrapDEK

func (m *Master) WrapDEK(dek, aad []byte) (WrappedKey, error)

WrapDEK encrypts a DEK under the master key. aad is bound into the GCM tag — callers pass the owning CA's ID so a wrapped DEK copied into another CA's row fails to decrypt instead of pairing that CA's cert with a foreign signing key (DB-write envelope swap).

type WrappedBlob

type WrappedBlob struct {
	Ciphertext []byte
	Nonce      []byte
}

WrappedBlob holds an arbitrary payload encrypted under a per-CA DEK.

func SealWithDEK

func SealWithDEK(dek, plaintext, aad []byte) (WrappedBlob, error)

SealWithDEK encrypts a payload under the given DEK using AES-256-GCM, binding aad (the owning CA's ID) into the tag — see WrapDEK.

type WrappedKey

type WrappedKey struct {
	Ciphertext []byte
	Nonce      []byte
}

WrappedKey holds a DEK encrypted under the master key.

Jump to

Keyboard shortcuts

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