# `MPP.BodyDigest`
[🔗](https://github.com/ZenHive/mpp/blob/v0.10.0/lib/mpp/body_digest.ex#L1)

SHA-256 body digest computation and verification.

Produces digest strings in the format `"sha-256=<base64>"` for binding request
bodies to challenges. Maps are JSON-encoded before hashing. Verification uses
constant-time comparison to prevent timing attacks.

**Note:** When passing a map, the digest is computed over `Jason.encode!/1` output.
For request body binding, pass the raw body bytes to ensure the digest matches
the exact wire format. The map convenience path matches the mppx TypeScript
reference but may produce different digests than raw body strings if key
ordering differs.

## Examples

    iex> MPP.BodyDigest.compute(~s({"amount":"1000"}))
    "sha-256=" <> _base64

    iex> digest = MPP.BodyDigest.compute(%{"amount" => "1000"})
    iex> MPP.BodyDigest.verify(digest, %{"amount" => "1000"})
    true

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `verify` | 2 | Verify a digest matches the given body using constant-time comparison. | `digest: value`, `body: value` |
| `compute` | 1 | Compute a SHA-256 digest of the given body. | `body: value` |

# `compute`

```elixir
@spec compute(String.t() | map()) :: String.t()
@spec compute(map()) :: String.t()
```

Compute a SHA-256 digest of the given body.

## Parameters

  * `body` - Request body as a string or map (maps are JSON-encoded before hashing) (value)

## Returns

Digest string in format "sha-256=<base64>" (`string`)

## Composes With

  * `verify`

```elixir
# descripex:contract
%{
  params: %{
    body: %{
      description: "Request body as a string or map (maps are JSON-encoded before hashing)",
      kind: :value
    }
  },
  returns: %{
    type: :string,
    description: "Digest string in format \"sha-256=<base64>\"",
    example: "sha-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE"
  },
  composes_with: [:verify]
}
```

# `verify`

```elixir
@spec verify(String.t(), String.t() | map()) :: boolean()
```

Verify a digest matches the given body using constant-time comparison.

## Parameters

  * `digest` - Digest string to verify (e.g., "sha-256=...") (value)
  * `body` - Request body as a string or map (maps are JSON-encoded before hashing) (value)

## Returns

True if the digest matches, false otherwise (`boolean`)

## Composes With

  * `compute`

```elixir
# descripex:contract
%{
  params: %{
    body: %{
      description: "Request body as a string or map (maps are JSON-encoded before hashing)",
      kind: :value
    },
    digest: %{
      description: "Digest string to verify (e.g., \"sha-256=...\")",
      kind: :value
    }
  },
  returns: %{
    type: :boolean,
    description: "True if the digest matches, false otherwise"
  },
  composes_with: [:compute]
}
```

---

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