Add endpoint to get server publishing keys

This commit is contained in:
Pim Kunis 2021-08-06 15:52:03 +02:00
parent 38af22fea6
commit ef9ae82e75
5 changed files with 58 additions and 13 deletions

View file

@ -42,10 +42,7 @@ defmodule MatrixServer.Device do
def generate_device_id(localpart) do def generate_device_id(localpart) do
# TODO: use random string instead # TODO: use random string instead
time_string = time_string = System.os_time(:millisecond) |> Integer.to_string()
DateTime.utc_now()
|> DateTime.to_unix()
|> Integer.to_string()
"#{localpart}_#{time_string}" "#{localpart}_#{time_string}"
end end

View file

@ -28,7 +28,7 @@ defmodule MatrixServer.Event do
room_id: room_id, room_id: room_id,
sender: MatrixServer.get_mxid(localpart), sender: MatrixServer.get_mxid(localpart),
event_id: generate_event_id(), event_id: generate_event_id(),
origin_server_ts: DateTime.utc_now() |> DateTime.to_unix(), origin_server_ts: System.os_time(:millisecond),
prev_events: [], prev_events: [],
auth_events: [] auth_events: []
} }
@ -281,7 +281,7 @@ defmodule MatrixServer.Event do
event event
|> Map.put(:hashes, %{"sha256" => content_hash}) |> Map.put(:hashes, %{"sha256" => content_hash})
|> redact() |> redact()
|> SigningServer.sign_event() |> SigningServer.sign_object()
end end
defp calculate_content_hash(event) do defp calculate_content_hash(event) do

View file

@ -12,8 +12,12 @@ defmodule MatrixServer.SigningServer do
GenServer.start_link(__MODULE__, opts, name: __MODULE__) GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end end
def sign_event(event) do def sign_object(object) do
GenServer.call(__MODULE__, {:sign_event, event}) GenServer.call(__MODULE__, {:sign_object, object})
end
def get_signing_keys do
GenServer.call(__MODULE__, :get_signing_keys)
end end
## Implementation ## Implementation
@ -27,12 +31,12 @@ defmodule MatrixServer.SigningServer do
# https://blog.swwomm.com/2020/09/elixir-ed25519-signatures-with-enacl.html # https://blog.swwomm.com/2020/09/elixir-ed25519-signatures-with-enacl.html
@impl true @impl true
def handle_call( def handle_call(
{:sign_event, event}, {:sign_object, object},
_from, _from,
%{private_key: private_key} = state %{private_key: private_key} = state
) do ) do
ordered_map = ordered_map =
event object
|> Map.drop([:signatures, :unsigned]) |> Map.drop([:signatures, :unsigned])
|> OrderedMap.from_map() |> OrderedMap.from_map()
@ -46,18 +50,24 @@ defmodule MatrixServer.SigningServer do
signature_map = %{@signing_key_id => signature} signature_map = %{@signing_key_id => signature}
servername = MatrixServer.server_name() servername = MatrixServer.server_name()
event = signed_object =
Map.update(event, :signatures, %{servername => signature_map}, fn signatures -> Map.update(object, :signatures, %{servername => signature_map}, fn signatures ->
Map.put(signatures, servername, signature_map) Map.put(signatures, servername, signature_map)
end) end)
{:reply, event, state} {:reply, {:ok, signed_object}, state}
{:error, _msg} -> {:error, _msg} ->
{:reply, {:error, :json_encode}, state} {:reply, {:error, :json_encode}, state}
end end
end end
def handle_call(:get_signing_keys, _from, %{public_key: public_key} = state) do
encoded_public_key = MatrixServer.encode_unpadded_base64(public_key)
{:reply, [{@signing_key_id, encoded_public_key}], state}
end
# TODO: not sure if there is a better way to do this... # TODO: not sure if there is a better way to do this...
defp get_keys do defp get_keys do
raw_priv_key = raw_priv_key =

View file

@ -0,0 +1,34 @@
defmodule MatrixServerWeb.KeyController do
use MatrixServerWeb, :controller
import MatrixServerWeb.Plug.Error
alias MatrixServer.SigningServer
@key_valid_time_ms 1000 * 60 * 24 * 30
def get_signing_keys(conn, _params) do
keys =
SigningServer.get_signing_keys()
|> Enum.into(%{}, fn {key_id, key} ->
{key_id, %{"key" => key}}
end)
data = %{
server_name: MatrixServer.server_name(),
verify_keys: keys,
old_verify_keys: %{},
valid_until_ts: System.os_time(:millisecond) + @key_valid_time_ms
}
case SigningServer.sign_object(data) do
{:ok, signed_data} ->
conn
|> put_status(200)
|> json(signed_data)
{:error, _msg} ->
put_error(conn, :unknown, "Error signing object.")
end
end
end

View file

@ -22,6 +22,10 @@ defmodule MatrixServerWeb.Router do
post "/login", AuthController, :login post "/login", AuthController, :login
end end
scope "/key/v2" do
get "/server", KeyController, :get_signing_keys
end
get "/client/versions", InfoController, :versions get "/client/versions", InfoController, :versions
end end