# `BoundedAuthorityProtocol.Es256`
[🔗](https://github.com/baselabs/bounded_authority_protocol/blob/v1.0.0/lib/bounded_authority_protocol/es256.ex#L1)

ES256 (ECDSA P-256 with SHA-256) signature canonicality, public-key acceptance, strict
verification, and producer utilities for the `BAP3-ES256-SHA256` suite.

This module is the single owner of the ES256 scalar and point rules for every ES256 surface of
the protocol. It is pure: no clock, randomness, process state, or I/O. It accepts public keys
only; no function here takes, holds, or produces private key material. No function raises.

## Wire form

A signature is the RFC 7518 §3.4 raw form `r || s`: exactly 64 bytes, two fixed-width 32-byte
unsigned big-endian integers. A public key is the 65-byte uncompressed SEC1 point
`0x04 || x || y`.

## Canonical signature

`canonical_signature?/1` is the suite's signature rule (`spec/bap-v3.md` § 3.2):
`0 < r < n` and `0 < s <= floor(n / 2)`, `n` the P-256 group order. Every verification surface
applies it before the backend, and every producer surface (compact assembly, anchored-export
encoding) refuses a signature that fails it (erratum 3).

## Producer utilities

Normalization is the signer's duty. `normalize_low_s/1` maps a high-S signature `(r, s)` to
its low-S twin `(r, n - s)`; `der_to_raw/1` converts a strict DER `ECDSA-Sig-Value` (the form
most HSM, KMS, and secret-store signers return) to the raw wire form. A producer runs
`der_to_raw/1`, then `normalize_low_s/1`, before compact assembly. The protocol's own producer
surfaces never normalize: they refuse.

A `true` result proves only that the bytes satisfy the rule. It never selects trusted keys or
grants authority.

# `acceptable_public_key?`
*since 0.9.0* 

```elixir
@spec acceptable_public_key?(binary()) :: boolean()
```

Returns whether a 65-byte uncompressed SEC1 public key `0x04 || x || y` may enter a
verification input: both coordinates are field elements (`< p`) and the point is on the
curve. Any other input returns `false`.

# `canonical_signature?`
*since 0.9.0* 

```elixir
@spec canonical_signature?(binary()) :: boolean()
```

Returns whether a raw 64-byte signature `r || s` is canonical: `0 < r < n` and
`0 < s <= floor(n / 2)`. Any other input, including non-binary or wrong-size input, returns
`false`.

# `der_to_raw`
*since 0.9.0* 

```elixir
@spec der_to_raw(binary()) :: {:ok, binary()} | {:error, :invalid}
```

Converts a strict DER `ECDSA-Sig-Value` (`SEQUENCE { INTEGER r, INTEGER s }`) to the raw
64-byte `r || s` form.

The encoding must be exact DER: single-byte lengths that match the content exactly (a valid
signature's content is at most 70 bytes, so a long-form length never matches), minimal
non-negative INTEGER encodings (a leading `0x00` only when the next byte has its high bit
set), and no trailing bytes. Both scalars must lie in `0 < r < n` and `0 < s < n`. The output
is not low-S normalized; pass it to `normalize_low_s/1`. Any other input returns
`{:error, :invalid}`.

# `normalize_low_s`
*since 0.9.0* 

```elixir
@spec normalize_low_s(binary()) :: {:ok, binary()} | {:error, :invalid}
```

Maps a raw 64-byte signature to its low-S form: `(r, n - s)` when `s > floor(n / 2)`, and the
same bytes otherwise. Idempotent.

Returns `{:error, :invalid}` unless `0 < r < n` and `0 < s < n`. This is a producer utility
for the signer; the protocol's producer surfaces never apply it.

# `verify_strict`
*since 0.9.0* 

```elixir
@spec verify_strict(binary(), binary(), binary()) :: boolean()
```

Verifies an ES256 signature strictly: the key must be acceptable, the signature canonical,
and then the ECDSA equation must hold (checked by the `:crypto` backend over a minimal DER
encoding of `r` and `s`). Any other input returns `false`; the function never raises.

The backend runs only on a binary message, a canonical signature, and an on-curve key with
coordinates below `p` (P-256 has prime order, so every such point is a valid public key):
the inputs on which a backend raises never reach it.

---

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