# `Attesto.Signer`
[🔗](https://github.com/XukuLLC/attesto/blob/v1.15.0/lib/attesto/signer.ex#L1)

Additive signing contract for non-extractable private keys.

A module implementing this behaviour exposes only the public JWK and signs
the already-encoded JWS signing input. The private key may therefore remain
inside an HSM, KMS, enclave, or remote custody service; it never needs to be
returned to Attesto or loaded into BEAM memory.

The signature returned by `sign/2` is the JWS signature octet sequence, not
a base64url string. In particular, ECDSA implementations return the fixed
width `R || S` encoding required by RFC 7518, rather than ASN.1 DER.
Implementations are responsible for the algorithm-specific requirements,
including the required RSA-PSS salt length.

Attesto verifies every returned signature against `signing_jwk/0` and the
selected `alg` before returning a compact JWS. A signer using the wrong
remote key, message/digest mode, signature encoding, or algorithm therefore
fails locally instead of issuing an unusable token.

Existing `Attesto.Keystore` implementations need no changes. When a module
does not implement this behaviour, Attesto continues to read its
`signing_pem/0` and uses the established in-process JOSE path. A
non-extractable implementation supplies `signing_jwk/0` and `sign/2` while
retaining `verification_pems/0` (with public PEMs) for verification and JWKS
publication.

A signer using an algorithm that cannot be inferred from its public key,
such as `PS256`, also implements the optional `Attesto.Keystore.signing_alg/0`
callback or publishes an `"alg"` member in `signing_jwk/0`.

# `alg`

```elixir
@type alg() :: String.t()
```

# `signature_error`

```elixir
@type signature_error() :: term()
```

# `sign`

```elixir
@callback sign(signing_input :: binary(), alg()) ::
  {:ok, signature :: binary()} | {:error, signature_error()}
```

Sign an encoded JWS signing input with the named JOSE algorithm.

# `signing_jwk`

```elixir
@callback signing_jwk() :: map() | JOSE.JWK.t()
```

The current signing key's public JWK. Private members are forbidden.

---

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