diff --git a/lib/kryptonite/aes.ex b/lib/kryptonite/aes.ex index 12ed99c..5b2517f 100644 --- a/lib/kryptonite/aes.ex +++ b/lib/kryptonite/aes.ex @@ -11,8 +11,8 @@ defmodule Kryptonite.AES do illustrated such as: iex> {key, iv} = {generate_key!(), Random.bytes!(16)} - iex> {:ok, cypher} = encrypt_cbc(key, iv, "Message...") - iex> decrypt_cbc(key, iv, cypher) + iex> {:ok, cypher} = encrypt_ctr(key, iv, "Message...") + iex> decrypt_ctr(key, iv, cypher) "Message..." In GCM mode, the same flow could be performed like so: @@ -34,16 +34,7 @@ defmodule Kryptonite.AES do {:error, :decryption_error} """ - defmodule StreamIntegrityError do - defexception message: "Stream integrity failed to check" - - @moduledoc """ - Error when checking integrity of AES encrypted stream - """ - end - @key_byte_size 32 - @hmac_type :sha256 @typedoc "A key is a 256 bit length bitstring." @type key :: <<_::256>> @@ -91,13 +82,13 @@ defmodule Kryptonite.AES do ## Examples - iex> {:ok, cypher} = encrypt_cbc(generate_key!(), Random.bytes!(16), "Message...") + iex> {:ok, cypher} = encrypt_ctr(generate_key!(), Random.bytes!(16), "Message...") iex> is_bitstring(cypher) true """ - @spec encrypt_cbc(key, iv, binary) :: {:ok, cypher} | {:error, any} - def encrypt_cbc(key, iv, msg) do - {:ok, :crypto.block_encrypt(:aes_cbc256, key, iv, pad(msg))} + @spec encrypt_ctr(key, iv, binary) :: {:ok, cypher} | {:error, any} + def encrypt_ctr(key, iv, msg) do + {:ok, :aes_256_ctr |> :crypto.crypto_one_time(key, iv, pad(msg), true)} catch _, e -> {:error, e} end @@ -119,102 +110,13 @@ defmodule Kryptonite.AES do """ @spec encrypt_gcm(key, iv, binary, binary) :: {:ok, cypher, tag} | {:error, any} def encrypt_gcm(key, iv, ad, msg) do - :aes_gcm - |> :crypto.block_encrypt(key, iv, {ad, msg}) + :aes_256_gcm + |> :crypto.crypto_one_time_aead(key, iv, msg, ad, true) |> Tuple.insert_at(0, :ok) catch _, e -> {:error, e} end - @doc """ - Encrypts a stream using AES in CTR mode. - - ## Examples - - iex> {key, iv} = {generate_key!(), Random.bytes!(16)} - iex> 'This is a secret' - ...> |> stream_encrypt(key, iv) - ...> |> Enum.to_list() - ...> |> is_list() - true - """ - @spec stream_encrypt(Enumerable.t(), key, iv) :: Enumerable.t() - def stream_encrypt(stream, key, iv) do - acc0 = :crypto.stream_init(:aes_ctr, key, iv) - - reduce = fn elem, acc -> - {acc, cypher} = :crypto.stream_encrypt(acc, elem |> List.wrap()) - {[cypher], acc} - end - - Stream.transform(stream, acc0, reduce) - end - - @doc """ - Encrypts + HMAC a stream into a Collectable - - ## Examples - - iex> {key, iv} = {generate_key!(), Random.bytes!(16)} - iex> fid = 1000000 |> :rand.uniform() |> to_string - iex> {plain, enc} = {"/tmp/\#{fid}.txt", "/tmp/\#{fid}.aes"} - iex> File.write!(plain, "This is a secret") - iex> {:ok, tag} = plain - ...> |> File.stream!() - ...> |> stream_encrypt(File.stream!(enc), key, iv, "Auth...") - iex> Enum.each([plain, enc], &File.rm!/1) - iex> is_binary(tag) - true - """ - @spec stream_encrypt(Enumerable.t(), Collectable.t(), key, iv, binary) :: {:ok, tag} - def stream_encrypt(in_stream, out_stream, key, iv, ad) do - acc = :crypto.stream_init(:aes_ctr, key, iv) - - enc_stream = - in_stream - |> Stream.transform(acc, &do_stream_encrypt/2) - |> Stream.into(out_stream) - - tag = - [iv] - |> Stream.concat(enc_stream) - |> stream_tag(ad) - - {:ok, tag} - end - - @doc """ - Check integrity then decrypts a stream encrypted with `stream_encrypt/5` - - Raise `Kryptonite.AES.StreamIntegrityError` in case of integrity checking error. - - ## Examples - - iex> {key, iv} = {generate_key!(), Random.bytes!(16)} - iex> fid = 1000000 |> :rand.uniform() |> to_string - iex> {plain, enc} = {"/tmp/\#{fid}.txt", "/tmp/\#{fid}.aes"} - iex> File.write!(plain, "This is a secret") - iex> {:ok, tag} = plain - ...> |> File.stream!() - ...> |> stream_encrypt(File.stream!(enc), key, iv, "Auth...") - iex> enc - ...> |> File.stream!() - ...> |> stream_decrypt!(key, iv, "Auth...", tag) - ...> |> Enum.to_list() - ...> |> IO.iodata_to_binary() - "This is a secret" - """ - @spec stream_decrypt!(Enumerable.t(), key, binary, iv, tag) :: Enumerable.t() - def stream_decrypt!(in_stream, key, iv, ad, tag) do - [iv] - |> Stream.concat(in_stream) - |> stream_tag(ad) - |> case do - ^tag -> stream_decrypt(in_stream, key, iv) - _ -> raise StreamIntegrityError - end - end - @doc """ Decrypts a `cypher` using AES in CBC mode. @@ -225,15 +127,15 @@ defmodule Kryptonite.AES do iex> {key, iv} = {generate_key!(), Random.bytes!(16)} iex> msg = "Message..." - iex> {:ok, cypher} = encrypt_cbc(key, iv, msg) - iex> msg == decrypt_cbc(key, iv, cypher) + iex> {:ok, cypher} = encrypt_ctr(key, iv, msg) + iex> msg == decrypt_ctr(key, iv, cypher) true """ - @spec decrypt_cbc(key, iv, cypher) :: binary - def decrypt_cbc(key, iv, cypher), + @spec decrypt_ctr(key, iv, cypher) :: binary + def decrypt_ctr(key, iv, cypher), do: - :aes_cbc256 - |> :crypto.block_decrypt(key, iv, cypher) + :aes_256_ctr + |> :crypto.crypto_one_time(key, iv, cypher, false) |> unpad() @doc """ @@ -249,55 +151,14 @@ defmodule Kryptonite.AES do """ @spec decrypt_gcm(key, iv, binary, cypher, tag) :: {:ok, binary} | {:error, any} def decrypt_gcm(key, iv, ad, cypher, tag) do - :aes_gcm - |> :crypto.block_decrypt(key, iv, {ad, cypher, tag}) + :aes_256_gcm + |> :crypto.crypto_one_time_aead(key, iv, cypher, ad, tag, false) |> case do :error -> {:error, :decryption_error} msg when is_binary(msg) -> {:ok, msg} end end - @doc """ - Decrypts a stream using AES in CTR mode. - - ## Examples - - iex> {key, iv} = {generate_key!(), Random.bytes!(16)} - iex> "This is a secret..." - ...> |> String.to_charlist() - ...> |> stream_encrypt(key, iv) - ...> |> Enum.to_list() - ...> |> stream_decrypt(key, iv) - ...> |> Enum.to_list() - ...> |> :erlang.iolist_to_binary - "This is a secret..." - """ - @spec stream_decrypt(Enumerable.t(), key, iv) :: Enumerable.t() - def stream_decrypt(stream, key, iv) do - acc0 = - :aes_ctr - |> :crypto.stream_init(key, iv) - - reduce = fn elem, acc -> - {acc, cypher} = :crypto.stream_decrypt(acc, elem) - {[cypher], acc} - end - - Stream.transform(stream, acc0, reduce) - end - - @doc """ - Returns computed AES + HMAC encoded stream tag - """ - @spec stream_tag(Enumerable.t(), binary) :: tag - def stream_tag(stream, key) do - stream - |> Enum.reduce(:crypto.hmac_init(@hmac_type, key), fn data, acc -> - :crypto.hmac_update(acc, data) - end) - |> :crypto.hmac_final() - end - # Private stuff. @spec pad(binary) :: padded @@ -317,9 +178,4 @@ defmodule Kryptonite.AES do @spec cut_key(binary) :: binary defp cut_key(<>), do: key - - defp do_stream_encrypt(elem, acc) do - {acc, cypher} = :crypto.stream_encrypt(acc, List.wrap(elem)) - {[cypher], acc} - end end diff --git a/mix.exs b/mix.exs index bac9665..581a612 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule Kryptonite.MixProject do def project do [ app: :kryptonite, - version: "0.1.12", + version: "1.0.0", elixir: "~> 1.5", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, @@ -25,7 +25,7 @@ defmodule Kryptonite.MixProject do end def application do - [extra_applications: [:logger]] + [extra_applications: [:logger, :crypto, :public_key]] end defp elixirc_paths(:test), do: ["lib", "test/support"] @@ -34,12 +34,11 @@ defmodule Kryptonite.MixProject do defp deps do [ # Dev and Test only. - {:credo, "~> 0.8", only: [:dev, :test], runtime: false}, - {:dialyxir, "~> 0.5", only: [:dev, :test], runtime: false}, + {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, + {:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false}, # Dev only. - {:mix_test_watch, "~> 0.5", only: :dev, runtime: false}, - {:ex_doc, "~> 0.16", only: :dev, runtime: false}, - {:excoveralls, "~> 0.8", only: :test, runtime: false} + {:ex_doc, "~> 0.25", only: :dev, runtime: false}, + {:excoveralls, "~> 0.14", only: :test, runtime: false} ] end diff --git a/mix.lock b/mix.lock index 46b7072..dab06a5 100644 --- a/mix.lock +++ b/mix.lock @@ -1,22 +1,23 @@ %{ - "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, - "certifi": {:hex, :certifi, "2.4.2", "75424ff0f3baaccfd34b1214184b6ef616d89e420b258bb0a5ea7d7bc628f7f0", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, - "credo": {:hex, :credo, "0.10.2", "03ad3a1eff79a16664ed42fc2975b5e5d0ce243d69318060c626c34720a49512", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, - "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm"}, - "earmark": {:hex, :earmark, "1.3.0", "17f0c38eaafb4800f746b457313af4b2442a8c2405b49c645768680f900be603", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.19.1", "519bb9c19526ca51d326c060cb1778d4a9056b190086a8c6c115828eaccea6cf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.7", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.10.3", "b090a3fbcb3cfa136f0427d038c92a9051f840953ec11b40ee74d9d4eac04d1e", [:mix], [{:hackney, "~> 1.13", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, - "file_system": {:hex, :file_system, "0.2.6", "fd4dc3af89b9ab1dc8ccbcc214a0e60c41f34be251d9307920748a14bf41f1d3", [:mix], [], "hexpm"}, - "hackney": {:hex, :hackney, "1.14.3", "b5f6f5dcc4f1fba340762738759209e21914516df6be440d85772542d4a5e412", [:rebar3], [{:certifi, "2.4.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, - "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, - "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, - "makeup": {:hex, :makeup, "0.5.5", "9e08dfc45280c5684d771ad58159f718a7b5788596099bdfb0284597d368a882", [:mix], [{:nimble_parsec, "~> 0.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.10.0", "0f09c2ddf352887a956d84f8f7e702111122ca32fbbc84c2f0569b8b65cbf7fa", [:mix], [{:makeup, "~> 0.5.5", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, - "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, - "mix_test_watch": {:hex, :mix_test_watch, "0.9.0", "c72132a6071261893518fa08e121e911c9358713f62794a90c95db59042af375", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm"}, - "nimble_parsec": {:hex, :nimble_parsec, "0.4.0", "ee261bb53214943679422be70f1658fff573c5d0b0a1ecd0f18738944f818efe", [:mix], [], "hexpm"}, - "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"}, + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, + "certifi": {:hex, :certifi, "2.8.0", "d4fb0a6bb20b7c9c3643e22507e42f356ac090a1dcea9ab99e27e0376d695eba", [:rebar3], [], "hexpm", "6ac7efc1c6f8600b08d625292d4bbf584e14847ce1b6b5c44d983d273e1097ea"}, + "credo": {:hex, :credo, "1.5.6", "e04cc0fdc236fefbb578e0c04bd01a471081616e741d386909e527ac146016c6", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "4b52a3e558bd64e30de62a648518a5ea2b6e3e5d2b164ef5296244753fc7eb17"}, + "dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.15", "b29e8e729f4aa4a00436580dcc2c9c5c51890613457c193cc8525c388ccb2f06", [:mix], [], "hexpm", "044523d6438ea19c1b8ec877ec221b008661d3c27e3b848f4c879f500421ca5c"}, + "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, + "ex_doc": {:hex, :ex_doc, "0.25.3", "3edf6a0d70a39d2eafde030b8895501b1c93692effcbd21347296c18e47618ce", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "9ebebc2169ec732a38e9e779fd0418c9189b3ca93f4a676c961be6c1527913f5"}, + "excoveralls": {:hex, :excoveralls, "0.14.3", "d17dc249ad32e469afd2bc656b58e810109d4367ec6bd467bed57a84dc4a3e02", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "b5aecdfdcf48e9d5e1c210841589b30981a5e7e66055cb8691a6f90b1601c108"}, + "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, + "hackney": {:hex, :hackney, "1.18.0", "c4443d960bb9fba6d01161d01cd81173089686717d9490e5d3606644c48d121f", [:rebar3], [{:certifi, "~>2.8.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "9afcda620704d720db8c6a3123e9848d09c87586dc1c10479c42627b905b5c5e"}, + "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, + "jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"}, + "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, + "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"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, } diff --git a/test/kryptonite/aes_test.exs b/test/kryptonite/aes_test.exs index 49d75fd..9cd167d 100644 --- a/test/kryptonite/aes_test.exs +++ b/test/kryptonite/aes_test.exs @@ -1,13 +1,13 @@ defmodule Kryptonite.AESTest do use ExUnit.Case, async: true - alias Kryptonite.{AES, AES.StreamIntegrityError, Random} + alias Kryptonite.{AES, Random} doctest AES, import: true @password "Some re4lly secUre stuff!" @message "Some simple\ntext message." @auth_data "Some random stuff." - describe ".generate_key!/0" do + describe "generate_key!/0" do test "generate an AES key the right size" do assert 256 == bit_size(AES.generate_key!()) end @@ -17,7 +17,7 @@ defmodule Kryptonite.AESTest do end end - describe ".generate_key/0" do + describe "generate_key/0" do test "generate an AES key the right size" do {:ok, key} = AES.generate_key() assert 256 == bit_size(key) @@ -28,7 +28,7 @@ defmodule Kryptonite.AESTest do end end - describe ".derive_key/1+1" do + describe "derive_key/1+1" do @opts [salt: "S", rounds: 2] test "generates a key given a password" do assert 256 == @@ -42,16 +42,16 @@ defmodule Kryptonite.AESTest do end end - describe ".encrypt_cbc/3" do + describe "encrypt_ctr/3" do setup :key test "encrypts properly", %{key: key, iv: iv} do - {:ok, cypher} = AES.encrypt_cbc(key, iv, @message) + {:ok, cypher} = AES.encrypt_ctr(key, iv, @message) assert is_bitstring(cypher) end end - describe ".encrypt_gcm/4" do + describe "encrypt_gcm/4" do setup :key test "encrypts properly", %{key: key, iv: iv} do @@ -60,80 +60,16 @@ defmodule Kryptonite.AESTest do end end - describe ".stream_encrypt/3" do - setup :key - - test "outputs a stream list", %{key: key, iv: iv} do - assert 'This is a secret' - |> AES.stream_encrypt(key, iv) - |> Enum.to_list() - |> is_list() - end - end - - describe ".stream_encrypt/5" do - setup :key - - test "encrypts files", %{key: key, iv: iv} do - fid = :rand.uniform(1_000_000) - {plain, enc} = {"/tmp/#{fid}.txt", "/tmp/#{fid}.aes"} - File.write!(plain, @message) - - {:ok, tag} = - plain - |> File.stream!() - |> AES.stream_encrypt(File.stream!(enc), key, iv, @auth_data) - - Enum.each([plain, enc], &File.rm!/1) - assert is_binary(tag) - end - end - - describe ".stream_decrypt/5" do + describe "decrypt_ctr/3" do setup :key test "decrypts the original message", %{key: key, iv: iv} do - fid = :rand.uniform(1_000_000) - {plain, enc} = {"/tmp/#{fid}.txt", "/tmp/#{fid}.aes"} - File.write!(plain, @message) - - {:ok, tag} = - plain - |> File.stream!() - |> AES.stream_encrypt(File.stream!(enc), key, iv, @auth_data) - - assert @message == - enc - |> File.stream!() - |> AES.stream_decrypt!(key, iv, @auth_data, tag) - |> Enum.to_list() - |> IO.iodata_to_binary() - end - - test "raises when the stream is corrupted", %{key: key, iv: iv} do - fid = :rand.uniform(1_000_000) - enc = "/tmp/#{fid}.aes" - File.write!(enc, "incorrect data") - tag = <<0::size(128)>> - - assert_raise StreamIntegrityError, fn -> - enc - |> File.stream!() - |> AES.stream_decrypt!(key, iv, @auth_data, tag) - end - end - end - - describe ".decrypt_cbc/3" do - setup :key - - test "decrypts the original message", %{key: key, iv: iv} do - {:ok, cypher} = AES.encrypt_cbc(key, iv, @message) - assert @message == AES.decrypt_cbc(key, iv, cypher) + {:ok, cypher} = AES.encrypt_ctr(key, iv, @message) + assert @message == AES.decrypt_ctr(key, iv, cypher) end end - describe ".decrypt_gcm/5" do + describe "decrypt_gcm/5" do setup :key test "decrypts the original message", %{key: key, iv: iv} do @@ -149,24 +85,6 @@ defmodule Kryptonite.AESTest do end end - describe "stream_decrypt!/3" do - setup :key - - test "decrypts a stream", %{key: key, iv: iv} do - cypher = - @message - |> String.to_charlist() - |> AES.stream_encrypt(key, iv) - |> Enum.to_list() - - assert @message == - cypher - |> AES.stream_decrypt(key, iv) - |> Enum.to_list() - |> :erlang.iolist_to_binary() - end - end - defp key(_) do key = AES.generate_key!() {:ok, key: key, iv: Random.bytes!(16)} diff --git a/test/kryptonite/rsa/private_key_test.exs b/test/kryptonite/rsa/private_key_test.exs index a29389c..964f45c 100644 --- a/test/kryptonite/rsa/private_key_test.exs +++ b/test/kryptonite/rsa/private_key_test.exs @@ -66,7 +66,7 @@ defmodule Kryptonite.RSA.PrivateKeyTest do PrivateKey.to_native(key) end - test "only hanndles known versions" do + test "only handles known versions" do key = %PrivateKey{version: :bad} assert {:error, :invalid_native_version} == PrivateKey.to_native(key) end