Aker.SignedCall (Aker v0.1.0)

Copy Markdown View Source

A call to the licensing server signed by the install key, and the check a server runs on one.

A signed call carries four headers:

  • x-licence-install-key: the install public key, base64;
  • x-licence-timestamp: Unix seconds;
  • x-licence-nonce: 16 random bytes, base64;
  • x-licence-signature: the install key's DER signature, base64, of signed_string/5.

verify/2 answers the install public key only when the signature holds. The server then looks that key up itself: a valid signature proves the caller holds the key, not that the server knows it.

Summary

Functions

The four headers for a call of method to path with body, signed by install_key ({module, opts}). :now (Unix seconds) sets the timestamp, for tests.

The text the install key signs for one call: the method, the path, the timestamp, the nonce and the body's SHA-256 in hex, one per line.

Checks a signed call as a server receives it: %{method:, path:, headers:, body:}, where headers is a list of {name, value} with lowercase names, as Plug gives them.

Functions

headers(arg, method, path, body, opts \\ [])

@spec headers({module(), keyword()}, String.t(), String.t(), binary(), keyword()) ::
  {:ok, [{String.t(), String.t()}]} | {:error, atom()}

The four headers for a call of method to path with body, signed by install_key ({module, opts}). :now (Unix seconds) sets the timestamp, for tests.

signed_string(method, path, timestamp, nonce, body)

@spec signed_string(String.t(), String.t(), String.t(), String.t(), binary()) ::
  binary()

The text the install key signs for one call: the method, the path, the timestamp, the nonce and the body's SHA-256 in hex, one per line.

verify(arg1, opts)

@spec verify(map(), keyword()) :: {:ok, binary()} | {:error, atom()}

Checks a signed call as a server receives it: %{method:, path:, headers:, body:}, where headers is a list of {name, value} with lowercase names, as Plug gives them.

Options:

  • :nonce_fresh? (required): a 1-arity function over the nonce's text that answers true the first time it sees a nonce and false after, kept over the server's own nonce table. It runs only once every other check has passed, so a forged call records no nonce. A timestamp may sit up to :window_s ahead of now, so keep each nonce for twice :window_s.
  • :now: Unix seconds (default now);
  • :window_s: how far the timestamp may sit from now (default 600).

Answers {:ok, install_public_key}, or {:error, reason} with reason :unsigned, :bad_key, :bad_nonce, :stale, :bad_signature or :replayed.