From bfcd9eabbb563ba97f8120c6fc34bbf8e5de997d Mon Sep 17 00:00:00 2001 From: Pierre Martin Date: Mon, 29 Sep 2025 17:49:53 +0200 Subject: [PATCH] Prototype of base64 wrapped encrypted value. --- lib/encrypted-base64.ex | 50 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 lib/encrypted-base64.ex diff --git a/lib/encrypted-base64.ex b/lib/encrypted-base64.ex new file mode 100644 index 0000000..026eecc --- /dev/null +++ b/lib/encrypted-base64.ex @@ -0,0 +1,50 @@ +defmodule Fields.EncryptedBase64 do + @moduledoc """ + An Ecto Type for encrypted fields. + See `Fields.AES` for details on encryption/decryption. + + ## Example + + schema "users" do + field :name, Fields.EncryptedBase64 + end + """ + use Ecto.Type + alias Fields.AES + require Logger + + def type(), + do: :string + + def cast(value), + do: {:ok, to_string(value)} + + def dump(value), + do: + value + |> then(fn + # Input value is nil. Store as-is. It's the developer's job + # to run validations if they don't want that. + nil -> value + # Value is any kind of binary. Encrypt, and base64 encode. + <<>> <> _ -> value |> to_string |> AES.encrypt() |> Base.encode64(padding: true) + end) + |> then(& {:ok, &1}) + + def load(value), + do: + value + |> then(fn + # We got nil from the database... Just use that. + nil -> value + # We got any binary. Decode64 and decrypt. + <<>> <> _ -> value |> Base.decode64!(padding: true) |> AES.decrypt() + end) + |> then(& {:ok, &1}) + + def embed_as(_), + do: :dump + + def equal?(term1, term2), + do: term1 == term2 +end