# `Attesto.Key`
[🔗](https://github.com/XukuLLC/attesto/blob/v0.13.0/lib/attesto/key.ex#L1)

Pure helpers for working with signing material as PEM strings.

An RSA private key already contains its public half, so there is never
a separately stored public PEM to drift out of sync. `public_pem/1`
derives the public key from a private PEM, giving exactly one source of
truth: the verification key always matches the signing key. This closes
a real failure mode where a tracked public PEM and a regenerated
private key silently mismatch and every verification fails.

`kid/1` is the RFC 7638 JWK thumbprint of a key's public half. It is
stable for a given key and changes iff the key changes, so rotating to a
new key yields a distinct `kid` automatically - no separate identifier
to assign or track.

# `jwk`

```elixir
@spec jwk(String.t()) :: JOSE.JWK.t()
```

Parse a PEM (private or public) into a `JOSE.JWK`.

Raises `ArgumentError` if `pem` does not contain exactly one parseable
key. `JOSE.JWK.from_pem/1` returns `[]` for input with no key entry and
a list for a multi-key PEM; left unguarded, `thumbprint/1` of those
returns `[]` rather than a string, which would silently poison `kid/1`
and verification-key selection. Failing loudly here surfaces a
malformed keystore PEM as a configuration error instead of a
request-time mystery.

Also raises if the key type/curve is not supported by Attesto's
asymmetric signing algorithms. Algorithms are derived from trusted key
metadata, not from a presented token header.

# `kid`

```elixir
@spec kid(String.t()) :: String.t()
```

The RFC 7638 SHA-256 JWK thumbprint (`kid`) of the public half of the
key in `pem`. Accepts a private or public PEM; both yield the same
thumbprint because it is computed over the public members only.

# `public_pem`

```elixir
@spec public_pem(String.t()) :: String.t()
```

Derive the public key, in conventional SPKI
(`-----BEGIN PUBLIC KEY-----`) PEM form, from a private RSA key PEM.

Accepts the PKCS#1 (`RSA PRIVATE KEY`) and PKCS#8 (`PRIVATE KEY`) forms.
Raises `ArgumentError` - signing material is operator-provided, so a
misconfiguration is a deploy-time failure that should be loud rather
than silently verifying against garbage - if `pem` contains no key
entry, contains more than one, contains a non-RSA key, or is
public-only. EC/OKP deployments should publish JWKS instead.

# `signing_jwk`

```elixir
@spec signing_jwk(String.t()) :: JOSE.JWK.t()
```

Parse a private PEM into a `JOSE.JWK` whose public half can sign and
derive a `kid`.

Unlike `jwk/1`, this rejects public-only PEMs: they are valid
verification material, but cannot sign tokens.

---

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