diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 8978217..d88dd33 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -29,8 +29,11 @@ blocks: - name: "Build" matrix: - env_var: ELIXIR_VERSION - values: ["1.11.3"] + values: ["1.11.3", "1.12.1"] + - env_var: ERLANG_VERSION + values: ["23.3", "24.0"] commands: + - sem-version erlang $ERLANG_VERSION - sem-version elixir $ELIXIR_VERSION - sem-service start postgres - checkout diff --git a/Dockerfile b/Dockerfile index 9cb479d..8986725 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,9 @@ -FROM hexpm/elixir:1.11.3-erlang-23.2.2-ubuntu-focal-20201008 +FROM hexpm/elixir:1.12.1-erlang-24.0.2-ubuntu-focal-20210325 # Install debian packages RUN apt-get update RUN apt-get install --yes build-essential inotify-tools postgresql-client +RUN apt-get install --yes git RUN mix local.hex --force RUN mix local.rebar --force diff --git a/bin/test b/bin/test index 0a27ec9..fc2f929 100755 --- a/bin/test +++ b/bin/test @@ -4,7 +4,10 @@ # # This script contains all the test commands for this app, which will be run # on the continuous integration server. +if [ "$ELIXIR_VERSION" != "1.11.3" ]; then MIX_ENV=test mix format --check-formatted || { echo 'Code was not formatted!'; exit 1; } +fi + MIX_ENV=test mix compile --force --warnings-as-errors || { echo 'Please fix all compiler warnings.'; exit 1; } if [ ! $CI ]; then diff --git a/coveralls.json b/coveralls.json index 16d1b54..1303d58 100644 --- a/coveralls.json +++ b/coveralls.json @@ -2,6 +2,7 @@ "skip_files": [ "lib/cloak_ecto.ex", "lib/cloak_ecto/migrator/custom_cursor.ex", + "lib/cloak_ecto/crypto.ex", "test/*" ] -} \ No newline at end of file +} diff --git a/guides/how_to/install.md b/guides/how_to/install.md index f00ca84..ea532d3 100644 --- a/guides/how_to/install.md +++ b/guides/how_to/install.md @@ -6,7 +6,7 @@ This guide will walk you through installing `Cloak.Ecto` in your project. First, add `:cloak_ecto` to your dependencies in `mix.exs`: - {:cloak_ecto, "~> 1.0.1"} + {:cloak_ecto, "~> 1.3.0"} Run `mix deps.get` to fetch the dependency. Since `:cloak_ecto` relies on `:cloak`, the `:cloak` package will also be installed. diff --git a/lib/cloak_ecto/crypto.ex b/lib/cloak_ecto/crypto.ex new file mode 100644 index 0000000..1f8d316 --- /dev/null +++ b/lib/cloak_ecto/crypto.ex @@ -0,0 +1,16 @@ +defmodule Cloak.Ecto.Crypto do + @moduledoc false + @behaviour Cloak.Ecto.Crypto.Interface + + if System.otp_release() >= "22" do + @impl Cloak.Ecto.Crypto.Interface + def hmac(algorithm, key, data) do + :crypto.mac(:hmac, algorithm, key, data) + end + else + @impl Cloak.Ecto.Crypto.Interface + def hmac(algorithm, key, data) do + :crypto.hmac(algorithm, key, data) + end + end +end diff --git a/lib/cloak_ecto/crypto/interface.ex b/lib/cloak_ecto/crypto/interface.ex new file mode 100644 index 0000000..40b2301 --- /dev/null +++ b/lib/cloak_ecto/crypto/interface.ex @@ -0,0 +1,8 @@ +defmodule Cloak.Ecto.Crypto.Interface do + @moduledoc false + @type algorithm :: atom() + @type secret :: binary + @type value :: iodata + + @callback hmac(atom(), secret, value) :: binary +end diff --git a/lib/cloak_ecto/types/hmac.ex b/lib/cloak_ecto/types/hmac.ex index 5bf7d2b..7bbca71 100644 --- a/lib/cloak_ecto/types/hmac.ex +++ b/lib/cloak_ecto/types/hmac.ex @@ -102,6 +102,8 @@ defmodule Cloak.Ecto.HMAC do otp_app = Keyword.fetch!(opts, :otp_app) quote do + alias Cloak.Ecto.Crypto + @behaviour Cloak.Ecto.HMAC @behaviour Ecto.Type @algorithms ~w[ @@ -142,7 +144,7 @@ defmodule Cloak.Ecto.HMAC do def dump(value) when is_binary(value) do config = build_config() - {:ok, :crypto.hmac(config[:algorithm], config[:secret], value)} + {:ok, Crypto.hmac(config[:algorithm], config[:secret], value)} end def dump(_value) do diff --git a/lib/cloak_ecto/types/pbkdf2.ex b/lib/cloak_ecto/types/pbkdf2.ex index 3cb8eaf..41d9a98 100644 --- a/lib/cloak_ecto/types/pbkdf2.ex +++ b/lib/cloak_ecto/types/pbkdf2.ex @@ -189,9 +189,7 @@ if Code.ensure_loaded?(:pbkdf2) do algo = inspect(config[:algorithm]) raise Cloak.InvalidConfig, - "#{algo} is an invalid hash algorithm for #{m}, must be in #{ - inspect(@algorithms) - }" + "#{algo} is an invalid hash algorithm for #{m}, must be in #{inspect(@algorithms)}" end unless is_integer(config[:iterations]) && config[:iterations] > 0 do diff --git a/mix.exs b/mix.exs index a49cf3a..051039c 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule Cloak.Ecto.MixProject do def project do [ app: :cloak_ecto, - version: "1.1.1", + version: "1.3.0", elixir: "~> 1.7", start_permanent: Mix.env() == :prod, test_coverage: [tool: ExCoveralls], @@ -35,9 +35,11 @@ defmodule Cloak.Ecto.MixProject do defp deps do [ - {:cloak, "~> 1.0.0"}, + {:cloak, "~> 1.1.1"}, {:ecto, "~> 3.0"}, - {:pbkdf2, "~> 2.0", optional: true}, + # Must use a forked version of pbkdf2 to support Erlang 24 + # See https://github.com/basho/erlang-pbkdf2/pull/12 + {:pbkdf2, "~> 2.0", optional: true, github: "miniclip/erlang-pbkdf2"}, {:ex_doc, ">= 0.0.0", only: :dev}, {:excoveralls, ">= 0.0.0", only: :test}, {:ecto_sql, ">= 0.0.0", only: [:dev, :test]}, diff --git a/mix.lock b/mix.lock index 873bb2f..b3d952a 100644 --- a/mix.lock +++ b/mix.lock @@ -1,7 +1,7 @@ %{ "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, "certifi": {:hex, :certifi, "2.5.3", "70bdd7e7188c804f3a30ee0e7c99655bc35d8ac41c23e12325f36ab449b70651", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "ed516acb3929b101208a9d700062d520f3953da3b6b918d866106ffa980e1c10"}, - "cloak": {:hex, :cloak, "1.0.3", "af8acef9e08e744441e961921c95a660074f9689892e18445ad8a60d5059aa10", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:pbkdf2, "~> 2.0", [hex: :pbkdf2, repo: "hexpm", optional: true]}], "hexpm", "130afd15b845f4cabb0be8df64ec93a59ff30657c539d454f7f747145c4e2452"}, + "cloak": {:hex, :cloak, "1.1.1", "6f8f6674cacd3c504daf2aaeba8f9cde3ae8009ce01ff854dd3e92fbb7954c69", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "d440c4ea3a5a31baeaea4592b534dfdccc4ded0ee098b92955a5658cbe7be625"}, "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, "db_connection": {:hex, :db_connection, "2.3.1", "4c9f3ed1ef37471cbdd2762d6655be11e38193904d9c5c1c9389f1b891a3088e", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "abaab61780dde30301d840417890bd9f74131041afd02174cf4e10635b3a63f5"}, "decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"}, @@ -21,7 +21,7 @@ "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, - "pbkdf2": {:hex, :pbkdf2, "2.0.0", "11c23279fded5c0027ab3996cfae77805521d7ef4babde2bd7ec04a9086cf499", [:rebar3], [], "hexpm", "1e793ce6fdb0576613115714deae9dfc1d1537eaba74f07efb36de139774488d"}, + "pbkdf2": {:git, "https://github.com/miniclip/erlang-pbkdf2.git", "75ef2d829962349395c53b630e844a729e5d9c53", []}, "postgrex": {:hex, :postgrex, "0.15.8", "f5e782bbe5e8fa178d5e3cd1999c857dc48eda95f0a4d7f7bd92a50e84a0d491", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "698fbfacea34c4cf22c8281abeb5cf68d99628d541874f085520ab3b53d356fe"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"}, diff --git a/test/cloak_ecto/types/hmac_test.exs b/test/cloak_ecto/types/hmac_test.exs index c5c8aca..752c7a0 100644 --- a/test/cloak_ecto/types/hmac_test.exs +++ b/test/cloak_ecto/types/hmac_test.exs @@ -1,6 +1,8 @@ defmodule Cloak.Ecto.HMACTest do use ExUnit.Case + alias Cloak.Ecto.Crypto + defmodule HMAC do use Cloak.Ecto.HMAC, otp_app: :cloak @@ -46,7 +48,7 @@ defmodule Cloak.Ecto.HMACTest do test "hashes binaries" do assert {:ok, hash} = HMAC.dump("plaintext") - assert hash == :crypto.hmac(:sha512, "secret", "plaintext") + assert hash == Crypto.hmac(:sha512, "secret", "plaintext") end test "returns :error for all other types" do