Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85630088
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
3 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 af88339..bddbe0c 100644
--- a/lib/http_signatures/http_signatures.ex
+++ b/lib/http_signatures/http_signatures.ex
@@ -1,94 +1,105 @@
# Pleroma: A lightweight social networking server
-# SPDX-FileCopyrightText: 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-FileCopyrightText: 2017-2026 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
+ @doc "Split raw signature string into a Map of individual components."
+ @spec split_signature(binary()) :: map()
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
+ @spec validate(map(), map(), any()) :: boolean()
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
+ @doc "Fetch public key and validate signature."
+ @spec validate_conn(%Plug.Conn{}) :: boolean()
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
+ @doc "Validate signature using specified public key."
+ @spec validate_conn(%Plug.Conn{}, any()) :: boolean()
def validate_conn(conn, public_key) do
headers = Enum.into(conn.req_headers, %{})
signature = split_signature(headers["signature"])
validate(headers, signature, public_key)
end
@doc "Get signature for conn in split form."
+ @spec signature_for_conn(%Plug.Conn{}) :: map()
def signature_for_conn(conn) do
with headers <- Enum.into(conn.req_headers, %{}),
signature when is_binary(signature) <- headers["signature"] do
split_signature(signature)
else
_ ->
%{}
end
end
+ @spec build_signing_string(map(), list()) :: String.t()
def build_signing_string(headers, used_headers) do
used_headers
|> Enum.map_join("\n", fn header -> "#{header}: #{headers[header]}" end)
end
+ @doc "Create rsa-sha256 signature."
+ @spec sign(any(), String.t(), map()) :: String.t()
def sign(private_key, key_id, headers) do
sigstring = build_signing_string(headers, Enum.sort(Map.keys(headers)))
signature =
:public_key.sign(sigstring, :sha256, private_key)
|> Base.encode64()
[
keyId: key_id,
algorithm: "rsa-sha256",
headers: Map.keys(headers) |> Enum.sort() |> Enum.join(" "),
signature: signature
]
|> Enum.map_join(",", fn {k, v} -> "#{k}=\"#{v}\"" end)
end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Aug 9, 9:55 AM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1722855
Default Alt Text
(3 KB)
Attached To
Mode
R18 http_signatures
Attached
Detach File
Event Timeline
Log In to Comment