diff --git a/lib/matrix_server/device.ex b/lib/matrix_server/device.ex index 40da497..b78b549 100644 --- a/lib/matrix_server/device.ex +++ b/lib/matrix_server/device.ex @@ -42,10 +42,7 @@ defmodule MatrixServer.Device do def generate_device_id(localpart) do # TODO: use random string instead - time_string = - DateTime.utc_now() - |> DateTime.to_unix() - |> Integer.to_string() + time_string = System.os_time(:millisecond) |> Integer.to_string() "#{localpart}_#{time_string}" end diff --git a/lib/matrix_server/event.ex b/lib/matrix_server/event.ex index 68ed749..c22e67a 100644 --- a/lib/matrix_server/event.ex +++ b/lib/matrix_server/event.ex @@ -28,7 +28,7 @@ defmodule MatrixServer.Event do room_id: room_id, sender: MatrixServer.get_mxid(localpart), event_id: generate_event_id(), - origin_server_ts: DateTime.utc_now() |> DateTime.to_unix(), + origin_server_ts: System.os_time(:millisecond), prev_events: [], auth_events: [] } @@ -281,7 +281,7 @@ defmodule MatrixServer.Event do event |> Map.put(:hashes, %{"sha256" => content_hash}) |> redact() - |> SigningServer.sign_event() + |> SigningServer.sign_object() end defp calculate_content_hash(event) do diff --git a/lib/matrix_server/signing_server.ex b/lib/matrix_server/signing_server.ex index b024793..c6d949c 100644 --- a/lib/matrix_server/signing_server.ex +++ b/lib/matrix_server/signing_server.ex @@ -12,8 +12,12 @@ defmodule MatrixServer.SigningServer do GenServer.start_link(__MODULE__, opts, name: __MODULE__) end - def sign_event(event) do - GenServer.call(__MODULE__, {:sign_event, event}) + def sign_object(object) do + GenServer.call(__MODULE__, {:sign_object, object}) + end + + def get_signing_keys do + GenServer.call(__MODULE__, :get_signing_keys) end ## Implementation @@ -27,12 +31,12 @@ defmodule MatrixServer.SigningServer do # https://blog.swwomm.com/2020/09/elixir-ed25519-signatures-with-enacl.html @impl true def handle_call( - {:sign_event, event}, + {:sign_object, object}, _from, %{private_key: private_key} = state ) do ordered_map = - event + object |> Map.drop([:signatures, :unsigned]) |> OrderedMap.from_map() @@ -46,18 +50,24 @@ defmodule MatrixServer.SigningServer do signature_map = %{@signing_key_id => signature} servername = MatrixServer.server_name() - event = - Map.update(event, :signatures, %{servername => signature_map}, fn signatures -> + signed_object = + Map.update(object, :signatures, %{servername => signature_map}, fn signatures -> Map.put(signatures, servername, signature_map) end) - {:reply, event, state} + {:reply, {:ok, signed_object}, state} {:error, _msg} -> {:reply, {:error, :json_encode}, state} 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... defp get_keys do raw_priv_key = diff --git a/lib/matrix_server_web/controllers/key_controller.ex b/lib/matrix_server_web/controllers/key_controller.ex new file mode 100644 index 0000000..4c3c9fa --- /dev/null +++ b/lib/matrix_server_web/controllers/key_controller.ex @@ -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 diff --git a/lib/matrix_server_web/router.ex b/lib/matrix_server_web/router.ex index f007714..95993fd 100644 --- a/lib/matrix_server_web/router.ex +++ b/lib/matrix_server_web/router.ex @@ -22,6 +22,10 @@ defmodule MatrixServerWeb.Router do post "/login", AuthController, :login end + scope "/key/v2" do + get "/server", KeyController, :get_signing_keys + end + get "/client/versions", InfoController, :versions end