View Source How to Rotate Keys

Many organizations rotate their keys on a regular schedule for security reasons. Cloak can do this with zero downtime.

Add Your New Key

You will need to add your new key to your vault configuration, as the first key in the :ciphers list. Demote and re-label existing keys.

For example, if your config currently looks like this:

config :my_app, MyApp.Vault,
  ciphers: [
    default: {Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V1", key: <<...>>},
  ]

Then you should change the :default label to the new key, and demote the existing key to the :retired label.

config :my_app, MyApp.Vault,
  ciphers: [
    default: {Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V2", key: <<...>>},
    retired: {Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V1", key: <<...>>}
  ]

Labels don't matter, order does

The :ciphers configuration is order-dependent. The first key in the list will be used as the default, regardless of its label. This guide uses the :default and :retired labels for clarity, but the order is what matters.

Migrate Data To New Key

For each schema that uses your vault, run mix cloak.migrate:

mix cloak.migrate.ecto -r MyApp.Repo -s MyApp.Schema

Alternatively, you can migrate multiple schemas at once by configuring the following values in config/config.exs:

config :my_app,
  cloak_repo: MyApp.Repo,
  cloak_schemas: [...]

With that in place, you can simply run:

mix cloak.migrate.ecto

Remove Retired Key

Once you are confident that all data have been converted over to use the new key, you may remove the :retired key from your configuration.

config :my_app, MyApp.Vault,
  ciphers: [
    default: {Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V2", key: <<...>>},
  ]

How It Works

Every ciphertext generated by Cloak is tagged with the :tag of the configured cipher that produced it.

As a result, Cloak will be able to find and use the correct cipher to decrypt any old ciphertext as long as you leave its cipher configured.

When you add a new default key, Cloak will immediately begin encrypting new data with the new key. Every time existing data are fetched from the database, they will be decrypted with the old key, and if changed, will be encrypted with the new key.

Even if you don't run mix cloak.migrate.ecto, data will gradually be converted over to the new key as they are used. The migration task simply speeds up the process.