# `Image.Plug.Provider.Imgix.Signing`
[🔗](https://github.com/elixir-image/image_plug/blob/v0.1.0/lib/image/plug/provider/imgix/signing.ex#L1)

Imgix-flavoured HMAC URL signing.

Per [imgix's docs](https://docs.imgix.com/en/latest/setup/securing-images):

* HMAC-SHA256 (we ship SHA-256 only; SHA-1 is not supported).
* Payload: `secret <> path <> "?" <> query` where the query
  excludes the `s` parameter. When the query is empty the
  payload is `secret <> path` with no trailing `?`.
* Hex digest, lowercase.
* Parameter: appended as `s=<hex>`.

Differences from `Image.Plug.Signing` (Cloudflare-flavoured):

* Parameter name: `s` vs Cloudflare's `sig`. Imgix's choice
  matches what the imgix CDN itself uses; matters for wire-
  format compatibility with imgix's own URLs.

* Canonical-string rule: imgix prepends the secret to the
  payload; Cloudflare uses the secret as the HMAC key only.

Sign and verify share the same wire format, so a URL signed by
`sign/3` verifies under `verify/3` with the same key. The
module mirrors `Image.Plug.Signing`'s public API so it's a
drop-in alternative when configuring the imgix provider.

# `sign`

```elixir
@spec sign(String.t(), [String.t(), ...], keyword()) :: String.t()
```

Signs `path_with_query` (a request path, optionally with a query
string) using the first key in `keys`. Returns the path with
`?s=<hex>` (or `&s=<hex>` if a query is already present)
appended.

### Options

* `:expires_at` — `DateTime` or unix-seconds. Adds an
  `expires=<unix>` parameter; the verifier rejects after that
  time.

# `verify`

```elixir
@spec verify(String.t(), [String.t(), ...], keyword()) ::
  :ok | {:error, Image.Plug.Error.t()}
```

Verifies the signature on `path_with_query`.

Returns `:ok` or an `Image.Plug.Error` with one of
`:signature_required`, `:invalid_signature`,
`:signature_expired`.

### Options

* `:required?` — when `true`, missing `?s=` produces
  `:signature_required`. Default `false` (defense-in-depth: a
  bad signature is always rejected, but a missing signature
  only fails when the deployment requires it).

* `:now` — current unix-seconds for expiry comparison.
  Defaults to `System.system_time(:second)`. Test-only override.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
