Skip to content

Commit

Permalink
Decode AES environment variable keys from base64
Browse files Browse the repository at this point in the history
This is needed because the user will probably store the keys encoded as
base64 when using environment variables.

This also adds a basic error report when the expected key is missing or
is not a valid base64 string.

Closes #9 - #9.
  • Loading branch information
philss committed May 20, 2016
1 parent adf7831 commit 66645d0
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
3 changes: 2 additions & 1 deletion config/test.exs
Expand Up @@ -5,5 +5,6 @@ config :cloak, Cloak.AES.CTR,
default: true,
keys: [
%{tag: <<1>>, key: :base64.decode("3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE="), default: true},
%{tag: <<2>>, key: :base64.decode("iutsyenD9K2psbQNIvdf/UTBYrFH1ONJlQUpQ6nRoAw="), default: false}
%{tag: <<2>>, key: :base64.decode("iutsyenD9K2psbQNIvdf/UTBYrFH1ONJlQUpQ6nRoAw="), default: false},
%{tag: <<3>>, key: {:system, "CLOAK_THIRD_KEY"}, default: false}
]
26 changes: 20 additions & 6 deletions lib/cloak/ciphers/aes_ctr.ex
Expand Up @@ -4,8 +4,8 @@ defmodule Cloak.AES.CTR do
## Configuration
In addition to the normal `:default` and `:tag` configuration options, this
cipher takes a `:keys` option to support using multiple AES keys at the same
In addition to the normal `:default` and `:tag` configuration options, this
cipher takes a `:keys` option to support using multiple AES keys at the same
time.
config :cloak, Cloak.AES.CTR,
Expand All @@ -24,7 +24,7 @@ defmodule Cloak.AES.CTR do
tag: "AES",
keys: [
%{tag: <<1>>, key: {:system, "CLOAK_KEY_PRIMARY"}, default: true},
%{tag: <<2>>, key: {:system, "CLOAK_KEY_SECONDAY"}, default: false}
%{tag: <<2>>, key: {:system, "CLOAK_KEY_SECONDARY"}, default: false}
]
### Key Configuration Options
Expand All @@ -35,7 +35,7 @@ defmodule Cloak.AES.CTR do
only a single byte. See `encrypt/2` for more details.
- `:key` - The AES key to use, in binary. If you store your keys in Base64
format you will need to decode them first. The key must be 128, 192, or 256 bits
format you will need to decode them first. The key must be 128, 192, or 256 bits
long (16, 24 or 32 bytes, respectively).
- `:default` - Boolean. Whether to use this key by default or not.
Expand Down Expand Up @@ -67,7 +67,7 @@ defmodule Cloak.AES.CTR do
@tag @key.tag

@doc """
Callback implementation for `Cloak.Cipher.encrypt`. Encrypts a value using
Callback implementation for `Cloak.Cipher.encrypt`. Encrypts a value using
AES in CTR mode.
Generates a random IV for every encryption, and prepends the key tag and IV to
Expand Down Expand Up @@ -156,9 +156,23 @@ defmodule Cloak.AES.CTR do
case key_config.key do
{:system, env_var} ->
System.get_env(env_var)

|> validate_key(env_var)
|> decode_key(env_var)

_ ->
key_config.key
end
end

defp validate_key(key, env_var) when key in [nil, ""] do
raise "Expect env variable #{env_var} to define a key, but is empty."
end
defp validate_key(key, _), do: key

defp decode_key(key, env_var) do
case Base.decode64(key) do
{:ok, decoded_key} -> decoded_key
:error -> raise "Expect env variable #{env_var} to be a valid base64 string."
end
end
end
6 changes: 6 additions & 0 deletions test/cloak/ciphers/aes_ctr_test.exs
Expand Up @@ -18,6 +18,12 @@ defmodule Cloak.AES.CTRTest do
assert String.length(ciphertext) > 0
end

test ".encrypt can encrypt a value using an environment variable as key" do
System.put_env("CLOAK_THIRD_KEY", "NhsNVkstdaUiXIh6fFZaRu+O6gK/p9C9LKJr3kkEWNA=")

assert encrypt("value", <<3>>) != "value"
end

test ".decrypt can decrypt a value" do
assert encrypt("value") |> decrypt == "value"
end
Expand Down

0 comments on commit 66645d0

Please sign in to comment.