Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F140817
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
4 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/http_signatures/http_signatures.ex b/lib/http_signatures/http_signatures.ex
index 25bc9f1..018ee2e 100644
--- a/lib/http_signatures/http_signatures.ex
+++ b/lib/http_signatures/http_signatures.ex
@@ -1,81 +1,85 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: LGPL-3.0-only
# https://tools.ietf.org/html/draft-cavage-http-signatures-08
defmodule HTTPSignatures do
+ @moduledoc """
+ HTTP Signatures library.
+ """
+
require Logger
def split_signature(sig) do
default = %{"headers" => "date"}
sig =
sig
|> String.trim()
|> String.split(",")
|> Enum.reduce(default, fn part, acc ->
[key | rest] = String.split(part, "=")
value = Enum.join(rest, "=")
Map.put(acc, key, String.trim(value, "\""))
end)
Map.put(sig, "headers", String.split(sig["headers"], ~r/\s/))
end
def validate(headers, signature, public_key) do
sigstring = build_signing_string(headers, signature["headers"])
Logger.debug("Signature: #{signature["signature"]}")
Logger.debug("Sigstring: #{sigstring}")
{:ok, sig} = Base.decode64(signature["signature"])
:public_key.verify(sigstring, :sha256, sig, public_key)
end
def validate_conn(conn) do
adapter = Application.get_env(:http_signatures, :adapter)
with {:ok, public_key} <- adapter.fetch_public_key(conn) do
if validate_conn(conn, public_key) do
true
else
Logger.debug("Could not validate, trying to refetch any relevant keys")
with {:ok, public_key} <- adapter.refetch_public_key(conn) do
validate_conn(conn, public_key)
end
end
else
e ->
Logger.debug("Could not validate against known public keys: #{inspect(e)}")
false
end
end
def validate_conn(conn, public_key) do
headers = Enum.into(conn.req_headers, %{})
signature = split_signature(headers["signature"])
validate(headers, signature, public_key)
end
def build_signing_string(headers, used_headers) do
used_headers
|> Enum.map(fn header -> "#{header}: #{headers[header]}" end)
|> Enum.join("\n")
end
def sign(private_key, key_id, headers) do
sigstring = build_signing_string(headers, Map.keys(headers))
signature =
:public_key.sign(sigstring, :sha256, private_key)
|> Base.encode64()
[
keyId: key_id,
algorithm: "rsa-sha256",
headers: Map.keys(headers) |> Enum.join(" "),
signature: signature
]
|> Enum.map(fn {k, v} -> "#{k}=\"#{v}\"" end)
|> Enum.join(",")
end
end
diff --git a/test/support/test_adapter.ex b/test/support/test_adapter.ex
index 01e173f..58b9b4b 100644
--- a/test/support/test_adapter.ex
+++ b/test/support/test_adapter.ex
@@ -1,34 +1,36 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: LGPL-3.0-only
defmodule HTTPSignatures.TestAdapter do
@behaviour HTTPSignatures.Adapter
+ @moduledoc "Test adapter for HTTPSignatures library."
+
@mastodon_admin_pubkey hd(
:public_key.pem_decode(
File.read!("test/admin@mastodon.example.org.key")
)
)
|> :public_key.pem_entry_decode()
@rye_pubkey hd(:public_key.pem_decode(File.read!("test/rye@niu.moe.key")))
|> :public_key.pem_entry_decode()
@lm_pubkey hd(
:public_key.pem_decode(File.read!("test/lucifermysticus@mst3k.interlinked.me.key"))
)
|> :public_key.pem_entry_decode()
def fetch_public_key(_), do: {:ok, @mastodon_admin_pubkey}
def refetch_public_key(%{params: %{"actor" => "https://niu.moe/users/rye"}}),
do: {:ok, @rye_pubkey}
def refetch_public_key(%{
params: %{"actor" => "https://mst3k.interlinked.me/users/luciferMysticus"}
}),
do: {:ok, @lm_pubkey}
def refetch_public_key(_), do: {:error, "no public key found"}
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jan 21, 9:23 PM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55758
Default Alt Text
(4 KB)
Attached To
Mode
R18 http_signatures
Attached
Detach File
Event Timeline
Log In to Comment