cloak v0.8.0 Cloak.Fields.HMAC behaviour View Source
A custom Ecto.Type for hashing fields using :crypto.hmac/3.
HMAC is more secure than Cloak.Fields.SHA256, because it uses a secret
to obfuscate the hash. This makes it harder to guess the value of the field.
Why
If you store a hash of a field’s value, you can then query on it as a proxy for an encrypted field. This works because HMAC is deterministic and always results in the same value, while secure encryption does not. Be warned, however, that hashing will expose which fields have the same value, because they will contain the same hash.
Configuration
Create an HMAC field in your project:
defmodule MyApp.Hashed.HMAC do
  use Cloak.Fields.HMAC, otp_app: :my_app
endThen, configure it with a :secret and :algorithm, either using
mix configuration:
config :my_app, MyApp.Hashed.HMAC,
  algorithm: :sha512,
  secret: "secret"Or using the init/1 callback to fetch configuration at runtime:
defmodule MyApp.Hashed.HMAC do
  use Cloak.Fields.HMAC, otp_app: :my_app
  @impl Cloak.Fields.HMAC
  def init(config) do
    config = Keyword.merge(config, [
      algorithm: :sha512,
      secret: System.get_env("HMAC_SECRET")
    ])
    {:ok, config}
  end
endUsage
Create the hash field with the type :binary. Add it to your schema
definition like this:
schema "table" do
  field :field_name, MyApp.Encrypted.Binary
  field :field_name_hash, MyApp.Hashed.HMAC
endEnsure that the hash is updated whenever the target field changes with the
put_change/3 function:
def changeset(struct, attrs \\ %{}) do
  struct
  |> cast(attrs, [:field_name, :field_name_hash])
  |> put_hashed_fields()
end
defp put_hashed_fields(changeset) do
  changeset
  |> put_change(:field_name_hash, get_field(changeset, :field_name))
endQuery the Repo using the :field_name_hash in any place you would typically
query by :field_name.
user = Repo.get_by(User, email_hash: "user@email.com")Link to this section Summary
Types
HMAC algorithms supported by Cloak.Field.HMAC
Callbacks
Configures the HMAC field using runtime information
Link to this section Types
algorithms() :: :md5 | :ripemd160 | :sha | :sha224 | :sha256 | :sha384 | :sha512
HMAC algorithms supported by Cloak.Field.HMAC
Link to this section Callbacks
Configures the HMAC field using runtime information.
Example
@impl Cloak.Fields.HMAC
def init(config) do
  config = Keyword.merge(config, [
    algorithm: :sha512,
    secret: System.get_env("HMAC_SECRET")
  ])
  {:ok, config}
end