Documentation
¶
Overview ¶
Package crypto implements envelope encryption.
Data is encrypted with a Data Encryption Key (DEK) using AES-256-GCM. Each DEK is in turn encrypted ("wrapped") by a Key Encryption Key (KEK), typically customer-managed and backed by a cloud KMS. The wrapped DEK and the ID of the KEK that wrapped it are carried together as DEKMaterial, allowing the DEK to be recovered and the data decrypted later.
A KEKRegistry manages the set of available KEKs, selecting the appropriate key by namespace for encryption and by key ID for decryption.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrMalformedCipherText = errors.New("invalid ciphertext, not encrypted with a DEK")
ErrMalformedCipherText indicates that the ciphertext was not created by a call to Encrypt, or that it was otherwise tampered with.
Functions ¶
This section is empty.
Types ¶
type CacheEvent ¶
type CacheEvent struct {
// Size is the number of entries in the DEK cache after the access.
Size int
}
CacheEvent describes a DEK cache access. Fields may be added over time without breaking implementers, so callers accept the struct by value.
type DEK ¶
type DEK struct {
// contains filtered or unexported fields
}
DEK defines a Data Encryption Key used to encrypt/decrypt payloads.
func (*DEK) Decrypt ¶
Decrypt decrypts the ciphertext ct using AES-256-GCM. The ciphertext must be prefixed with the nonce, as produced by DEK.Encrypt.
type DEKMaterial ¶
type DEKMaterial struct {
Version byte
KEKID string // The ID/URI of the KEK the encrypted the DEK.
EncryptedDEK string // The base64-encoded encrypted DEK.
}
DEKMaterial defines the material needed in order to decrypt a payload.
type KEK ¶
type KEK interface {
io.Closer
// ID returns a unique ID for this KEK, e.g. a KMS ARN.
ID() string
// Encrypt encrypts a DEK, returning the ciphertext.
Encrypt(context.Context, []byte) ([]byte, error)
// Decrypt decrypts a DEK previously produced by Encrypt.
Decrypt(context.Context, []byte) ([]byte, error)
}
KEK defines an interface for a Key Encryption Keys. These keys are used to encrypt/decrypt DEKs and are customer-managed (e.g. via AWS/GCP KMS).
type KEKRegistry ¶
type KEKRegistry struct {
// contains filtered or unexported fields
}
KEKRegistry holds the set of KEKs available for encrypting and decrypting DEKs. It is keyed by namespace (for encryption) and by key ID (for decryption). Close must be called when the registry is no longer needed to release KEK resources.
func NewKEKRegistry ¶
func NewKEKRegistry(opts ...KEKRegistryOption) (*KEKRegistry, error)
NewKEKRegistry constructs a KEKRegistry, applying opts in order. A default key is required (see WithDefaultKey); construction fails if one is not provided. The key-ID index used by Decrypt is built after all options are applied.
func (*KEKRegistry) Close ¶
func (r *KEKRegistry) Close() error
Close closes all registered KEKs and releases their resources. Subsequent calls return the same error as the first call.
func (*KEKRegistry) Decrypt ¶
func (r *KEKRegistry) Decrypt(ctx context.Context, m *DEKMaterial) (*DEK, error)
Decrypt decrypts the DEK described by m using the KEK identified by m.KEKID.
func (*KEKRegistry) Encrypt ¶
func (r *KEKRegistry) Encrypt(ctx context.Context, ns string, dek *DEK) (*DEKMaterial, error)
Encrypt encrypts the given DEK using the KEK registered for the specified namespace. It returns DEKMaterial containing the KEK ID and the base64-encoded ciphertext.
type KEKRegistryOption ¶
type KEKRegistryOption interface {
// contains filtered or unexported methods
}
KEKRegistryOption configures a KEKRegistry during construction.
func WithDecryptOnlyKey ¶
func WithDecryptOnlyKey(k KEK) KEKRegistryOption
WithDecryptOnlyKey registers k for decryption only. It is added to the key-ID index so that DEKs encrypted with k can still be opened, but k is never selected for new DEK encryption. This is typically used for keys that have been rotated out of active use.
func WithDefaultKey ¶
func WithDefaultKey(k KEK) KEKRegistryOption
WithDefaultKey sets the fallback KEK used when no namespace-specific key is registered. A default key is required: NewKEKRegistry returns an error if one is not provided.
func WithKeyForNamespace ¶
func WithKeyForNamespace(ns string, k KEK) KEKRegistryOption
WithKeyForNamespace registers k for ns, used when encrypting or decrypting DEKs for that namespace.
type KeyConfig ¶
type KeyConfig struct {
// Duration is how long a DEK is valid before it must be rotated.
Duration time.Duration
// RenewBefore causes a DEK to be treated as expired this long before
// Duration elapses, so it can be rotated ahead of its actual expiry.
RenewBefore time.Duration
}
KeyConfig controls the lifetime of a namespace's DEK.
type Message ¶
type Message struct {
Ciphertext []byte
KeyMaterial *DEKMaterial
}
Message is the result of sealing plaintext: the AES-256-GCM ciphertext together with the wrapped DEK (DEKMaterial) required to open it.
type NamespacedVault ¶
type NamespacedVault struct {
// contains filtered or unexported fields
}
NamespacedVault is a Vault bound to a single namespace so callers can Seal and Open without passing the namespace on every call. Obtain one via Vault.ForNamespace.
func (*NamespacedVault) Open ¶
Open decrypts msg within the bound namespace. See Vault.Open.
func (*NamespacedVault) Seal ¶
Seal encrypts data within the bound namespace. See Vault.Seal.
type Observer ¶
type Observer interface {
CacheHit(CacheEvent)
CacheMiss(CacheEvent)
}
Observer receives notifications about Vault-internal events for telemetry. Implementations must be safe for concurrent use and must not block: a Vault calls these on the Open path. A nil Observer is never used; the Vault substitutes a no-op (see WithObserver).
type Vault ¶
type Vault struct {
// contains filtered or unexported fields
}
Vault provides envelope encryption scoped by namespace. It keeps a sliding Data Encryption Key (DEK) per namespace, wrapping each DEK with the KEK selected for that namespace by a KEKRegistry. DEKs are rotated on a sliding schedule (see KeyConfig) and decrypted DEKs are cached to avoid repeated KMS calls on Open. A Vault is safe for concurrent use.
func NewVault ¶
func NewVault(r *KEKRegistry, opts ...VaultOption) (*Vault, error)
NewVault constructs a Vault backed by r, applying opts in order. A DEK is pre-generated for every namespace registered via WithKeyConfig. NewVault returns an error if any option is invalid (for example, a duplicate namespace config) or if key/cache setup fails.
func (*Vault) ForNamespace ¶
func (v *Vault) ForNamespace(ns string) *NamespacedVault
ForNamespace returns a NamespacedVault that seals and opens within ns.
func (*Vault) Open ¶
Open decrypts msg, which must have been produced by Vault.Seal (or NamespacedVault.Seal). The wrapped DEK is unwrapped via the KEKRegistry using the KEK identified by the material carried in msg, served from the decrypted-DEK cache when it is enabled.
func (*Vault) Refresh ¶
Refresh rotates every namespace DEK that has reached its renewal threshold. It is meant to be called periodically. Seal also rotates an expired DEK on demand, so Refresh is an optimization that keeps rotation off the request path rather than a correctness requirement.
type VaultOption ¶
type VaultOption func(*vaultOptions)
VaultOption configures a Vault during construction.
func WithCacheSize ¶
func WithCacheSize(n int) VaultOption
WithCacheSize sets the maximum number of decrypted DEKs retained in the Open cache. A value of zero or less disables the cache, so every Open unwraps its DEK via the KEKRegistry.
func WithDefaultKeyConfig ¶
func WithDefaultKeyConfig(cfg KeyConfig) VaultOption
WithDefaultKeyConfig sets the KeyConfig used for namespaces that have no explicit WithKeyConfig. Without a default, sealing an unconfigured namespace fails; with one, a DEK is created for such namespaces on first use.
func WithKeyConfig ¶
func WithKeyConfig(ns string, cfg KeyConfig) VaultOption
WithKeyConfig sets the KeyConfig for a specific namespace. Registering the same namespace more than once is an error surfaced by NewVault.
func WithNowFunc ¶
func WithNowFunc(fn func() time.Time) VaultOption
WithNowFunc overrides the clock used to evaluate DEK expiry. It is primarily useful in tests. A nil function is rejected by NewVault.
func WithObserver ¶
func WithObserver(o Observer) VaultOption
WithObserver sets the Observer notified of Vault-internal events such as DEK cache hits and misses. A nil Observer is replaced with a no-op, so Open never needs to nil-check. Without this option no events are emitted.