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

Exact public Ed25519 JWK encoding, decoding, and RFC 7638 thumbprints.

Every documented function here refuses a key that fails
`BoundedAuthorityProtocol.Ed25519.acceptable_public_key?/1` (non-canonical, small-order or
off-curve) with the closed `{:error, :invalid}`, so no such key can enter a JWK, a holder
confirmation thumbprint, or a key fingerprint.

# `decode_public`

```elixir
@spec decode_public(binary(), BoundedAuthorityProtocol.V1.Bounds.t() | map()) ::
  {:ok, binary()} | {:error, :invalid}
```

Decodes an exact public Ed25519 OKP JWK carrying an acceptable key.

# `encode_public`

```elixir
@spec encode_public(binary(), BoundedAuthorityProtocol.V1.Bounds.t() | map()) ::
  {:ok, binary()} | {:error, :invalid}
```

Encodes one acceptable raw 32-byte Ed25519 public key as the canonical public OKP JWK.

# `public_key_thumbprint_raw`

```elixir
@spec public_key_thumbprint_raw(
  binary(),
  BoundedAuthorityProtocol.V1.Bounds.t() | map()
) ::
  {:ok, binary()} | {:error, :invalid}
```

Returns the raw 32-byte SHA-256 RFC 7638 thumbprint of a raw 32-byte Ed25519 public key.

Equivalent to `encode_public/2` followed by `thumbprint_raw/2`. Use it to compute the
holder confirmation a `BoundedAuthorityProtocol.V1.Grant` carries: pass the raw digest
as `holder_thumbprint` (the producer base64url-encodes it into the `cnf.jkt` claim). A key that fails
`BoundedAuthorityProtocol.Ed25519.acceptable_public_key?/1` is `{:error, :invalid}`.

## Example

    iex> public_key =
    ...>   Base.decode16!("D75A980182B10AB7D54BFED3C964073A0EE172F3DAA62325AF021A68F707511A")
    iex> {:ok, digest} = BoundedAuthorityProtocol.V1.Jwk.public_key_thumbprint_raw(public_key, %{})
    iex> Base.url_encode64(digest, padding: false)
    "kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k"

# `thumbprint`

```elixir
@spec thumbprint(binary(), BoundedAuthorityProtocol.V1.Bounds.t() | map()) ::
  {:ok, binary()} | {:error, :invalid}
```

Returns the canonical base64url RFC 7638 thumbprint.

# `thumbprint_preimage`

```elixir
@spec thumbprint_preimage(binary(), BoundedAuthorityProtocol.V1.Bounds.t() | map()) ::
  {:ok, binary()} | {:error, :invalid}
```

Returns the exact RFC 7638 public OKP thumbprint preimage.

# `thumbprint_raw`

```elixir
@spec thumbprint_raw(binary(), BoundedAuthorityProtocol.V1.Bounds.t() | map()) ::
  {:ok, binary()} | {:error, :invalid}
```

Returns the raw 32-byte SHA-256 RFC 7638 thumbprint of an exact public OKP JWK.

This is the digest `thumbprint/2` base64url-encodes. The JWK must be the exact canonical
member set `decode_public/2` accepts, carrying an acceptable key; anything else is
`{:error, :invalid}`.

## Example

    iex> jwk = ~s({"crv":"Ed25519","kty":"OKP","x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"})
    iex> {:ok, digest} = BoundedAuthorityProtocol.V1.Jwk.thumbprint_raw(jwk, %{})
    iex> Base.url_encode64(digest, padding: false)
    "kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k"

---

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