# `Aker.InstallKey`
[🔗](https://github.com/udin-io/aker/blob/v0.1.0/lib/aker/install_key.ex#L1)

The keypair that ties a licence to one install. The licensing server
stores its public half and names it in the signed licence; the app proves
it holds the private half by signing a fresh random value.

The key is ECDSA on NIST P-256, because TPM 2.0 chips sign on that curve
and few sign Ed25519. A public key travels as the 65-byte uncompressed
point, base64; a signature as DER, the form OpenSSL and the TPM tools
write.

`Aker.InstallKey.Software` keeps the private key in a file;
`Aker.InstallKey.Tpm` keeps it in the chip.

# `opts`

```elixir
@type opts() :: keyword()
```

Where the implementation keeps its key, such as `dir:`.

# `public_key`

```elixir
@type public_key() :: &lt;&lt;_::520&gt;&gt;
```

The uncompressed P-256 point: 0x04, then X and Y.

# `ensure`

```elixir
@callback ensure(opts()) :: {:ok, public_key()} | {:error, atom()}
```

Makes the key when there is none, and answers its public half.

# `kind`

```elixir
@callback kind() :: :software | :tpm
```

Which kind of key this is, as an activation request names it.

# `public_key`

```elixir
@callback public_key(opts()) :: {:ok, public_key()} | {:error, atom()}
```

The public half of the key that exists, without making one.

# `sign`

```elixir
@callback sign(message :: binary(), opts()) :: {:ok, binary()} | {:error, atom()}
```

The DER ECDSA SHA-256 signature of `message`.

# `for_dir`

```elixir
@spec for_dir(Path.t(), keyword()) :: {module(), opts()}
```

The install key for the licence folder `dir`, as `{module, opts}`.

The key stays the kind that made it, since the licence names that key:
a key made in the chip stays the chip's, so a machine whose chip is gone
refuses rather than making a new key, and a key made in a file is never
moved into a chip that appears later. A new install uses the chip when
the machine has one, and a file otherwise.

Options:

  * `:tpm_device` - the chip's device (default `/dev/tpmrm0`);
  * `:tpm_options` - options passed to `Aker.InstallKey.Tpm`.

# `point?`

```elixir
@spec point?(binary()) :: boolean()
```

Whether `public_key` is an uncompressed point on P-256.

# `proves?`

```elixir
@spec proves?({module(), opts()}, binary()) :: boolean()
```

Signs a fresh 32-byte random value with the key `{module, opts}` names
and checks the signature against `public_key`. True only when the key
in hand is the one `public_key` describes.

# `verify`

```elixir
@spec verify(binary(), binary(), binary()) :: boolean()
```

Whether `signature` is `public_key`'s DER signature of `message`.

---

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