# `Macaw.Auth.Native.Hasher`
[🔗](https://github.com/dcoai/macaw_auth/blob/v0.4.1/lib/macaw/auth/native/hasher.ex#L1)

How `Macaw.Auth.Native` hashes passwords: a behavior with two
implementations, `Macaw.Auth.Native.Hasher.Bcrypt` and
`Macaw.Auth.Native.Hasher.Argon2`. Each library is an optional
dependency, and each implementation is compiled only when its library is,
so a host carries only the NIF it chose.

    config :macaw_auth, Macaw.Auth.Native, hasher: Macaw.Auth.Native.Hasher.Argon2

The default is Bcrypt. A configured hasher whose library is missing is
refused when the configuration is read (`Macaw.Auth.Native.Config`),
naming the dependency to add, never at the first sign-in.

**Rehashing.** A stored hash is replaced at a successful sign-in when it
`needs_rehash?/2`: made with other parameters (a raised bcrypt cost), or
by the other algorithm. A hash carries its algorithm's prefix, so moving
from bcrypt to argon2 needs no flag day: a bcrypt hash still verifies
with bcrypt (when `:bcrypt_elixir` is still loaded) and is rehashed with
argon2 on that user's next sign-in.

**No enumeration.** `no_user_verify/0` spends a verification's time and
returns false, so refusing an unknown user takes as long as refusing a
wrong password.

# `hash`

```elixir
@callback hash(password :: String.t()) :: String.t()
```

A new hash of `password`, with the configured parameters.

# `needs_rehash?`

```elixir
@callback needs_rehash?(hash :: String.t()) :: boolean()
```

Whether `hash`, one of this algorithm's, was made with other parameters than now.

# `no_user_verify`

```elixir
@callback no_user_verify() :: false
```

Spends a verification's time and returns false.

# `owns?`

```elixir
@callback owns?(hash :: String.t()) :: boolean()
```

Whether `hash` is one of this algorithm's (by its prefix).

# `verify`

```elixir
@callback verify(password :: String.t(), hash :: String.t()) :: boolean()
```

Whether `password` matches `hash` (constant time).

# `check`

```elixir
@spec check(module()) :: :ok | {:error, String.t()}
```

Whether `module` can hash here: compiled (its library is loaded) and
implementing this behavior, every callback of it. `:ok` or
`{:error, message}`.

# `needs_rehash?`

```elixir
@spec needs_rehash?(module(), String.t()) :: boolean()
```

Whether `hash` should be replaced by a `configured` one.

# `verify`

```elixir
@spec verify(module(), String.t(), String.t() | nil) :: boolean()
```

Verifies `password` against a stored `hash` with whichever available
algorithm made it. A hash no available algorithm owns (or none at all)
spends the configured hasher's time and is false.

---

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