Actually check signature metadata
This commit is contained in:
parent
e601195042
commit
86bc35c2a7
5 changed files with 348 additions and 188 deletions
|
|
@ -6,5 +6,10 @@ import Config
|
|||
config :http_signatures, adapter: HTTPSignatures.NullAdapter
|
||||
|
||||
if Mix.env() == :test do
|
||||
config :http_signatures, adapter: HTTPSignatures.TestAdapter
|
||||
config :http_signatures,
|
||||
adapter: HTTPSignatures.TestAdapter,
|
||||
# 20 years in seconds; to not just test our own signatures
|
||||
# the test suite contains signatures from other real-world implementations
|
||||
# which we cannot regenerate on the fly with prod-sane creation timestamps
|
||||
max_sig_age: 631_152_000
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ defmodule HTTPSignatures do
|
|||
@key_id "keyId"
|
||||
@request_target "(request-target)"
|
||||
|
||||
@max_clock_skew Application.compile_env(:http_signatures, :max_clock_skew, 2400)
|
||||
@max_sig_age Application.compile_env(:http_signatures, :max_sig_age, 7200)
|
||||
|
||||
defp split_signature(sig) do
|
||||
default = %{"headers" => "date"}
|
||||
|
||||
|
|
@ -183,6 +186,85 @@ defmodule HTTPSignatures do
|
|||
end
|
||||
end
|
||||
|
||||
defp unixstr_to_time(unixstr) do
|
||||
with {seconds, ""} when is_integer(seconds) <- Integer.parse(unixstr),
|
||||
{:ok, time} <- DateTime.from_unix(seconds) do
|
||||
{:ok, time}
|
||||
else
|
||||
_ -> {:error, :invalid_date}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_expiry(now, %{"(expires)" => expires_unix_seconds}) do
|
||||
with {:ok, expires} <- unixstr_to_time(expires_unix_seconds),
|
||||
true <- DateTime.diff(expires, now) > -@max_clock_skew do
|
||||
:ok
|
||||
else
|
||||
false -> {:error, :too_old}
|
||||
{:error, e} -> {:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_expiry(_, _), do: :ok
|
||||
|
||||
defp check_created(now, %{"(created)" => created_unix_seconds}) do
|
||||
with {:ok, created} <- unixstr_to_time(created_unix_seconds),
|
||||
diff <- DateTime.diff(now, created),
|
||||
{_, false} <- {:future, diff < -@max_clock_skew},
|
||||
{_, false} <- {:too_old, diff > @max_sig_age} do
|
||||
:ok
|
||||
else
|
||||
{:future, _} -> {:error, :future_timestamp}
|
||||
{:too_old, _} -> {:error, :too_old}
|
||||
{:error, e} -> {:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_created(_, _), do: :ok
|
||||
|
||||
defp check_date(now, %{"date" => date_str}) do
|
||||
with {_, {:ok, created}} <- {:parse, Timex.parse(date_str, "{RFC1123}")},
|
||||
diff <- DateTime.diff(now, created),
|
||||
{:future, false} <- {:future, diff < -@max_clock_skew},
|
||||
true <- diff < @max_sig_age do
|
||||
:ok
|
||||
else
|
||||
{:parse, _} -> {:error, :invalid_date}
|
||||
{:future, _} -> {:error, :future_timestamp}
|
||||
_ -> {:error, :too_old}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_date(_, _), do: :ok
|
||||
|
||||
defp check_timing(header_defs) do
|
||||
now = DateTime.utc_now()
|
||||
|
||||
with :ok <- check_date(now, header_defs),
|
||||
:ok <- check_created(now, header_defs) do
|
||||
check_expiry(now, header_defs)
|
||||
else
|
||||
# :error -> {:error, :too_old}
|
||||
{:error, e} -> {:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
# Checks whether non-cryptographic parts are valid,
|
||||
# e.g. not expired
|
||||
defp check_contextual_validity(signature, header_defs) do
|
||||
with {_, %{@key_id => kid}} when kid != "" <- {:key_id, signature},
|
||||
{_, :ok} <- {:timing, check_timing(header_defs)} do
|
||||
:ok
|
||||
else
|
||||
{:key_id, sig} ->
|
||||
Logger.debug("Signature is missing a valid key id!")
|
||||
{:error, {:missing_key_id, sig}}
|
||||
|
||||
{:timing, {:error, e}} ->
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Validates the presence and authenticity of an incoming HTTP request
|
||||
|
||||
|
|
@ -196,8 +278,6 @@ defmodule HTTPSignatures do
|
|||
|
||||
Note: results other than {:ok, key} and {:error, _} will only ever be returned
|
||||
if instructed to do so by the key adapter via {:halt, _}.
|
||||
|
||||
XXX: currently the values for (expired) and (created) are not checked against the local system time
|
||||
"""
|
||||
@spec validate_conn(Plug.Conn.t(), [String.t() | (-> String.t() | [String.t()])], any()) ::
|
||||
{:ok, key :: HTTPSignatures.HTTPKey.t()} | {:error, any()} | any()
|
||||
|
|
@ -207,24 +287,25 @@ defmodule HTTPSignatures do
|
|||
headers = Enum.into(conn.req_headers, %{})
|
||||
|
||||
with {_, sigstr} when sigstr != nil <- {:signature, headers["signature"]},
|
||||
{_, %{@key_id => kid} = signature} when kid != "" <- {:key_id, split_signature(sigstr)},
|
||||
{_, {:ok, %{} = pseudo_headers}} <- {:psuedo_headers, collect_pseudo_headers(signature)} do
|
||||
signature <- split_signature(sigstr),
|
||||
{_, {:ok, %{} = pseudo_headers}} <- {:psuedo_headers, collect_pseudo_headers(signature)},
|
||||
header_defs <- Map.merge(headers, pseudo_headers),
|
||||
{_, :ok} <- {:context, check_contextual_validity(signature, header_defs)} do
|
||||
validate_signature_with_request_target_aliases(
|
||||
request_targets,
|
||||
signature,
|
||||
Map.merge(headers, pseudo_headers),
|
||||
header_defs,
|
||||
user_data
|
||||
)
|
||||
else
|
||||
{:signature, _} ->
|
||||
{:error, :unsigned}
|
||||
|
||||
{:key_id, sig} ->
|
||||
Logger.debug("Signature is missing a valid key id!")
|
||||
{:error, {:missing_key_id, sig}}
|
||||
|
||||
{:pseudo_headers, {:error, _} = e} ->
|
||||
e
|
||||
|
||||
{:context, {:error, _} = e} ->
|
||||
e
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
1
mix.exs
1
mix.exs
|
|
@ -28,6 +28,7 @@ defmodule HttpSignatures.MixProject do
|
|||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
{:timex, "~> 3.7"},
|
||||
{:credo, "~> 1.0", only: [:dev, :test], runtime: false},
|
||||
{:ex_doc, "~> 0.19", only: :dev, runtime: false},
|
||||
{:dialyxir, "~> 1.1.0", only: [:dev], runtime: false}
|
||||
|
|
|
|||
13
mix.lock
13
mix.lock
|
|
@ -1,14 +1,27 @@
|
|||
%{
|
||||
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
|
||||
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
|
||||
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
|
||||
"credo": {:hex, :credo, "1.7.11", "d3e805f7ddf6c9c854fd36f089649d7cf6ba74c42bc3795d587814e3c9847102", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "56826b4306843253a66e47ae45e98e7d284ee1f95d53d1612bb483f88a8cf219"},
|
||||
"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.42", "f23d856f41919f17cd06a493923a722d87a2d684f143a1e663c04a2b93100682", [:mix], [], "hexpm", "6915b6ca369b5f7346636a2f41c6a6d78b5af419d61a611079189233358b8b8b"},
|
||||
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.36.1", "4197d034f93e0b89ec79fac56e226107824adcce8d2dd0a26f5ed3a95efc36b1", [:mix], [{:earmark_parser, "~> 1.4.42", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "d7d26a7cf965dacadcd48f9fa7b5953d7d0cfa3b44fa7a65514427da44eafd89"},
|
||||
"expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"},
|
||||
"file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"},
|
||||
"gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"},
|
||||
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.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.4.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", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
|
||||
"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.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
||||
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
|
||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.4.1", "f41275a0354c736db4b1d255b5d2a27c91028e55c21ea3145b938e22649ffa3f", [:mix], [], "hexpm", "605e44204998f138d6e13be366c8e81af860e726c8177caf50067e1b618fe522"},
|
||||
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
|
||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
|
||||
"timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"},
|
||||
"tzdata": {:hex, :tzdata, "1.1.2", "45e5f1fcf8729525ec27c65e163be5b3d247ab1702581a94674e008413eef50b", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "cec7b286e608371602318c414f344941d5eb0375e14cfdab605cca2fe66cba8b"},
|
||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ defmodule HttpSignaturesTest do
|
|||
"expires" => "1388967500"
|
||||
}
|
||||
|
||||
# since the lib (currently) doesn't handle digest verification or generation,
|
||||
# anything works and we only need to distinguish bodyless from body requests
|
||||
@stub_body %{"type" => "Note", "content" => "Hi!"}
|
||||
|
||||
@default_signature """
|
||||
keyId="Test",algorithm="rsa-sha256",signature="jKyvPcxB4JbmYY4mByyBY7cZfNl4OW9HpFQlG7N4YcJPteKTu4MWCLyk+gIr0wDgqtLWf9NLpMAMimdfsH7FSWGfbMFSrsVTHNTk0rK3usrfFnti1dxsM4jl0kYJCKTGI/UWkqiaxwNiKqGcdlEDrTcUhhsFsOIo8VhddmZTZ8w="
|
||||
"""
|
||||
|
|
@ -45,13 +49,14 @@ defmodule HttpSignaturesTest do
|
|||
keyId="Test",algorithm="rsa-sha256",headers="(request-target) host date content-type digest content-length",signature="Ef7MlxLXoBovhil3AlyjtBwAL9g4TN3tibLj7uuNB3CROat/9KaeQ4hW2NiJ+pZ6HQEOx9vYZAyi+7cmIkmJszJCut5kQLAwuX+Ms/mUFvpKlSo9StS2bMXDBNjOh4Auj774GFj4gwjS+3NhFeoqyr/MuN6HsEnkvn6zdgfE2i0="
|
||||
"""
|
||||
|
||||
defp signed_conn(signature), do: %{req_headers: [{"signature", signature} | @headers]}
|
||||
defp signed_conn(signature, headers, body_params \\ @stub_body),
|
||||
do: %{
|
||||
req_headers: [{"signature", signature} | headers],
|
||||
body_params: body_params
|
||||
}
|
||||
|
||||
defp assert_signature(signature, request_targets \\ [@pseudo_headers["request-target"]]) do
|
||||
assert match?(
|
||||
{:ok, %HTTPKey{user_data: %{"key_id" => @key_id}}},
|
||||
HTTPSignatures.validate_conn(signed_conn(signature), request_targets)
|
||||
)
|
||||
defp check_signature(signature, request_targets \\ [@pseudo_headers["request-target"]]) do
|
||||
HTTPSignatures.validate_conn(signed_conn(signature, @headers, %{}), request_targets)
|
||||
end
|
||||
|
||||
defp assert_conn(conn, request_targets, key_id) do
|
||||
|
|
@ -61,55 +66,64 @@ defmodule HttpSignaturesTest do
|
|||
)
|
||||
end
|
||||
|
||||
test "validates the default case" do
|
||||
assert_signature(@default_signature, [nil])
|
||||
test "accepts the default case" do
|
||||
assert match?(
|
||||
{:ok, %HTTPKey{user_data: %{"key_id" => @key_id}}},
|
||||
check_signature(@default_signature, [nil])
|
||||
)
|
||||
end
|
||||
|
||||
test "validates the basic case" do
|
||||
assert_signature(@basic_signature)
|
||||
test "accepts signature without digest if body-less" do
|
||||
assert match?(
|
||||
{:ok, %HTTPKey{user_data: %{"key_id" => @key_id}}},
|
||||
check_signature(@basic_signature)
|
||||
)
|
||||
end
|
||||
|
||||
test "validates the timestamped case" do
|
||||
assert_signature(@timestamped_signature)
|
||||
test "rejects signature if expired" do
|
||||
assert {:error, :too_old} == check_signature(@timestamped_signature)
|
||||
end
|
||||
|
||||
test "validates the all-headers case" do
|
||||
assert_signature(@all_headers_signature)
|
||||
assert match?(
|
||||
{:ok, %HTTPKey{user_data: %{"key_id" => @key_id}}},
|
||||
check_signature(@all_headers_signature)
|
||||
)
|
||||
end
|
||||
|
||||
test "it validates a conn" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"host", "localtesting.pleroma.lol"},
|
||||
{"connection", "close"},
|
||||
{"content-length", "2316"},
|
||||
{"user-agent", "http.rb/2.2.2 (Mastodon/2.1.0.rc3; +http://mastodon.example.org/)"},
|
||||
{"date", "Sun, 10 Dec 2017 14:23:49 GMT"},
|
||||
{"digest", "SHA-256=x/bHADMW8qRrq2NdPb5P9fl0lYpKXXpe5h5maCIL0nM="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"signature",
|
||||
"keyId=\"http://example.org/mystery/key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"i0FQvr51sj9BoWAKydySUAO1RDxZmNY6g7M62IA7VesbRSdFZZj9/fZapLp6YSuvxUF0h80ZcBEq9GzUDY3Chi9lx6yjpUAS2eKb+Am/hY3aswhnAfYd6FmIdEHzsMrpdKIRqO+rpQ2tR05LwiGEHJPGS0p528NvyVxrxMT5H5yZS5RnxY5X2HmTKEgKYYcvujdv7JWvsfH88xeRS7Jlq5aDZkmXvqoR4wFyfgnwJMPLel8P/BUbn8BcXglH/cunR0LUP7sflTxEz+Rv5qg+9yB8zgBsB4C0233WpcJxjeD6Dkq0EcoJObBR56F8dcb7NQtUDu7x6xxzcgSd7dHm5w==\""}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"http://example.org/mystery/key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"i0FQvr51sj9BoWAKydySUAO1RDxZmNY6g7M62IA7VesbRSdFZZj9/fZapLp6YSuvxUF0h80ZcBEq9GzUDY3Chi9lx6yjpUAS2eKb+Am/hY3aswhnAfYd6FmIdEHzsMrpdKIRqO+rpQ2tR05LwiGEHJPGS0p528NvyVxrxMT5H5yZS5RnxY5X2HmTKEgKYYcvujdv7JWvsfH88xeRS7Jlq5aDZkmXvqoR4wFyfgnwJMPLel8P/BUbn8BcXglH/cunR0LUP7sflTxEz+Rv5qg+9yB8zgBsB4C0233WpcJxjeD6Dkq0EcoJObBR56F8dcb7NQtUDu7x6xxzcgSd7dHm5w==\"",
|
||||
[
|
||||
{"host", "localtesting.pleroma.lol"},
|
||||
{"connection", "close"},
|
||||
{"content-length", "2316"},
|
||||
{"user-agent", "http.rb/2.2.2 (Mastodon/2.1.0.rc3; +http://mastodon.example.org/)"},
|
||||
{"date", "Sun, 10 Dec 2017 14:23:49 GMT"},
|
||||
{"digest", "SHA-256=x/bHADMW8qRrq2NdPb5P9fl0lYpKXXpe5h5maCIL0nM="},
|
||||
{"content-type", "application/activity+json"}
|
||||
]
|
||||
)
|
||||
|
||||
assert_conn(conn, ["post /users/demiurge/inbox"], "http://example.org/mystery/key")
|
||||
end
|
||||
|
||||
test "it validates a conn and fetches the key" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"host", "localtesting.pleroma.lol"},
|
||||
{"x-forwarded-for", "127.0.0.1"},
|
||||
{"connection", "close"},
|
||||
{"content-length", "2307"},
|
||||
{"user-agent", "http.rb/2.2.2 (Mastodon/2.1.0.rc3; +http://mastodon.example.org/)"},
|
||||
{"date", "Sun, 11 Feb 2018 17:12:01 GMT"},
|
||||
{"digest", "SHA-256=UXsAnMtR9c7mi1FOf6HRMtPgGI1yi2e9nqB/j4rZ99I="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"signature",
|
||||
"keyId=\"http://mastodon.example.org/users/admin#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"qXKqpQXUpC3d9bZi2ioEeAqP8nRMD021CzH1h6/w+LRk4Hj31ARJHDwQM+QwHltwaLDUepshMfz2WHSXAoLmzWtvv7xRwY+mRqe+NGk1GhxVZ/LSrO/Vp7rYfDpfdVtkn36LU7/Bzwxvvaa4ZWYltbFsRBL0oUrqsfmJFswNCQIG01BB52BAhGSCORHKtQyzo1IZHdxl8y80pzp/+FOK2SmHkqWkP9QbaU1qTZzckL01+7M5btMW48xs9zurEqC2sM5gdWMQSZyL6isTV5tmkTZrY8gUFPBJQZgihK44v3qgfWojYaOwM8ATpiv7NG8wKN/IX7clDLRMA8xqKRCOKw==\""}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"http://mastodon.example.org/users/admin#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"qXKqpQXUpC3d9bZi2ioEeAqP8nRMD021CzH1h6/w+LRk4Hj31ARJHDwQM+QwHltwaLDUepshMfz2WHSXAoLmzWtvv7xRwY+mRqe+NGk1GhxVZ/LSrO/Vp7rYfDpfdVtkn36LU7/Bzwxvvaa4ZWYltbFsRBL0oUrqsfmJFswNCQIG01BB52BAhGSCORHKtQyzo1IZHdxl8y80pzp/+FOK2SmHkqWkP9QbaU1qTZzckL01+7M5btMW48xs9zurEqC2sM5gdWMQSZyL6isTV5tmkTZrY8gUFPBJQZgihK44v3qgfWojYaOwM8ATpiv7NG8wKN/IX7clDLRMA8xqKRCOKw==\"",
|
||||
[
|
||||
{"host", "localtesting.pleroma.lol"},
|
||||
{"x-forwarded-for", "127.0.0.1"},
|
||||
{"connection", "close"},
|
||||
{"content-length", "2307"},
|
||||
{"user-agent", "http.rb/2.2.2 (Mastodon/2.1.0.rc3; +http://mastodon.example.org/)"},
|
||||
{"date", "Sun, 11 Feb 2018 17:12:01 GMT"},
|
||||
{"digest", "SHA-256=UXsAnMtR9c7mi1FOf6HRMtPgGI1yi2e9nqB/j4rZ99I="},
|
||||
{"content-type", "application/activity+json"}
|
||||
]
|
||||
)
|
||||
|
||||
assert_conn(
|
||||
conn,
|
||||
|
|
@ -119,58 +133,58 @@ defmodule HttpSignaturesTest do
|
|||
end
|
||||
|
||||
test "validate this" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"x-forwarded-for", "149.202.73.191"},
|
||||
{"host", "testing.pleroma.lol"},
|
||||
{"x-cluster-client-ip", "149.202.73.191"},
|
||||
{"connection", "upgrade"},
|
||||
{"content-length", "2396"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://niu.moe/)"},
|
||||
{"date", "Sun, 18 Feb 2018 20:31:51 GMT"},
|
||||
{"digest", "SHA-256=dzH+vLyhxxALoe9RJdMl4hbEV9bGAZnSfddHQzeidTU="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"signature",
|
||||
"keyId=\"https://niu.moe/users/rye#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"wtxDg4kIpW7nsnUcVJhBk6SgJeDZOocr8yjsnpDRqE52lR47SH6X7G16r7L1AUJdlnbfx7oqcvomoIJoHB3ghP6kRnZW6MyTMZ2jPoi3g0iC5RDqv6oAmDSO14iw6U+cqZbb3P/odS5LkbThF0UNXcfenVNfsKosIJycFjhNQc54IPCDXYq/7SArEKJp8XwEgzmiC2MdxlkVIUSTQYfjM4EG533cwlZocw1mw72e5mm/owTa80BUZAr0OOuhoWARJV9btMb02ZyAF6SCSoGPTA37wHyfM1Dk88NHf7Z0Aov/Fl65dpRM+XyoxdkpkrhDfH9qAx4iuV2VEWddQDiXHA==\""}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"https://niu.moe/users/rye#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"wtxDg4kIpW7nsnUcVJhBk6SgJeDZOocr8yjsnpDRqE52lR47SH6X7G16r7L1AUJdlnbfx7oqcvomoIJoHB3ghP6kRnZW6MyTMZ2jPoi3g0iC5RDqv6oAmDSO14iw6U+cqZbb3P/odS5LkbThF0UNXcfenVNfsKosIJycFjhNQc54IPCDXYq/7SArEKJp8XwEgzmiC2MdxlkVIUSTQYfjM4EG533cwlZocw1mw72e5mm/owTa80BUZAr0OOuhoWARJV9btMb02ZyAF6SCSoGPTA37wHyfM1Dk88NHf7Z0Aov/Fl65dpRM+XyoxdkpkrhDfH9qAx4iuV2VEWddQDiXHA==\"",
|
||||
[
|
||||
{"x-forwarded-for", "149.202.73.191"},
|
||||
{"host", "testing.pleroma.lol"},
|
||||
{"x-cluster-client-ip", "149.202.73.191"},
|
||||
{"connection", "upgrade"},
|
||||
{"content-length", "2396"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://niu.moe/)"},
|
||||
{"date", "Sun, 18 Feb 2018 20:31:51 GMT"},
|
||||
{"digest", "SHA-256=dzH+vLyhxxALoe9RJdMl4hbEV9bGAZnSfddHQzeidTU="},
|
||||
{"content-type", "application/activity+json"}
|
||||
]
|
||||
)
|
||||
|
||||
assert_conn(conn, ["post /inbox"], "https://niu.moe/users/rye#main-key")
|
||||
end
|
||||
|
||||
test "validate this too" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"x-forwarded-for", "149.202.73.191"},
|
||||
{"host", "testing.pleroma.lol"},
|
||||
{"x-cluster-client-ip", "149.202.73.191"},
|
||||
{"connection", "upgrade"},
|
||||
{"content-length", "2342"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://niu.moe/)"},
|
||||
{"date", "Sun, 18 Feb 2018 21:44:46 GMT"},
|
||||
{"digest", "SHA-256=vS8uDOJlyAu78cF3k5EzrvaU9iilHCX3chP37gs5sS8="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"signature",
|
||||
"keyId=\"https://niu.moe/users/rye#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"IN6fHD8pLiDEf35dOaRHzJKc1wBYh3/Yq0ItaNGxUSbJTd2xMjigZbcsVKzvgYYjglDDN+disGNeD+OBKwMqkXWaWe/lyMc9wHvCH5NMhpn/A7qGLY8yToSt4vh8ytSkZKO6B97yC+Nvy6Fz/yMbvKtFycIvSXCq417cMmY6f/aG+rtMUlTbKO5gXzC7SUgGJCtBPCh1xZzu5/w0pdqdjO46ePNeR6JyJSLLV4hfo3+p2n7SRraxM4ePVCUZqhwS9LPt3Zdhy3ut+IXCZgMVIZggQFM+zXLtcXY5HgFCsFQr5WQDu+YkhWciNWtKFnWfAsnsg5sC330lZ/0Z8Z91yA==\""}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"https://niu.moe/users/rye#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"IN6fHD8pLiDEf35dOaRHzJKc1wBYh3/Yq0ItaNGxUSbJTd2xMjigZbcsVKzvgYYjglDDN+disGNeD+OBKwMqkXWaWe/lyMc9wHvCH5NMhpn/A7qGLY8yToSt4vh8ytSkZKO6B97yC+Nvy6Fz/yMbvKtFycIvSXCq417cMmY6f/aG+rtMUlTbKO5gXzC7SUgGJCtBPCh1xZzu5/w0pdqdjO46ePNeR6JyJSLLV4hfo3+p2n7SRraxM4ePVCUZqhwS9LPt3Zdhy3ut+IXCZgMVIZggQFM+zXLtcXY5HgFCsFQr5WQDu+YkhWciNWtKFnWfAsnsg5sC330lZ/0Z8Z91yA==\"",
|
||||
[
|
||||
{"x-forwarded-for", "149.202.73.191"},
|
||||
{"host", "testing.pleroma.lol"},
|
||||
{"x-cluster-client-ip", "149.202.73.191"},
|
||||
{"connection", "upgrade"},
|
||||
{"content-length", "2342"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://niu.moe/)"},
|
||||
{"date", "Sun, 18 Feb 2018 21:44:46 GMT"},
|
||||
{"digest", "SHA-256=vS8uDOJlyAu78cF3k5EzrvaU9iilHCX3chP37gs5sS8="},
|
||||
{"content-type", "application/activity+json"}
|
||||
]
|
||||
)
|
||||
|
||||
assert_conn(conn, ["post /inbox"], "https://niu.moe/users/rye#main-key")
|
||||
end
|
||||
|
||||
test "it validates a bridgy signature" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"user-agent", "Bridgy Fed (https://fed.brid.gy/)"},
|
||||
{"date", "Mon, 15 Jul 2024 04:35:16 GMT"},
|
||||
{"host", "akko.wtf"},
|
||||
{"content-type",
|
||||
"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""},
|
||||
{"digest", "SHA-256=aD6VWn+4CUs5hBeEjAiSdRjga/h5Qnub0gLVSqSosSk="},
|
||||
{"signature",
|
||||
~s|keyId="https://fed.brid.gy/snarfed.org#key",algorithm="rsa-sha256",signature="pezDShRpsN8sErE5xOPWh4iJOzi2nz7IcwxtCYEQ3KfqezkQIGFb9lxCwgUZDUdueX6R/eUXGJ5S5GdzjEMbs90iIzaqvN2fRmhs3VHgd7Y1O8bMJGfkOz5i6JllyPMgfFT9937147ATmGTmo7h4NhE5XgQ6VwNijNuBhLGOZsCLYqldpuyGuHXyLOmGHsIL/tBf0LBKPMyE6S70hEmh6Zx7nQeW5Kt9CTZIxnSbeFrg2HMiMaFRM5gWtPTH5N6Jr6SGal/vXT9VrN1wjwZI83y45aHmpnU7VImSWGWyXxcveHvspXtDciWAPNU8ng6aglYVgWrLaQz70ApRb10fXg==",headers="date host digest (request-target)"|}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
~s|keyId="https://fed.brid.gy/snarfed.org#key",algorithm="rsa-sha256",signature="pezDShRpsN8sErE5xOPWh4iJOzi2nz7IcwxtCYEQ3KfqezkQIGFb9lxCwgUZDUdueX6R/eUXGJ5S5GdzjEMbs90iIzaqvN2fRmhs3VHgd7Y1O8bMJGfkOz5i6JllyPMgfFT9937147ATmGTmo7h4NhE5XgQ6VwNijNuBhLGOZsCLYqldpuyGuHXyLOmGHsIL/tBf0LBKPMyE6S70hEmh6Zx7nQeW5Kt9CTZIxnSbeFrg2HMiMaFRM5gWtPTH5N6Jr6SGal/vXT9VrN1wjwZI83y45aHmpnU7VImSWGWyXxcveHvspXtDciWAPNU8ng6aglYVgWrLaQz70ApRb10fXg==",headers="date host digest (request-target)"|,
|
||||
[
|
||||
{"user-agent", "Bridgy Fed (https://fed.brid.gy/)"},
|
||||
{"date", "Mon, 15 Jul 2024 04:35:16 GMT"},
|
||||
{"host", "akko.wtf"},
|
||||
{"content-type",
|
||||
"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""},
|
||||
{"digest", "SHA-256=aD6VWn+4CUs5hBeEjAiSdRjga/h5Qnub0gLVSqSosSk="}
|
||||
]
|
||||
)
|
||||
|
||||
assert_conn(conn, ["post /users/Oneric/inbox"], "https://fed.brid.gy/snarfed.org#key")
|
||||
end
|
||||
|
|
@ -181,28 +195,31 @@ defmodule HttpSignaturesTest do
|
|||
"http://mastodon.example.org/users/admin#main-key",
|
||||
%{
|
||||
:host => "mastodon.example.org",
|
||||
"(request-target)" => "post http.//example.com/inbox"
|
||||
"(request-target)" => "post http://example.com/inbox",
|
||||
"(created)" => "#{DateTime.utc_now() |> DateTime.to_unix()}",
|
||||
"digest" =>
|
||||
"SHA256-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
}
|
||||
) =~ "keyId=\""
|
||||
end
|
||||
|
||||
test "this too" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://mst3k.interlinked.me/)"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"signature",
|
||||
"keyId=\"https://mst3k.interlinked.me/users/luciferMysticus#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\""},
|
||||
{"x-forwarded-for", "2607:5300:203:2899::31:1337"},
|
||||
{"x-forwarded-host", "soc.canned-death.us"},
|
||||
{"x-forwarded-server", "soc.canned-death.us"},
|
||||
{"connection", "Keep-Alive"},
|
||||
{"content-length", "2006"}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"https://mst3k.interlinked.me/users/luciferMysticus#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\"",
|
||||
[
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://mst3k.interlinked.me/)"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"x-forwarded-for", "2607:5300:203:2899::31:1337"},
|
||||
{"x-forwarded-host", "soc.canned-death.us"},
|
||||
{"x-forwarded-server", "soc.canned-death.us"},
|
||||
{"connection", "Keep-Alive"},
|
||||
{"content-length", "2006"}
|
||||
]
|
||||
)
|
||||
|
||||
assert_conn(
|
||||
conn,
|
||||
|
|
@ -212,22 +229,22 @@ defmodule HttpSignaturesTest do
|
|||
end
|
||||
|
||||
test "works with request_aliases" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://mst3k.interlinked.me/)"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"signature",
|
||||
"keyId=\"https://mst3k.interlinked.me/users/luciferMysticus#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\""},
|
||||
{"x-forwarded-for", "2607:5300:203:2899::31:1337"},
|
||||
{"x-forwarded-host", "soc.canned-death.us"},
|
||||
{"x-forwarded-server", "soc.canned-death.us"},
|
||||
{"connection", "Keep-Alive"},
|
||||
{"content-length", "2006"}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"https://mst3k.interlinked.me/users/luciferMysticus#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\"",
|
||||
[
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://mst3k.interlinked.me/)"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"x-forwarded-for", "2607:5300:203:2899::31:1337"},
|
||||
{"x-forwarded-host", "soc.canned-death.us"},
|
||||
{"x-forwarded-server", "soc.canned-death.us"},
|
||||
{"connection", "Keep-Alive"},
|
||||
{"content-length", "2006"}
|
||||
]
|
||||
)
|
||||
|
||||
assert_conn(
|
||||
conn,
|
||||
|
|
@ -237,22 +254,22 @@ defmodule HttpSignaturesTest do
|
|||
end
|
||||
|
||||
test "works with lazy-eval request_aliases" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://mst3k.interlinked.me/)"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"signature",
|
||||
"keyId=\"https://mst3k.interlinked.me/users/luciferMysticus#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\""},
|
||||
{"x-forwarded-for", "2607:5300:203:2899::31:1337"},
|
||||
{"x-forwarded-host", "soc.canned-death.us"},
|
||||
{"x-forwarded-server", "soc.canned-death.us"},
|
||||
{"connection", "Keep-Alive"},
|
||||
{"content-length", "2006"}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"https://mst3k.interlinked.me/users/luciferMysticus#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\"",
|
||||
[
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://mst3k.interlinked.me/)"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"x-forwarded-for", "2607:5300:203:2899::31:1337"},
|
||||
{"x-forwarded-host", "soc.canned-death.us"},
|
||||
{"x-forwarded-server", "soc.canned-death.us"},
|
||||
{"connection", "Keep-Alive"},
|
||||
{"content-length", "2006"}
|
||||
]
|
||||
)
|
||||
|
||||
assert_conn(
|
||||
conn,
|
||||
|
|
@ -262,22 +279,22 @@ defmodule HttpSignaturesTest do
|
|||
end
|
||||
|
||||
test "works with lazy-eval batch request_aliases" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://mst3k.interlinked.me/)"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"signature",
|
||||
"keyId=\"https://mst3k.interlinked.me/users/luciferMysticus#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\""},
|
||||
{"x-forwarded-for", "2607:5300:203:2899::31:1337"},
|
||||
{"x-forwarded-host", "soc.canned-death.us"},
|
||||
{"x-forwarded-server", "soc.canned-death.us"},
|
||||
{"connection", "Keep-Alive"},
|
||||
{"content-length", "2006"}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"https://mst3k.interlinked.me/users/luciferMysticus#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\"",
|
||||
[
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"user-agent", "http.rb/3.0.0 (Mastodon/2.2.0; +https://mst3k.interlinked.me/)"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"x-forwarded-for", "2607:5300:203:2899::31:1337"},
|
||||
{"x-forwarded-host", "soc.canned-death.us"},
|
||||
{"x-forwarded-server", "soc.canned-death.us"},
|
||||
{"connection", "Keep-Alive"},
|
||||
{"content-length", "2006"}
|
||||
]
|
||||
)
|
||||
|
||||
assert_conn(
|
||||
conn,
|
||||
|
|
@ -287,46 +304,84 @@ defmodule HttpSignaturesTest do
|
|||
end
|
||||
|
||||
test "returns a custom result from adapter on key fetch" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"signature",
|
||||
"keyId=\"halt_id\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest
|
||||
content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\""}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"halt_id\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\"",
|
||||
[
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"}
|
||||
]
|
||||
)
|
||||
|
||||
assert HTTPSignatures.validate_conn(conn, ["post /inbox"]) == :custom_res
|
||||
end
|
||||
|
||||
test "returns a custom result from adapter on key refetch" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"},
|
||||
{"signature",
|
||||
"keyId=\"halt_refetch_id\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\""}
|
||||
]
|
||||
}
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"halt_refetch_id\",algorithm=\"rsa-sha256\",headers=\"(request-target) user-agent host date digest content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\"",
|
||||
[
|
||||
{"host", "soc.canned-death.us"},
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"content-type", "application/activity+json"}
|
||||
]
|
||||
)
|
||||
|
||||
assert HTTPSignatures.validate_conn(conn, ["post /inbox"]) == :custom_res2
|
||||
end
|
||||
|
||||
test "returns an error on unknown key" do
|
||||
conn = %{
|
||||
req_headers: [
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="},
|
||||
{"signature",
|
||||
"keyId=\"unknown_id\",algorithm=\"rsa-sha256\",headers=\"(request-target) date digest\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\""}
|
||||
]
|
||||
test "accepts its own signature" do
|
||||
request_target = "post http://example.com/inbox"
|
||||
|
||||
conn_headers = %{
|
||||
"digest" => "SHA256-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"host" => "example.com"
|
||||
}
|
||||
|
||||
signature =
|
||||
HTTPSignatures.sign(
|
||||
%HTTPKey{key: @private_key},
|
||||
"Test",
|
||||
%{
|
||||
"(request-target)" => request_target,
|
||||
"(created)" => DateTime.utc_now() |> DateTime.to_unix(),
|
||||
:host => conn_headers["host"],
|
||||
"digest" => conn_headers["digest"]
|
||||
}
|
||||
)
|
||||
|
||||
conn = signed_conn(signature, Enum.into(conn_headers, []))
|
||||
|
||||
assert match?({:ok, _}, HTTPSignatures.validate_conn(conn, [request_target]))
|
||||
end
|
||||
|
||||
test "rejects too old signatures" do
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"Test\",algorithm=\"rsa-sha256\",headers=\"(request-target) date digest\",signature=\"fTmDCQYXsib05+Np0R3jQhG5KYu8v8chjiZnpZxKMnTPLJ6C/XDeqTIAvBtikuIrSWNG0k3/xSMXR3c1IVw/T5lwo9KAjsZU39ztYGBckE8X9BdT1GklpyWDtI4X9MvBrq5lmMn/r1gbQFzelQEF1+RdK6kbDwg8goAYGEkm9KE=\"",
|
||||
[
|
||||
{"date", "Wed, 09 Feb 2000 00:00:00 GMT"},
|
||||
{"digest", "SHA256-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}
|
||||
]
|
||||
)
|
||||
|
||||
assert {:error, :too_old} ==
|
||||
HTTPSignatures.validate_conn(conn, ["post http://example.com/inbox"])
|
||||
end
|
||||
|
||||
test "returns an error on unknown key" do
|
||||
conn =
|
||||
signed_conn(
|
||||
"keyId=\"unknown_id\",algorithm=\"rsa-sha256\",headers=\"(request-target) date digest\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15pCpAyx8IZp53s0Fn/y8MjCTzp+absw8kxx0k2sQAXYs2iy6xhdDUe7iGzz+XLAEqLyZIZfecynaU2nb3Z2XnFDjhGjR1vj/JP7wiXpwp6o1dpDZj+KT2vxHtXuB9585V+sOHLwSB1cGDbAgTy0jx/2az2EGIKK2zkw1KJuAZm0DDMSZalp/30P8dl3qz7DV2EHdDNfaVtrs5BfbDOZ7t1hCcASllzAzgVGFl0BsrkzBfRMeUMRucr111ZG+c0BNOEtJYOHSyZsSSdNknElggCJekONYMYk5ZA==\"",
|
||||
[
|
||||
{"date", "Sun, 11 Mar 2018 12:19:36 GMT"},
|
||||
{"digest", "SHA-256=V7Hl6qDK2m8WzNsjzNYSBISi9VoIXLFlyjF/a5o1SOc="}
|
||||
]
|
||||
)
|
||||
|
||||
assert match?(
|
||||
{:error, {:fetch_key, _}},
|
||||
HTTPSignatures.validate_conn(conn, ["post /inbox"])
|
||||
|
|
@ -351,10 +406,15 @@ content-type\",signature=\"CTYdK5a6lYMxzmqjLOpvRRASoxo2Rqib2VrAvbR5HaTn80kiImj15
|
|||
|
||||
private_key = %HTTPKey{key: private_key}
|
||||
|
||||
headers = %{host: "test.test", "content-length": 100}
|
||||
headers = %{
|
||||
"host" => "test.test",
|
||||
"content-length" => "0",
|
||||
"date" => "Sat, 01 Feb 2025 00:00:00 GMT",
|
||||
"(request-target)" => "get https://example.com/object/123"
|
||||
}
|
||||
|
||||
expected_signature =
|
||||
~s|keyId="https://mastodon.social/users/lambadalambda#main-key",algorithm="rsa-sha256",headers="content-length host",signature="sibUOoqsFfTDerquAkyprxzDjmJm6erYc42W5w1IyyxusWngSinq5ILTjaBxFvfarvc7ci1xAi+5gkBwtshRMWm7S+Uqix24Yg5EYafXRun9P25XVnYBEIH4XQ+wlnnzNIXQkU3PU9e6D8aajDZVp3hPJNeYt1gIPOA81bROI8/glzb1SAwQVGRbqUHHHKcwR8keiR/W2h7BwG3pVRy4JgnIZRSW7fQogKedDg02gzRXwUDFDk0pr2p3q6bUWHUXNV8cZIzlMK+v9NlyFbVYBTHctAR26GIAN6Hz0eV0mAQAePHDY1mXppbA8Gpp6hqaMuYfwifcXmcc+QFm4e+n3A=="|
|
||||
~s|keyId="https://mastodon.social/users/lambadalambda#main-key",algorithm="rsa-sha256",headers="(request-target) content-length date host",signature="b3ORqxn55+DOz4LljaugGfV3lOnozvW1fO54N6RE1Zr9o4wdaVmV/8CsaN3FCMKDf2rWbr6qWDyC0s6zbhwBGQOZc2SdchFxc4OFGZtEILNqCC4EYQkJ85xwR7DkVxDCZNBJRc6HKuAGOd4TavmWgoUaiyj+6aOho7X/lAFhhx6rNDZtOI7/3D/j/6t5d3vz90dyhiYSg0jPg+rLnFq99oZ+LUVBAHFVFBumZSoZeF6AoxnHtoeG98Qf0ICYPfdCfOIfbMjw6xQt2ciichcagDcsZS6sO3/wBAznloQIg/pO4BhV1G2Gnp/SVjL9CsaXndXGW8ABbQIDELI+IOQjSg=="|
|
||||
|
||||
signature = HTTPSignatures.sign(private_key, user_ap_id, headers)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue