View Source Cloak.Cipher behaviour (cloak v1.1.3)

A behaviour for encryption/decryption modules. You can rely on this behaviour to create your own Cloak-compatible cipher modules.

Example

We will create a cipher that simply prepends "Hello, " to any given plaintext on encryption, and removes the prefix on decryption.

First, define your own cipher module, and specify the Cloak.Cipher behaviour.

defmodule MyApp.PrefixCipher do
  @behaviour Cloak.Cipher
end

Add some configuration to your vault for this new cipher:

config :my_app, MyApp.Vault,
  ciphers: [
    prefix: {MyApp.PrefixCipher, prefix: "Hello, "}
  ]

The keyword list containing the :prefix will be passed in as opts to our cipher callbacks. You should specify any options your cipher will need for encryption/decryption here, such as the key.

Next, define the can_decrypt?/2 callback:

@impl true
def can_decrypt?(ciphertext, opts) do
  String.starts_with?(ciphertext, opts[:prefix])
end

If the ciphertext starts with "Hello, ", we know it was encrypted with this cipher and we can proceed. Finally, define the encrypt and decrypt functions:

@impl true
def encrypt(plaintext, opts) do
  opts[:prefix] <> plaintext
end

@impl true
def decrypt(ciphertext, opts) do
  String.replace(ciphertext, opts[:prefix], "")
end

You can now use your cipher with your vault!

MyApp.Vault.encrypt!("World!", :prefix)
# => "Hello, World!"

MyApp.Vault.decrypt!("Hello, World!")
# => "World!"

Summary

Callbacks

Determines if a given ciphertext can be decrypted by this cipher. Options are derived from the cipher configuration. See encrypt/2.

Decrypt a value, using the given opts. Options are derived from the cipher configuration. See encrypt/2.

Encrypt a value, using the given keyword list of options. These options derive from the cipher configuration, like so

Types

@type ciphertext() :: binary()
@type opts() :: Keyword.t()
@type plaintext() :: binary()

Callbacks

Link to this callback

can_decrypt?(ciphertext, opts)

View Source
@callback can_decrypt?(ciphertext(), opts()) :: boolean()

Determines if a given ciphertext can be decrypted by this cipher. Options are derived from the cipher configuration. See encrypt/2.

Link to this callback

decrypt(ciphertext, opts)

View Source
@callback decrypt(ciphertext(), opts()) :: {:ok, binary()} | :error

Decrypt a value, using the given opts. Options are derived from the cipher configuration. See encrypt/2.

Link to this callback

encrypt(plaintext, opts)

View Source
@callback encrypt(plaintext(), opts()) :: {:ok, binary()} | :error

Encrypt a value, using the given keyword list of options. These options derive from the cipher configuration, like so:

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

The above configuration will result in the following opts being passed to this function:

[tag: "AES.GCM.V1", key: <<1, 0, ...>>]

Your implementation must include any information it will need for decryption in the generated ciphertext.