Current section
13 Versions
Jump to
Current section
13 Versions
Compare versions
5
files changed
+26
additions
-19
deletions
| @@ -1,5 +1,9 @@ | |
| 1 1 | # Changelog |
| 2 2 | |
| 3 | + ## v1.2.4 (2023-03-10) |
| 4 | + |
| 5 | + * Allow AAD to be given as argument on message encryptor |
| 6 | + |
| 3 7 | ## v1.2.3 (2022-08-19) |
| 4 8 | |
| 5 9 | * Remove warnings on Elixir v1.14 |
| @@ -14,4 +14,4 @@ | |
| 14 14 | [{<<"GitHub">>,<<"https://github.com/elixir-plug/plug_crypto">>}]}. |
| 15 15 | {<<"name">>,<<"plug_crypto">>}. |
| 16 16 | {<<"requirements">>,[]}. |
| 17 | - {<<"version">>,<<"1.2.3">>}. |
| 17 | + {<<"version">>,<<"1.2.4">>}. |
| @@ -29,10 +29,14 @@ defmodule Plug.Crypto.MessageEncryptor do | |
| 29 29 | |
| 30 30 | @doc """ |
| 31 31 | Encrypts a message using authenticated encryption. |
| 32 | + |
| 33 | + A custom authentication message can be provided. |
| 34 | + It defaults to "A128GCM" for backwards compatibility. |
| 32 35 | """ |
| 33 | - def encrypt(message, secret, sign_secret) |
| 34 | - when is_binary(message) and byte_size(secret) > 0 and is_binary(sign_secret) do |
| 35 | - aes128_gcm_encrypt(message, secret, sign_secret) |
| 36 | + def encrypt(message, aad \\ "A128GCM", secret, sign_secret) |
| 37 | + when is_binary(message) and is_binary(aad) and byte_size(secret) > 0 and |
| 38 | + is_binary(sign_secret) do |
| 39 | + aes128_gcm_encrypt(message, aad, secret, sign_secret) |
| 36 40 | rescue |
| 37 41 | e -> reraise e, Plug.Crypto.prune_args_from_stacktrace(__STACKTRACE__) |
| 38 42 | end |
| @@ -40,9 +44,10 @@ defmodule Plug.Crypto.MessageEncryptor do | |
| 40 44 | @doc """ |
| 41 45 | Decrypts a message using authenticated encryption. |
| 42 46 | """ |
| 43 | - def decrypt(encrypted, secret, sign_secret) |
| 44 | - when is_binary(encrypted) and byte_size(secret) > 0 and is_binary(sign_secret) do |
| 45 | - aes128_gcm_decrypt(encrypted, secret, sign_secret) |
| 47 | + def decrypt(encrypted, aad \\ "A128GCM", secret, sign_secret) |
| 48 | + when is_binary(encrypted) and is_binary(aad) and byte_size(secret) > 0 and |
| 49 | + is_binary(sign_secret) do |
| 50 | + aes128_gcm_decrypt(encrypted, aad, secret, sign_secret) |
| 46 51 | rescue |
| 47 52 | e -> reraise e, Plug.Crypto.prune_args_from_stacktrace(__STACKTRACE__) |
| 48 53 | end |
| @@ -51,19 +56,18 @@ defmodule Plug.Crypto.MessageEncryptor do | |
| 51 56 | # |
| 52 57 | # A random 128-bit content encryption key (CEK) is generated for |
| 53 58 | # every message which is then encrypted with `aes_gcm_key_wrap/3`. |
| 54 | - defp aes128_gcm_encrypt(plain_text, secret, sign_secret) when bit_size(secret) > 256 do |
| 55 | - aes128_gcm_encrypt(plain_text, binary_part(secret, 0, 32), sign_secret) |
| 59 | + defp aes128_gcm_encrypt(plain_text, aad, secret, sign_secret) when bit_size(secret) > 256 do |
| 60 | + aes128_gcm_encrypt(plain_text, aad, binary_part(secret, 0, 32), sign_secret) |
| 56 61 | end |
| 57 62 | |
| 58 | - defp aes128_gcm_encrypt(plain_text, secret, sign_secret) |
| 63 | + defp aes128_gcm_encrypt(plain_text, aad, secret, sign_secret) |
| 59 64 | when is_binary(plain_text) and bit_size(secret) in [128, 192, 256] and |
| 60 65 | is_binary(sign_secret) do |
| 61 66 | key = :crypto.strong_rand_bytes(16) |
| 62 67 | iv = :crypto.strong_rand_bytes(12) |
| 63 | - aad = "A128GCM" |
| 64 68 | {cipher_text, cipher_tag} = block_encrypt(:aes_gcm, key, iv, {aad, plain_text}) |
| 65 69 | encrypted_key = aes_gcm_key_wrap(key, secret, sign_secret) |
| 66 | - encode_token(aad, encrypted_key, iv, cipher_text, cipher_tag) |
| 70 | + encode_token("A128GCM", encrypted_key, iv, cipher_text, cipher_tag) |
| 67 71 | end |
| 68 72 | |
| 69 73 | # Verifies and decrypts a message using AES128-GCM mode. |
| @@ -72,15 +76,15 @@ defmodule Plug.Crypto.MessageEncryptor do | |
| 72 76 | # |
| 73 77 | # The encrypted content encryption key (CEK) is decrypted |
| 74 78 | # with `aes_gcm_key_unwrap/3`. |
| 75 | - defp aes128_gcm_decrypt(cipher_text, secret, sign_secret) when bit_size(secret) > 256 do |
| 76 | - aes128_gcm_decrypt(cipher_text, binary_part(secret, 0, 32), sign_secret) |
| 79 | + defp aes128_gcm_decrypt(cipher_text, aad, secret, sign_secret) when bit_size(secret) > 256 do |
| 80 | + aes128_gcm_decrypt(cipher_text, aad, binary_part(secret, 0, 32), sign_secret) |
| 77 81 | end |
| 78 82 | |
| 79 | - defp aes128_gcm_decrypt(cipher_text, secret, sign_secret) |
| 83 | + defp aes128_gcm_decrypt(cipher_text, aad, secret, sign_secret) |
| 80 84 | when is_binary(cipher_text) and bit_size(secret) in [128, 192, 256] and |
| 81 85 | is_binary(sign_secret) do |
| 82 86 | case decode_token(cipher_text) do |
| 83 | - {aad = "A128GCM", encrypted_key, iv, cipher_text, cipher_tag} |
| 87 | + {"A128GCM", encrypted_key, iv, cipher_text, cipher_tag} |
| 84 88 | when bit_size(iv) === 96 and bit_size(cipher_tag) === 128 -> |
| 85 89 | encrypted_key |
| 86 90 | |> aes_gcm_key_unwrap(secret, sign_secret) |
| @@ -120,7 +124,6 @@ defmodule Plug.Crypto.MessageEncryptor do | |
| 120 124 | :error, :notsup -> raise_notsup(cipher) |
| 121 125 | end |
| 122 126 | |
| 123 | - # TODO: remove when we reqwuire OTP 24 (since it has similar alias handling) |
| 124 127 | defp cipher_alias(:aes_gcm, 128), do: :aes_128_gcm |
| 125 128 | defp cipher_alias(:aes_gcm, 192), do: :aes_192_gcm |
| 126 129 | defp cipher_alias(:aes_gcm, 256), do: :aes_256_gcm |
| @@ -77,7 +77,7 @@ defmodule Plug.Crypto.MessageVerifier do | |
| 77 77 | |
| 78 78 | defp decode_token(token) do |
| 79 79 | with [protected, payload, signature] <- String.split(token, ".", parts: 3), |
| 80 | - plain_text = protected <> "." <> payload, |
| 80 | + plain_text = [protected, ?., payload], |
| 81 81 | {:ok, protected} <- Base.url_decode64(protected, padding: false), |
| 82 82 | {:ok, payload} <- Base.url_decode64(payload, padding: false), |
| 83 83 | {:ok, signature} <- Base.url_decode64(signature, padding: false) do |
| @@ -1,7 +1,7 @@ | |
| 1 1 | defmodule Plug.Crypto.MixProject do |
| 2 2 | use Mix.Project |
| 3 3 | |
| 4 | - @version "1.2.3" |
| 4 | + @version "1.2.4" |
| 5 5 | @description "Crypto-related functionality for the web" |
| 6 6 | @source_url "https://github.com/elixir-plug/plug_crypto" |