crypt

package
v0.16.4 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package crypt is the encryption-at-rest key hierarchy for a ClassAd database.

A random 256-bit DB master key roots the hierarchy. It is never stored in the clear: it is wrapped once per available pool key (a KEK), so any one pool key opens the DB and the DB survives key rotation (add a row per new key). Purpose-specific subkeys are derived from the master via HKDF -- the data key (wraps each segment's DEK) and the backup key (wraps a snapshot's decryption key). Each segment gets its own random DEK, wrapped by the data key and stored with the segment; the DEK encrypts that segment's encrypted attributes with AES-256-GCM. A stolen database is useless without a pool key.

This mirrors golang-htcondor's session-cache envelope, generalized for the DB.

Index

Constants

View Source
const (
	// DataInfo derives the data key, which wraps each per-segment DEK.
	DataInfo = "classad-db-data-v1"
	// BackupInfo derives the backup key, which wraps a snapshot's decryption key.
	BackupInfo = "classad-db-backups-v1"
)

Purpose labels for master-key subkeys (HKDF context). Distinct labels keep the derived keys independent, so the same master protects multiple uses without key reuse.

View Source
const (
	// KeySize is the AES-256 / master-key / DEK size in bytes.
	KeySize = 32
)

Variables

View Source
var ErrNoKey = errors.New("crypt: no available pool key can decrypt the database")

ErrNoKey reports that none of the available pool keys could unwrap the master key.

Functions

func NewDEK

func NewDEK() ([]byte, error)

NewDEK returns a fresh random 256-bit data-encryption key (one per segment).

func NewMaster

func NewMaster() ([]byte, error)

NewMaster returns a fresh random 256-bit master key.

func Open

func Open(key, nonce, ciphertext []byte) ([]byte, error)

Open decrypts a Seal result, verifying the GCM tag (returns an error on tampering or a wrong key).

func OpenMaster

func OpenMaster(rows []MasterKeyRow, keys []KEK) ([]byte, error)

OpenMaster recovers the master key from the first row whose KeyID matches an available KEK and whose wrapping decrypts. Returns ErrNoKey if none match.

func Seal

func Seal(key, plaintext []byte) (nonce, ciphertext []byte, err error)

Seal encrypts plaintext with AES-256-GCM under key, returning a fresh nonce and the ciphertext (with the GCM tag appended).

func Subkey

func Subkey(master []byte, info string) ([]byte, error)

Subkey derives a 256-bit purpose-specific key from master via HKDF-SHA256 with the given context label (use DataInfo / BackupInfo).

func UnwrapDEK

func UnwrapDEK(key, nonce, wrapped []byte) ([]byte, error)

UnwrapDEK recovers a DEK wrapped by WrapDEK.

func WrapDEK

func WrapDEK(dek, key []byte) (nonce, wrapped []byte, err error)

WrapDEK wraps a DEK under key (the data key); UnwrapDEK reverses it.

Types

type KEK

type KEK struct {
	ID       string
	Material []byte
}

KEK is a key-encryption key: a pool / HTCondor signing key. ID names it (e.g. "POOL"); Material is the raw key bytes.

type MasterKeyRow

type MasterKeyRow struct {
	KeyID   string
	Salt    []byte
	Nonce   []byte
	Wrapped []byte // AES-GCM(KEK, master)
}

MasterKeyRow is the DB master key wrapped by one KEK, persisted so any available pool key can recover the master.

func WrapMaster

func WrapMaster(master []byte, k KEK) (MasterKeyRow, error)

WrapMaster wraps master with the KEK derived from k (via a fresh salt), producing a persistable row.

Jump to

Keyboard shortcuts

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