Macaw.Auth.Native.Seal (macaw_auth v0.4.1)

Copy Markdown View Source

Sealing at rest: what the native backend stores that must not be read back from the table (a TOTP secret) is sealed with AES-256-GCM, OTP's :crypto, under a key from the configuration (sealing_key:, Macaw.Auth.Native.Config).

  • The key. sealing_key is a binary of at least 32 bytes, or {module, function, args} returning one, called at each use (so a host can keep it in its data directory, or derive it from its secret_key_base, without this library depending on how). It is never logged and never in telemetry; the configuration's inspect leaves it out. A missing or short key is Macaw.Auth.Native.SealingKeyError at first use, naming the fault and never the value.
  • Derived, not used as is. The AES key is HMAC-SHA256 of a fixed label under the configured key, so a host may pass a longer secret it also uses elsewhere (its secret_key_base) and the two uses never share a key.
  • Bound to its row. Each sealed value carries associated data (the purpose and the user's id), so a sealed secret copied onto another user's row does not unseal there.
  • The format. <<1, iv::12 bytes, tag::16 bytes, ciphertext>>, the first byte a version, so a later scheme can be told apart. A fresh random IV for every seal.

unseal/3 returns {:error, :wrong_key} for anything that fails to authenticate: a different key, a tampered value, another row's value.

Summary

Functions

The AES key from the configured sealing_key; raises Macaw.Auth.Native.SealingKeyError when it is missing, short, or its function returns something that isn't a key.

The smallest key accepted, in bytes.

Seals plaintext under key (from key!/1), bound to aad.

Unseals: {:ok, plaintext}, or {:error, :wrong_key} when it doesn't authenticate.

Types

key_source()

@type key_source() :: binary() | {module(), atom(), list()} | nil

Functions

key!(source)

@spec key!(key_source()) :: binary()

The AES key from the configured sealing_key; raises Macaw.Auth.Native.SealingKeyError when it is missing, short, or its function returns something that isn't a key.

min_bytes()

@spec min_bytes() :: pos_integer()

The smallest key accepted, in bytes.

seal(plaintext, key, aad)

@spec seal(binary(), binary(), binary()) :: binary()

Seals plaintext under key (from key!/1), bound to aad.

unseal(arg1, key, aad)

@spec unseal(binary(), binary(), binary()) :: {:ok, binary()} | {:error, :wrong_key}

Unseals: {:ok, plaintext}, or {:error, :wrong_key} when it doesn't authenticate.