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
- Variables
- func NewDEK() ([]byte, error)
- func NewMaster() ([]byte, error)
- func Open(key, nonce, ciphertext []byte) ([]byte, error)
- func OpenMaster(rows []MasterKeyRow, keys []KEK) ([]byte, error)
- func Seal(key, plaintext []byte) (nonce, ciphertext []byte, err error)
- func Subkey(master []byte, info string) ([]byte, error)
- func UnwrapDEK(key, nonce, wrapped []byte) ([]byte, error)
- func WrapDEK(dek, key []byte) (nonce, wrapped []byte, err error)
- type KEK
- type MasterKeyRow
Constants ¶
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.
const (
// KeySize is the AES-256 / master-key / DEK size in bytes.
KeySize = 32
)
Variables ¶
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 Open ¶
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 ¶
Seal encrypts plaintext with AES-256-GCM under key, returning a fresh nonce and the ciphertext (with the GCM tag appended).
func Subkey ¶
Subkey derives a 256-bit purpose-specific key from master via HKDF-SHA256 with the given context label (use DataInfo / BackupInfo).
Types ¶
type KEK ¶
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.