### Configure Vault with Runtime Environment Variables Source: https://context7.com/danielberkompas/cloak/llms.txt Configures the Vault at runtime by fetching encryption keys from environment variables using the `init/1` callback. Ensure the environment variable is set before starting the application. ```elixir defmodule MyApp.Vault do use Cloak.Vault, otp_app: :my_app @impl GenServer def init(config) do config = Keyword.put(config, :ciphers, [ default: { Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V1", key: decode_env!("CLOAK_KEY"), iv_length: 12 } ]) {:ok, config} end defp decode_env!(var) do var |> System.get_env() |> Base.decode64!() end end # Set environment variable before starting: # export CLOAK_KEY="aJ7HcM24BcyiwsAvRsa3EG3jcvaFWooyQJ+91OO7bRU=" ``` -------------------------------- ### Generate 256-bit Base64 Encrypted Key Source: https://github.com/danielberkompas/cloak/blob/master/guides/how_to/generate_keys.md Use this command in IEx to generate a strong 256-bit key encoded with Base64. Ensure you have Elixir installed. ```elixir $ iex iex> 32 |> :crypto.strong_rand_bytes() |> Base.encode64() "HXCdm5z61eNgUpnXObJRv94k3JnKSrnfwppyb60nz6w=" ``` -------------------------------- ### Configure Cloak Vault with Ciphers Source: https://github.com/danielberkompas/cloak/blob/master/README.md Example of configuring a Vault module with multiple cipher options, including AES.GCM with a specified IV length for interoperability. Ensure keys are securely managed. ```elixir config :my_app, MyApp.Vault, ciphers: [ # In AES.GCM, it is important to specify 12-byte IV length for # interoperability with other encryption software. See this GitHub issue # for more details: https://github.com/danielberkompas/cloak/issues/93 # # In Cloak 2.0, this will be the default iv length for AES.GCM. aes_gcm: {Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V1", key: <<...>>, iv_length: 12}, aes_ctr: {Cloak.Ciphers.AES.CTR, tag: "AES.CTR.V1", key: <<...>>} ] ``` -------------------------------- ### Migrate Cloak Configuration to Vault Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.6.x_to_0.7.x.md Convert existing Cloak configuration to the new vault format, updating tags and keys. This example shows the conversion from a direct configuration to a vault configuration with default and retired ciphers. ```elixir config :cloak, Cloak.AES.CTR, tag: "AES", default: true, keys: [ %{tag: <<1>>, key: :base64.decode("..."), default: true} ] ``` ```elixir 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!(...)} ] ``` -------------------------------- ### Implement GenServer init/1 Callback Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.8.x_to_0.9.x.md Update the `init/1` callback in your custom vault module to use `GenServer.init/1`, especially if fetching keys from system variables. ```elixir defmodule MyApp.Vault do use Cloak.Vault, otp_app: :my_app @impl GenServer def init(config) do (...) end end ``` -------------------------------- ### Configure Vault with Environment Variables Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.6.x_to_0.7.x.md Implement the `init/1` callback in your vault module to configure ciphers using environment variables for keys. Ensure the environment variables are properly set and decoded. ```elixir 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() |> Base.decode64!() end end ``` -------------------------------- ### Run Cloak Data Migration Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.6.x_to_0.7.x.md Execute the `mix cloak.migrate` task to convert existing encrypted data from the old v0.6 format to the new v0.7 format. Specify your repository and schema modules. ```bash mix cloak.migrate -r MyApp.Repo -s MyApp.Schema ``` -------------------------------- ### Configure Poison as JSON Library Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.9.x_to_1.0.x.md If you are not specifying the `:json_library` setting and wish to continue using Poison, add this configuration to your `config/config.exs`. ```elixir config :my_app, MyApp.Vault, json_library: Poison, # ... ``` -------------------------------- ### Add Cloak Dependency to mix.exs Source: https://github.com/danielberkompas/cloak/blob/master/guides/how_to/install.md Add the Cloak dependency to your project's `mix.exs` file. Run `mix deps.get` afterwards to fetch the dependency. ```elixir {:cloak, "1.1.1"} ``` -------------------------------- ### Define a Cloak Vault Module Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.6.x_to_0.7.x.md Create a vault module for your project by using `Cloak.Vault` and specifying the `otp_app`. ```elixir defmodule MyApp.Vault do use Cloak.Vault, otp_app: :my_app end ``` -------------------------------- ### Add Jason Dependency Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.9.x_to_1.0.x.md If you are not using the default JSON library and want to use Jason, add it to your dependencies. ```elixir {:jason, "~> 1.0"} ``` -------------------------------- ### Define Cloak Vault with Environment Variable Key Source: https://github.com/danielberkompas/cloak/blob/master/guides/how_to/install.md Configure a Cloak Vault to fetch the encryption key from a system environment variable (e.g., `CLOAK_KEY`). The `init/1` callback is used for this dynamic configuration. ```elixir defmodule MyApp.Vault do use Cloak.Vault, otp_app: :my_app @impl GenServer def init(config) do config = Keyword.put(config, :ciphers, [ default: { Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V1", key: decode_env!("CLOAK_KEY"), iv_length: 12 } ]) {:ok, config} end defp decode_env!(var) do var |> System.get_env() |> Base.decode64!() end end ``` -------------------------------- ### Re-encrypt Data with a New Algorithm/Key Source: https://github.com/danielberkompas/cloak/blob/master/README.md Demonstrates re-encrypting data using a specified algorithm, then decrypting and re-encrypting again. This showcases the flexibility in changing encryption parameters. ```elixir "plaintext" |> MyApp.Vault.encrypt!(:aes_256) |> MyApp.Vault.decrypt!() |> MyApp.Vault.encrypt!(:aes_256) |> MyApp.Vault.decrypt!() # => "plaintext" ``` -------------------------------- ### Update Migration Command Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.9.x_to_1.0.x.md Rename the `mix cloak.migrate` command to `mix cloak.migrate.ecto` for Ecto migrations. ```bash mix cloak.migrate.ecto ``` -------------------------------- ### Add cloak_ecto Dependency Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.9.x_to_1.0.x.md Replace the `cloak` dependency with `cloak_ecto` in your `mix.exs` file for version 1.0.0. ```elixir {:cloak_ecto, "1.0.0"} ``` -------------------------------- ### Configure Vault with Mix Config Source: https://context7.com/danielberkompas/cloak/llms.txt Configures the Vault module with cipher settings in the application's configuration file. The first cipher in the list is set as the default for new encryptions. ```elixir # config/runtime.exs config :my_app, MyApp.Vault, json_library: Jason, ciphers: [ # AES.GCM is recommended for most use cases default: { Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V1", key: Base.decode64!("aJ7HcM24BcyiwsAvRsa3EG3jcvaFWooyQJ+91OO7bRU="), # Use 12-byte IV for interoperability with other encryption software iv_length: 12 }, # Legacy cipher for decrypting old data during key rotation legacy: { Cloak.Ciphers.AES.CTR, tag: "AES.CTR.V1", key: Base.decode64!("oldKeyHere...") } ] ``` -------------------------------- ### Define and Configure Multiple Vaults Source: https://context7.com/danielberkompas/cloak/llms.txt Run multiple Vaults simultaneously for different encryption contexts, useful in umbrella applications or multi-tenant systems. Configure each vault separately and add them to the supervision tree. ```elixir # Define separate vaults defmodule MyApp.UserVault do use Cloak.Vault, otp_app: :my_app end defmodule MyApp.PaymentVault do use Cloak.Vault, otp_app: :my_app end # Configure each vault separately config :my_app, MyApp.UserVault, ciphers: [ default: {Cloak.Ciphers.AES.GCM, tag: "USER.V1", key: user_key, iv_length: 12} ] config :my_app, MyApp.PaymentVault, ciphers: [ default: {Cloak.Ciphers.AES.GCM, tag: "PAY.V1", key: payment_key, iv_length: 12} ] # Add both to supervision tree children = [ MyApp.UserVault, MyApp.PaymentVault ] # Use appropriate vault for each context MyApp.UserVault.encrypt!("user SSN") MyApp.PaymentVault.encrypt!("credit card number") ``` -------------------------------- ### Transparent Ecto Field Encryption with Cloak Source: https://context7.com/danielberkompas/cloak/llms.txt Demonstrates how Cloak encrypts data upon insertion and automatically decrypts it upon retrieval when used with Ecto. Ensure your schema fields are configured for Cloak encryption. ```elixir user = %MyApp.User{email: "user@example.com", ssn: "123-45-6789"} Repo.insert!(user) # SSN stored encrypted in database user = Repo.get(MyApp.User, 1) user.ssn # => "123-45-6789" (automatically decrypted) ``` -------------------------------- ### Define Project-Specific Encrypted Binary Field Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.6.x_to_0.7.x.md Create a local Ecto type for encrypted binary fields by using `Cloak.Fields.Binary` and specifying the vault. This replaces the generic `Cloak.EncryptedBinaryField`. ```elixir defmodule MyApp.Encrypted.Binary do use Cloak.Fields.Binary, vault: MyApp.Vault end ``` -------------------------------- ### Update Cloak Dependency to 0.8.0 Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.7.x_to_0.8.x.md Update your project's `cloak` dependency to version `0.8.0` or later in your `mix.exs` file. This is the primary step for upgrading. ```elixir {:cloak, "~> 0.8.0"} ``` -------------------------------- ### Generate a 256-bit Encryption Key Source: https://github.com/danielberkompas/cloak/blob/master/guides/how_to/install.md Generate a strong, 256-bit encryption key encoded in Base64 using IEx. This key is required for setting up the Cloak Vault. ```elixir 32 |> :crypto.strong_rand_bytes() |> Base.encode64() ``` -------------------------------- ### Implement Custom Cipher Source: https://context7.com/danielberkompas/cloak/llms.txt Implement the `Cloak.Cipher` behaviour to create custom encryption modules for specialized use cases. Configure the custom cipher in your application's configuration. ```elixir defmodule MyApp.CustomCipher do @behaviour Cloak.Cipher @impl true def encrypt(plaintext, opts) do key = Keyword.fetch!(opts, :key) tag = Keyword.fetch!(opts, :tag) iv = :crypto.strong_rand_bytes(16) # Your encryption logic here ciphertext = :crypto.crypto_one_time(:aes_256_cbc, key, iv, plaintext, encrypt: true) {:ok, tag <> iv <> ciphertext} end @impl true def decrypt(ciphertext, opts) do if can_decrypt?(ciphertext, opts) do key = Keyword.fetch!(opts, :key) tag = Keyword.fetch!(opts, :tag) tag_size = byte_size(tag) <<^tag::binary-size(tag_size), iv::binary-16, encrypted::binary>> = ciphertext plaintext = :crypto.crypto_one_time(:aes_256_cbc, key, iv, encrypted, encrypt: false) {:ok, plaintext} else :error end end @impl true def can_decrypt?(ciphertext, opts) do tag = Keyword.fetch!(opts, :tag) String.starts_with?(ciphertext, tag) end end # Configure the custom cipher config :my_app, MyApp.Vault, ciphers: [ custom: {MyApp.CustomCipher, tag: "CUSTOM.V1", key: Base.decode64!("key...")} ] ``` -------------------------------- ### Supervise Cloak Vault Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.8.x_to_0.9.x.md Add your `MyApp.Vault` to your application's supervision tree to ensure it is properly managed. ```elixir children = [ MyApp.Vault ] ``` -------------------------------- ### Update Cloak Field Reference Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.9.x_to_1.0.x.md Change references from the old `Cloak.Fields.Binary` naming scheme to the new `Cloak.Ecto.Binary` scheme. ```elixir use Cloak.Fields.Binary, vault: MyApp.Vault Should now become: use Cloak.Ecto.Binary, vault: MyApp.Vault ``` -------------------------------- ### Update Schema to Use Project-Specific Field Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.6.x_to_0.7.x.md Replace `Cloak.EncryptedBinaryField` with the newly defined project-specific field (e.g., `MyApp.Encrypted.Binary`) in your Ecto schema. Also, remove the `encryption_version` field. ```elixir defmodule MyApp.Accounts.User do use Ecto.Schema import Ecto.Changeset schema "users" do field :name, MyApp.Encrypted.Binary, field :encryption_version end @doc false def changeset(struct, attrs \\ %{}) def changeset(struct, attrs \\ %{}) do struct |> cast(attrs, [:name]) end end ``` -------------------------------- ### Encrypt with a Specific Key Label Source: https://github.com/danielberkompas/cloak/blob/master/guides/how_to/install.md Encrypt data using a specific cipher key by providing its label as the second argument to `MyApp.Vault.encrypt/2`. Decryption automatically uses the key specified in the ciphertext's metadata. ```elixir MyApp.Vault.encrypt("plaintext", :default) ``` -------------------------------- ### Add Vault to Supervision Tree Source: https://context7.com/danielberkompas/cloak/llms.txt Integrates the Vault module into the application's supervision tree for automatic startup. The Vault can be added directly or with specific runtime configurations. ```elixir # lib/my_app/application.ex defmodule MyApp.Application do use Application def start(_type, _args) do children = [ # Start the Vault MyApp.Vault, # Or with runtime configuration: # {MyApp.Vault, ciphers: [...]} ] opts = [strategy: :one_for_one, name: MyApp.Supervisor] Supervisor.start_link(children, opts) end end ``` -------------------------------- ### Update Cloak Dependency Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.6.x_to_0.7.x.md Specify the Cloak version in your project's dependency list to upgrade to 0.7.0 or later. ```elixir {:cloak, ">~> 0.7.0"} ``` -------------------------------- ### Update Cloak Dependency Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.8.x_to_0.9.x.md Modify your project's dependency configuration to use Cloak version 0.9.0 or higher. ```elixir {:cloak, "~> 0.9.2"} ``` -------------------------------- ### Define a Cloak Vault Source: https://github.com/danielberkompas/cloak/blob/master/guides/how_to/install.md Define a `Cloak.Vault` for your application. Ensure the `otp_app` is set correctly. Configure ciphers, including the key (decoded from Base64) and IV length. ```elixir defmodule MyApp.Vault do use Cloak.Vault, otp_app: :my_app end config :my_app, MyApp.Vault, ciphers: [ default: { Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V1", key: Base.decode64!("your-key-here"), iv_length: 12 } ] ``` -------------------------------- ### Rotate Encryption Keys with New Cipher Source: https://context7.com/danielberkompas/cloak/llms.txt Add a new cipher as the first in the list to rotate encryption keys. Old data decrypts with the legacy cipher and re-encrypts with the new default. ```elixir # Configuration with new and old keys config :my_app, MyApp.Vault, ciphers: [ # New key - used for all new encryptions default: { Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V2", key: Base.decode64!("newKeyHere..."), iv_length: 12 }, # Old key - still used for decryption of existing data retired: { Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V1", key: Base.decode64!("oldKeyHere..."), iv_length: 12 } ] # Re-encrypt existing data with the new key old_ciphertext = <<...>> # Encrypted with V1 new_ciphertext = old_ciphertext |> MyApp.Vault.decrypt!() # Decrypts using V1 key (auto-detected) |> MyApp.Vault.encrypt!() # Re-encrypts using V2 key (default) ``` -------------------------------- ### Ecto Integration for Encrypted Fields Source: https://context7.com/danielberkompas/cloak/llms.txt Use the `cloak_ecto` package to transparently encrypt Ecto schema fields at the database level. Define an encrypted field type and use it in your Ecto schema. ```elixir # Add to mix.exs {:cloak_ecto, "~> 1.2"} # Define encrypted field type defmodule MyApp.Encrypted.Binary do use Cloak.Ecto.Binary, vault: MyApp.Vault end # Use in schema defmodule MyApp.User do use Ecto.Schema schema "users" do field :email, :string field :ssn, MyApp.Encrypted.Binary # Automatically encrypted/decrypted timestamps() end end ``` -------------------------------- ### Encrypt and Decrypt Values with Cloak Vault Source: https://github.com/danielberkompas/cloak/blob/master/guides/how_to/install.md Encrypt plaintext data using `MyApp.Vault.encrypt/1` and decrypt the resulting ciphertext using `MyApp.Vault.decrypt/1`. By default, the first configured key is used for encryption. ```elixir {:ok, ciphertext} = MyApp.Vault.encrypt("plaintext") MyApp.Vault.decrypt(ciphertext) ``` -------------------------------- ### Encrypt and Decrypt Data with Cloak Source: https://github.com/danielberkompas/cloak/blob/master/README.md Encrypts plaintext data and then decrypts the resulting ciphertext. Ensure your Vault module is configured correctly. ```elixir {:ok, ciphertext} = MyApp.Vault.encrypt("plaintext") # => {:ok, <<1, 10, 65, 69, 83, 46, 71, 67, 77, 46, 86, 49, 45, 1, 250, 221, # => 189, 64, 26, 214, 26, 147, 171, 101, 181, 158, 224, 117, 10, 254, 140, 207, # => 215, 98, 208, 208, 174, 162, 33, 197, 179, 56, 236, 71, 81, 67, 85, 229, # => ...>>} MyApp.Vault.decrypt(ciphertext) # => {:ok, "plaintext"} ``` -------------------------------- ### Generate Encryption Key Source: https://context7.com/danielberkompas/cloak/llms.txt Generates a cryptographically secure 256-bit AES encryption key using Erlang's crypto module. The key is base64-encoded for safe storage and can be decoded for use in configuration. ```elixir # Generate a 256-bit (32 byte) encryption key key = 32 |> :crypto.strong_rand_bytes() |> Base.encode64() # => "aJ7HcM24BcyiwsAvRsa3EG3jcvaFWooyQJ+91OO7bRU=" # Decode for use in configuration decoded_key = Base.decode64!(key) # => <<104, 158, 199, 112, 205, 184, 133, ...>> ``` -------------------------------- ### AES-GCM Cipher Encryption and Decryption Source: https://context7.com/danielberkompas/cloak/llms.txt Use AES in Galois/Counter Mode for authenticated encryption. Includes automatic random IV generation and ciphertext authentication. Typically done through Vault. ```elixir # Direct cipher usage (typically done through Vault) alias Cloak.Ciphers.AES.GCM opts = [ tag: "AES.GCM.V1", key: :crypto.strong_rand_bytes(32), iv_length: 12 # Recommended for interoperability ] {:ok, ciphertext} = GCM.encrypt("plaintext", opts) # => {:ok, <<1, 10, 65, 69, 83, 46, 71, 67, 77, ...>>} {:ok, plaintext} = GCM.decrypt(ciphertext, opts) # => {:ok, "plaintext"} # Check if cipher can decrypt a ciphertext GCM.can_decrypt?(ciphertext, opts) # => true ``` -------------------------------- ### Encrypt Data with Vault Source: https://context7.com/danielberkompas/cloak/llms.txt Encrypts plaintext data using the Vault's default cipher. Provides both safe (`{:ok, ciphertext}`) and unsafe (`ciphertext`) versions. Specific ciphers can be selected using an atom. ```elixir # Safe version - returns {:ok, ciphertext} or {:error, reason} {:ok, ciphertext} = MyApp.Vault.encrypt("sensitive data") # => {:ok, <<1, 10, 65, 69, 83, 46, 71, 67, 77, 46, 86, 49, ...>>} # Unsafe version - raises on error ciphertext = MyApp.Vault.encrypt!("sensitive data") # => <<1, 10, 65, 69, 83, 46, 71, 67, 77, 46, 86, 49, ...>> # Encrypt with a specific labeled cipher {:ok, ciphertext} = MyApp.Vault.encrypt("sensitive data", :legacy) ciphertext = MyApp.Vault.encrypt!("sensitive data", :legacy) ``` -------------------------------- ### AES-CTR Cipher Encryption and Decryption Source: https://context7.com/danielberkompas/cloak/llms.txt Use AES in Counter Mode for streaming encryption. Suitable for large data or when authenticated encryption is not required. Typically done through Vault. ```elixir # Direct cipher usage (typically done through Vault) alias Cloak.Ciphers.AES.CTR opts = [ tag: "AES.CTR.V1", key: :crypto.strong_rand_bytes(32) ] {:ok, ciphertext} = CTR.encrypt("plaintext", opts) # => {:ok, <<1, 10, 65, 69, 83, 46, 67, 84, 82, ...>>} {:ok, plaintext} = CTR.decrypt(ciphertext, opts) # => {:ok, "plaintext"} # Check if cipher can decrypt a ciphertext CTR.can_decrypt?(ciphertext, opts) # => true ``` -------------------------------- ### Remove Retired Cipher Configuration Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.6.x_to_0.7.x.md After successfully migrating data, remove the `:retired` cipher entry from your vault configuration to finalize the upgrade. ```elixir config :my_app, MyApp.Vault, ciphers: [ default: {Cloak.Ciphers.AES.CTR, tag: "AES.V2", key: Base.decode64!(...)} ] ``` -------------------------------- ### Remove Encryption Version Field from Migration Source: https://github.com/danielberkompas/cloak/blob/master/guides/upgrading/0.6.x_to_0.7.x.md In your database migrations, remove the `encryption_version` column from the relevant table as it is no longer required in Cloak 0.7.x. ```elixir alter table(:users) do remove :encryption_version end ``` -------------------------------- ### Decrypt Data with Vault Source: https://context7.com/danielberkompas/cloak/llms.txt Decrypts ciphertext back to plaintext. The Vault automatically identifies the cipher used from the embedded tag. Offers safe and unsafe versions. ```elixir # Safe version - returns {:ok, plaintext} or {:error, reason} {:ok, plaintext} = MyApp.Vault.decrypt(ciphertext) # => {:ok, "sensitive data"} # Unsafe version - raises on error plaintext = MyApp.Vault.decrypt!(ciphertext) # => "sensitive data" # Full round-trip example "my secret" |> MyApp.Vault.encrypt!() |> MyApp.Vault.decrypt!() # => "my secret" ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.