How To Upgrade From 0.6.x to 0.7.x
Cloak 0.7 introduced a number of important changes.
- Encryption is now performed through Cloak.Vaultmodules
- Ciphertext no longer contains a module_tag
- Ecto types are now local to your project
- You no longer need an :encryption_versionfield
Install Cloak 0.7
Update your cloak dependency to 0.7 or later.
{:cloak, "~> 0.7.0"}Create a Vault
Create a vault module for your project. (Or more than one, if you want!)
defmodule MyApp.Vault do
  use Cloak.Vault, otp_app: :my_app
endYou will need to move your existing configuration to the vault. For example, if you had this configuration:
config :cloak, Cloak.AES.CTR,
  tag: "AES",
  default: true,
  keys: [
    %{tag: <<1>>, key: :base64.decode("..."), default: true}
  ]You would convert it to the following:
config :my_app, MyApp.Vault,
  ciphers: [
    default: {Cloak.Ciphers.AES.CTR, tag: "AES.V2", key: Base.decode64("...")},
    retired: {Cloak.Ciphers.Deprecated.AES.CTR, module_tag: "AES", tag: <<1>>, key: Base.decode64("...")}
  ]Notice that the tag: "AES" became module_tag: "AES" in the :retired
cipher configuration.
Alternatively, if your keys are stored in environment variables, you could
configure the vault using the Cloak.Vault.init/1 callback:
defmodule MyApp.Vault do
  use Cloak.Vault, otp_app: :my_app
  @impl Cloak.Vault
  def init(config) do
    config =
      Keyword.put(config, :ciphers, [
        default: {Cloak.Ciphers.AES.CTR, tag: "AES.V2", key: decode_env("CLOAK_KEY")},
        retired: {Cloak.Ciphers.Deprecated.AES.CTR, module_tag: "AES", tag: <<1>>, key: decode_env("CLOAK_KEY")}
      ])
    {:ok, config}
  end
  defp decode_env(var) do
    var
    |> System.get_env(var)
    |> Base.decode64!()
  end
endCreate Project-Specific Ecto Types
For each type of encrypted field you have, define a local type. For example, if you had the following schema:
defmodule MyApp.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset
  schema "users" do
    field :name, Cloak.EncryptedBinaryField,
    field :encryption_version
  end
  @doc false
  def changeset(struct, attrs \\ %{}) do
    struct
    |> cast(attrs, [:name])
    |> put_change(:encryption_version, Cloak.version())
  end
endYou would define a project-specific field:
defmodule MyApp.Encrypted.Binary do
  use Cloak.Fields.Binary, vault: MyApp.Vault
endAnd then replace Cloak.EncryptedBinaryField in your schema:
schema "users" do
  field :name, MyApp.Encrypted.Binary,
  field :encryption_version
end Finally, you’d remove the :encryption_version field as it is no longer
needed.
# In migration...
alter table(:users) do
  remove :encryption_version
end
# In your changeset...
@doc false
def changeset(struct, attrs \\ %{}) do
  struct
  |> cast(attrs, [:name])
endMigrate Existing Data
To convert ciphertext en masse from the old v0.6 format to the new v0.7
format, you’ll need to run mix cloak.migrate as shown in its documentation.
mix cloak.migrate -r MyApp.Repo -s MyApp.Schema
  
  Remove :retired Cipher
Now that the data has been migrated to the new v0.7 format, you can remove the
:retired cipher from your configuration.
config :my_app, MyApp.Vault,
  ciphers: [
    default: {Cloak.Ciphers.AES.CTR, tag: "AES.V2", key: Base.decode64("...")}
  ]