diff --git a/lib/stripe/webhook.ex b/lib/stripe/webhook.ex index c5b61f58..024a6a74 100644 --- a/lib/stripe/webhook.ex +++ b/lib/stripe/webhook.ex @@ -116,10 +116,17 @@ defmodule Stripe.Webhook do end defp compute_signature(payload, secret) do - :crypto.hmac(:sha256, secret, payload) + hmac(:sha256, secret, payload) |> Base.encode16(case: :lower) end + # TODO: remove when we require OTP 22 + if System.otp_release() >= "22" do + defp hmac(digest, key, data), do: :crypto.mac(:hmac, digest, key, data) + else + defp hmac(digest, key, data), do: :crypto.hmac(digest, key, data) + end + defp secure_equals?(input, expected) when byte_size(input) == byte_size(expected) do input = String.to_charlist(input) expected = String.to_charlist(expected) @@ -135,7 +142,7 @@ defmodule Stripe.Webhook do import Bitwise acc - |> bor(input_codepoint ^^^ expected_codepoint) + |> bor(bxor(input_codepoint, expected_codepoint)) |> secure_compare(input, expected) end diff --git a/test/stripe/webhook_test.exs b/test/stripe/webhook_test.exs index b4c66c5b..53051458 100644 --- a/test/stripe/webhook_test.exs +++ b/test/stripe/webhook_test.exs @@ -11,10 +11,17 @@ defmodule Stripe.WebhookTest do @secret "secret" defp generate_signature(timestamp, payload, secret \\ @secret) do - :crypto.hmac(:sha256, secret, "#{timestamp}.#{payload}") + hmac(:sha256, secret, "#{timestamp}.#{payload}") |> Base.encode16(case: :lower) end + # TODO: remove when we require OTP 22 + if System.otp_release() >= "22" do + defp hmac(digest, key, data), do: :crypto.mac(:hmac, digest, key, data) + else + defp hmac(digest, key, data), do: :crypto.hmac(digest, key, data) + end + defp create_signature_header(timestamp, scheme, signature) do "t=#{timestamp},#{scheme}=#{signature}" end