# `TruelayerClient.Signing`
[🔗](https://github.com/iamkanishka/truelayer_client/blob/v1.0.0/lib/truelayer_client/signing.ex#L1)

ES512 JWS request signing for the TrueLayer Payments, Payouts, and Mandates APIs.

Uses Erlang's `:crypto` and `:public_key` OTP modules — zero external dependencies.

## TrueLayer signing specification

  * Algorithm: ES512 (ECDSA with P-521 curve and SHA-512)
  * Format: `<base64url_header>..<base64url_p1363_signature>`
  * JWS protected header: `{"alg":"ES512","kid":"<key_id>","tl-version":"2","tl-headers":"<header_names>","iat":<unix_ts>}`
  * Signing payload: `<METHOD>\n<PATH>\n<HEADER_LINES>\n<BODY>`

## Obtaining a signing key

Generate a P-521 EC key pair using OpenSSL:

    openssl ecparam -name secp521r1 -genkey -noout -out signing_private.pem
    openssl ec -in signing_private.pem -pubout -out signing_public.pem

Upload the public key to the TrueLayer Console and note the returned Key ID.

# `signer`

```elixir
@type signer() :: %{key: term(), key_id: String.t()}
```

# `new_signer`

```elixir
@spec new_signer(binary(), String.t()) ::
  {:ok, signer()} | {:error, TruelayerClient.Error.t()}
```

Parse a PEM-encoded EC private key (PKCS8 or SEC1) and return a signer map.

## Example

    pem = File.read!("keys/signing_private.pem")
    {:ok, signer} = TruelayerClient.Signing.new_signer(pem, "my-key-id")

# `sign`

```elixir
@spec sign(signer(), String.t(), String.t(), map(), binary()) ::
  {:ok, String.t()} | {:error, TruelayerClient.Error.t()}
```

Produce the value of the `Tl-Signature` request header.

## Parameters

  * `signer` - signer map from `new_signer/2`
  * `method` - HTTP method in uppercase, e.g. `"POST"`
  * `path` - request path without query string, e.g. `"/v3/payments"`
  * `headers` - map of header names → values to include in the signature
  * `body` - raw request body bytes (use `""` for no body)

## Example

    {:ok, sig} = TruelayerClient.Signing.sign(signer, "POST", "/v3/payments", %{
      "idempotency-key" => "idem-001",
      "content-type" => "application/json"
    }, body_bytes)
    # Use sig as the value of the Tl-Signature header

---

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