Documentation
¶
Overview ¶
Package crypt seals byte values with AES-256-GCM using named keys from secrets.Provider.
Design ¶
Keyring derives keys with HKDF-SHA256, seals with an active key and accepts configured retired keys for reads. Ciphertext identifies its format and key name; additional authenticated data binds a value to its purpose and row. Strict mode rejects legacy plaintext. Callers rotate by retaining old keys until values have been rewrapped under the new active key.
The package does not select database columns or encrypt entire records automatically. SQL backends define which values are sealed and how Rewrap walks them; raw check-in records and exports can still contain sensitive data.
References ¶
- Decision record 0011: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/research/decisions/0011-secrets-provider.md
- Decision record 0013: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/research/decisions/0013-secrets-at-rest.md
- Threat model: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/security/threat-model.md (Storage disclosure and ciphertext row swap rows)
- Apple: https://developer.apple.com/documentation/devicemanagement/check-in
- Apple: https://developer.apple.com/documentation/devicemanagement/managing-certificates-for-device-management-services-and-devices
- Schema: third_party/device-management/mdm/checkin/tokenupdate.yaml (UnlockToken)
- Schema: third_party/device-management/mdm/checkin/setbootstraptoken.yaml (BootstrapToken)
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoKeyring is returned when Seal or Open is called on a nil Keyring. ErrNoKeyring = errors.New("crypt: no keyring configured") // ErrUnknownKey is returned when a header names a key the ring does not hold. ErrUnknownKey = errors.New("crypt: ciphertext uses an unknown key") // ErrTampered is returned when authentication fails, including a wrong AAD. ErrTampered = errors.New("crypt: authentication failed") // ErrUnsealed is returned by strict callers that meet a value without the header. ErrUnsealed = errors.New("crypt: value is not sealed") // ErrWeakKey is returned when a provider supplies fewer than 16 bytes of key material. ErrWeakKey = errors.New("crypt: key material shorter than 16 bytes") // ErrBadFormat is returned for input that is not a well formed sealed value. ErrBadFormat = errors.New("crypt: malformed ciphertext") // ErrNoActive is returned when Keys.Active is empty. ErrNoActive = errors.New("crypt: no active key name") )
Sentinel errors returned by this package. Callers should test them with errors.Is because the returned values may carry extra context.
Functions ¶
func AAD ¶
AAD builds the associated data that binds a value to its table column and row, as purpose, a NUL byte, then rowID. Moving a sealed value to another column or row therefore fails to open.
Types ¶
type Keyring ¶
type Keyring struct {
// contains filtered or unexported fields
}
Keyring holds the derived AEAD for each key name. It is safe for concurrent use once constructed.
func NewKeyring ¶
NewKeyring fetches every named key from the provider once, so a provider failure is a construction error rather than a surprise at the first Seal. Provider bytes are normalised to a 32 byte AES key with HKDF over SHA-256, salted with the key name, so two names backed by the same material still yield distinct keys.
func (*Keyring) Open ¶
Open decrypts a sealed value and reports which key name it used. It returns ErrBadFormat for input that is not sealed or is too short, ErrUnknownKey when the header names a key the ring does not hold, and ErrTampered when authentication fails, which includes a wrong aad.
func (*Keyring) Seal ¶
Seal encrypts plaintext under the active key and returns the sealed value: magic, key name length, key name, nonce, then the AES-GCM output including its tag. Empty plaintext is allowed and yields a sealed empty value. The aad is authenticated but not stored; Open must be given the same bytes.
type Keys ¶
type Keys struct {
// Active is the key name every Seal uses.
Active string
// Accepted lists retired key names Open still honours.
Accepted []string
// Strict makes callers refuse unsealed values (set once Rewrap has run everywhere).
Strict bool
}
Keys names the active key and the retired keys still accepted on read.