From e6040c527a118778354dd5773fd1e35e16271409 Mon Sep 17 00:00:00 2001 From: Niklas Lindgren Date: Fri, 17 May 2024 16:42:20 +0300 Subject: [PATCH 1/3] style: naming --- test/erebus_test.exs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/erebus_test.exs b/test/erebus_test.exs index 0a2fbb5..00e6e64 100644 --- a/test/erebus_test.exs +++ b/test/erebus_test.exs @@ -10,7 +10,7 @@ defmodule Erebus.Test do :ok end - defmodule EncryptedStuff do + defmodule EncryptedModel do use Ecto.Schema import Ecto.Changeset import Erebus.Schema @@ -47,11 +47,11 @@ defmodule Erebus.Test do end test "encrypting and decrypting data with ecto" do - model = %EncryptedStuff{} + model = %EncryptedModel{} encrypted = model - |> EncryptedStuff.changeset(%{first: "hello", second: "there"}) + |> EncryptedModel.changeset(%{first: "hello", second: "there"}) |> Ecto.Changeset.apply_changes() # simulate reloading with virtual fields emptied |> Map.merge(%{first: nil, second: nil}) @@ -86,7 +86,7 @@ defmodule Erebus.Test do encrypted_2 = encrypted - |> EncryptedStuff.changeset(%{second: "thereX"}) + |> EncryptedModel.changeset(%{second: "thereX"}) |> Ecto.Changeset.apply_changes() assert hash_before != encrypted_2.first_encrypted @@ -96,7 +96,7 @@ defmodule Erebus.Test do encrypted_3 = encrypted - |> EncryptedStuff.changeset(%{other: "somestring"}) + |> EncryptedModel.changeset(%{other: "somestring"}) |> Ecto.Changeset.apply_changes() assert hash_before == encrypted_3.first_encrypted @@ -104,11 +104,11 @@ defmodule Erebus.Test do end test "encrypting and decrypting data with one field being null" do - model = %EncryptedStuff{} + model = %EncryptedModel{} encrypted = model - |> EncryptedStuff.changeset(%{first: "hello"}) + |> EncryptedModel.changeset(%{first: "hello"}) |> Ecto.Changeset.apply_changes() # simulate reloading with virtual fields emptied |> Map.merge(%{first: nil}) @@ -130,11 +130,11 @@ defmodule Erebus.Test do end test "forcing data reencryption" do - model = %EncryptedStuff{first: "hello"} + model = %EncryptedModel{first: "hello"} encrypted = model - |> EncryptedStuff.changeset(%{}, true) + |> EncryptedModel.changeset(%{}, true) |> Ecto.Changeset.apply_changes() # simulate reloading with virtual fields emptied |> Map.merge(%{first: nil}) From 11a671d34e99d8b29d5bf84fd73bfd24d49cc6b4 Mon Sep 17 00:00:00 2001 From: Niklas Lindgren Date: Fri, 17 May 2024 16:53:22 +0300 Subject: [PATCH 2/3] style: coding style --- lib/erebus.ex | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/erebus.ex b/lib/erebus.ex index 93fa103..1f69079 100644 --- a/lib/erebus.ex +++ b/lib/erebus.ex @@ -96,12 +96,13 @@ defmodule Erebus do * options - providing backend and options for that backend """ def decrypt(struct, fields_to_decrypt, opts \\ []) do - encrypted_dek = struct.dek |> Erebus.EncryptedData.cast_if_needed() + encrypted_dek = Erebus.EncryptedData.cast_if_needed(struct.dek) decrypted_dek = Erebus.SymmetricKeyStore.get_key(encrypted_dek, opts) decrypted_fields = - Enum.map(fields_to_decrypt, fn field -> + fields_to_decrypt + |> Enum.map(fn field -> stringified_field = Atom.to_string(field) encrypted_field = Map.get(struct, String.to_atom(stringified_field <> "_encrypted")) @@ -181,13 +182,18 @@ defmodule Erebus do nil -> nil - field -> + field_name -> aead = :crypto.strong_rand_bytes(16) iv = :crypto.strong_rand_bytes(16) - stringified = Atom.to_string(field) + stringified = Atom.to_string(field_name) - data_to_encrypt = struct.changes |> Map.get(field) || Map.get(struct.data, field) + data_to_encrypt = + Map.get_lazy( + struct.changes, + field_name, + fn -> Map.get(struct.data, field_name) end + ) if not is_nil(data_to_encrypt) do {ciphertext, ciphertag} = From b68d3b5a36af4a0831213966d87974e89fc4c1b2 Mon Sep 17 00:00:00 2001 From: Niklas Lindgren Date: Fri, 17 May 2024 16:54:32 +0300 Subject: [PATCH 3/3] feat: keep nil values on cloaked fields they don't need to be encrypted (although maybe they still should be, as keeping nil values plain is revealing), but by discarding nil value fields it becomes impossible to set a cloaked field to nil --- lib/erebus.ex | 1 - test/erebus_test.exs | 11 +++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/erebus.ex b/lib/erebus.ex index 1f69079..35a2834 100644 --- a/lib/erebus.ex +++ b/lib/erebus.ex @@ -224,7 +224,6 @@ defmodule Erebus do ] end end) - |> Enum.filter(& &1) |> List.flatten() |> Enum.into(%{}) diff --git a/test/erebus_test.exs b/test/erebus_test.exs index 00e6e64..5880b31 100644 --- a/test/erebus_test.exs +++ b/test/erebus_test.exs @@ -153,4 +153,15 @@ defmodule Erebus.Test do assert "hello" == decrypted_first.first end + + test "setting a field to nil" do + model = %EncryptedModel{first: "beep", second: "boop"} + + encrypted = + model + |> EncryptedModel.changeset(%{}, true) + |> Ecto.Changeset.apply_changes() + + raise "test not implemented" + end end