Documentation
¶
Index ¶
- Constants
- func DecryptPassword(encryptedPassword string, masterKey []byte) (string, error)
- func EncryptPassword(password string, masterKey []byte) (string, error)
- func GetOrCreateKeyFile(dataDir string) ([]byte, error)
- func IsLegacyCiphertext(stored string) bool
- func KeyID(masterKey []byte) string
- func ReadKeyFileAt(path string) ([]byte, error)
- func WriteKeyFile(path string, key []byte) error
- type ArchiveKey
- type KeyIDProbe
Constants ¶
const KeyFileSize = 32 // 256 bits for AES-256
const LegacyKeyFileBackupSuffix = ".pre-v1"
LegacyKeyFileBackupSuffix names the pre-upgrade copy kept beside an upgraded master key, so a binary rollback has something to roll back to.
const ThreeNcrPrefix = "3ncr.org/1#"
ThreeNcrPrefix is the header of the 3ncr.org/1 encrypted-string format that all new encryptions use. Stored values without it are in the legacy format (base64url of AES-256-GCM nonce||ciphertext||tag, as written by ODDK <= 0.1.28 via cryptopasta); the daemon re-encrypts those at startup, and DecryptPassword keeps a legacy fallback for rows that pre-date the sweep.
Variables ¶
This section is empty.
Functions ¶
func DecryptPassword ¶
DecryptPassword decrypts a stored value with the master key, handling both the 3ncr.org/1 format and the legacy pre-0.1.29 format.
func EncryptPassword ¶
EncryptPassword encrypts a password with the master key in the 3ncr.org/1 format (AES-256-GCM with the raw 32-byte key, self-describing header).
func GetOrCreateKeyFile ¶
GetOrCreateKeyFile gets or creates the master key file.
A legacy headerless key is upgraded to the V1 format in place, best-effort: the upgrade is cosmetic, so a failure to rewrite (a read-only 0400 key, a read-only filesystem) is logged and the already-decoded key is returned. The upgrade lives here rather than in a separate startup sweep because this function aborts daemon startup on an unrecognised file, so a sweep running after it would never see the file it was meant to migrate.
func IsLegacyCiphertext ¶
IsLegacyCiphertext reports whether a stored value is in the legacy format and should be re-encrypted (used by the daemon's startup sweep).
func KeyID ¶ added in v0.1.94
KeyID names a master key in messages: the checksum that already ends its key-file line (`ODDK-SECRET-MASTER-KEY;V1;<payload>;<checksum>`), so an operator can match an archive to a key file by eye. It is 32 bits of a hash of a 256-bit random key, so publishing it in an archive header reveals nothing useful about the key.
func ReadKeyFileAt ¶ added in v0.1.59
ReadKeyFileAt reads a master key from an arbitrary path, for `snapshot apply` where the operator supplies the source host's key from wherever they archived it.
Unlike GetOrCreateKeyFile this never creates a key, never rewrites it, and it does not reject loose permissions: a key restored from backup media legitimately arrives 0644, and refusing it would block a disaster recovery for a property of a file that is about to be re-written with 0600 anyway. Symlinks are still refused, and the format is still validated.
func WriteKeyFile ¶ added in v0.1.59
WriteKeyFile installs a master key at path with 0600 permissions, in the current on-disk format.
Types ¶
type ArchiveKey ¶ added in v0.1.94
type ArchiveKey struct {
// contains filtered or unexported fields
}
ArchiveKey is the age identity ODDK encrypts archives to, derived from the master key so disaster recovery stays one secret (internal-docs/archive-encryption.md).
func NewArchiveKey ¶ added in v0.1.94
func NewArchiveKey(masterKey []byte) (*ArchiveKey, error)
NewArchiveKey derives the archive key from a 32-byte master key. The derivation is HKDF-SHA256 to a 32-byte seed, which is exactly what an age post-quantum (ML-KEM-768 + X25519) identity is.
func (*ArchiveKey) AgeSecret ¶ added in v0.1.94
func (k *ArchiveKey) AgeSecret() string
AgeSecret is the identity in age's own text form (AGE-SECRET-KEY-PQ-1…), for `age -d -i`. It is a full decryption secret: print it only locally, to the data-dir owner, never over the API.
func (*ArchiveKey) ID ¶ added in v0.1.94
func (k *ArchiveKey) ID() string
ID is the key ID of the master key this archive key was derived from.
func (*ArchiveKey) Identity ¶ added in v0.1.94
func (k *ArchiveKey) Identity() age.Identity
Identity decrypts archives encrypted to this key.
func (*ArchiveKey) Recipient ¶ added in v0.1.94
func (k *ArchiveKey) Recipient() age.Recipient
Recipient encrypts to this key and records its ID in the header.
type KeyIDProbe ¶ added in v0.1.94
type KeyIDProbe struct {
// ID is the recorded key ID, or "" when the header has none (an archive
// not written by ODDK).
ID string
}
KeyIDProbe is an age identity that opens nothing: it records the key ID stanza of the header it is shown. age tries native identities first and stops at the first that opens the file, so a probe listed with the real keys is consulted only when none of them could — the one case that needs to name the key. The ID is unauthenticated at that point: a hint for an error message, never an input to a decision.