View Source Cloak.Ecto.HMAC behaviour (cloak_ecto v1.3.0)
A custom Ecto.Type for hashing fields using :crypto.hmac/3.
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.
Security
HMAC is more secure than Cloak.Ecto.SHA256, because it uses a
secret to obfuscate the hash. This makes it harder to guess the value of
the field.
Configuration
Create an HMAC field in your project:
defmodule MyApp.Hashed.HMAC do
use Cloak.Ecto.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.Ecto.HMAC, otp_app: :my_app
@impl Cloak.Ecto.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")
Summary
Types
HMAC algorithms supported by Cloak.Field.HMAC
Callbacks
Configures the HMAC field using runtime information.
Types
@type algorithms() :: :md5 | :ripemd160 | :sha | :sha224 | :sha256 | :sha384 | :sha512
HMAC algorithms supported by Cloak.Field.HMAC