From 27b376e1f5a806ce6ca76f81059d5022eea65632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?poljar=20=28Damir=20Jeli=C4=87=29?= Date: Thu, 22 Mar 2018 21:02:31 +0100 Subject: [PATCH] olm: Upload the identity keys. --- matrix/api.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ matrix/events.py | 21 ++++++++++++++++ matrix/server.py | 16 +++++++++++- 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/matrix/api.py b/matrix/api.py index f9e4a83..221d6b5 100644 --- a/matrix/api.py +++ b/matrix/api.py @@ -224,6 +224,49 @@ class MatrixClient: h = HttpRequest(RequestType.POST, self.host, path, content) return h + def keys_upload(self, user_id, device_id, account, keys=None, + one_time_keys=None): + query_parameters = {"access_token": self.access_token} + + path = ("{api}/keys/upload?" + "{query_parameters}").format( + api=MATRIX_API_PATH, + query_parameters=urlencode(query_parameters)) + + content = {} + + # TODO one time keys + if keys: + device_keys = { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": device_id, + "user_id": user_id, + "keys": { + "curve25519:" + device_id: keys["curve25519"], + "ed25519:" + device_id: keys["ed25519"] + } + } + + signature = account.sign(json.dumps( + device_keys, + ensure_ascii=False, + separators=(',', ':'), + sort_keys=True, + )) + + device_keys["signatures"] = { + user_id: { + "ed25519:" + device_id: signature + } + } + + content["device_keys"] = device_keys + + return HttpRequest(RequestType.POST, self.host, path, content) + def mxc_to_http(self, mxc): # type: (str) -> str url = urlparse(mxc) @@ -510,3 +553,24 @@ class MatrixKickMessage(MatrixMessage): self.reason) return self._decode(server, object_hook) + + +class MatrixKeyUploadMessage(MatrixMessage): + + def __init__(self, client, user_id, device_id, account, keys=None, + one_time_keys=None): + data = { + "device_id": device_id, + "user_id": user_id, + "account": account, + "keys": keys, + "one_time_keys": one_time_keys + } + + MatrixMessage.__init__(self, client.keys_upload, data) + + def decode_body(self, server): + object_hook = partial(MatrixEvents.MatrixKeyUploadEvent.from_dict, + server) + + return self._decode(server, object_hook) diff --git a/matrix/events.py b/matrix/events.py index b87436b..7d5f495 100644 --- a/matrix/events.py +++ b/matrix/events.py @@ -67,6 +67,26 @@ class MatrixErrorEvent(MatrixEvent): fatal=fatal) +class MatrixKeyUploadEvent(MatrixEvent): + + def __init__(self, server): + MatrixEvent.__init__(self, server) + + def execute(self): + message = "{prefix}matrix: Uploaded olm device keys.".format( + prefix=W.prefix("network")) + + W.prnt(self.server.server_buffer, message) + + @classmethod + def from_dict(cls, server, parsed_dict): + try: + return cls(server) + except (KeyError, TypeError, ValueError): + return MatrixErrorEvent.from_dict(server, "Error uploading device" + "keys", False, parsed_dict) + + class MatrixLoginEvent(MatrixEvent): def __init__(self, server, user_id, device_id, access_token): @@ -90,6 +110,7 @@ class MatrixLoginEvent(MatrixEvent): if not self.server.olm: self.server.create_olm() self.server.store_olm() + self.server.upload_keys(device_keys=True, one_time_keys=False) self.server.sync() diff --git a/matrix/server.py b/matrix/server.py index fcac056..e9f0cc5 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -33,7 +33,12 @@ from matrix.utils import (key_from_value, prnt_debug, server_buffer_prnt, from matrix.utf import utf8_decode from matrix.globals import W, SERVERS, OPTIONS import matrix.api as API -from matrix.api import MatrixClient, MatrixSyncMessage, MatrixLoginMessage +from matrix.api import ( + MatrixClient, + MatrixSyncMessage, + MatrixLoginMessage, + MatrixKeyUploadMessage +) from matrix.encryption import Olm, EncryptionError @@ -456,6 +461,15 @@ class MatrixServer: message = MatrixSyncMessage(self.client, self.next_batch, limit) self.send_queue.append(message) + def upload_keys(self, device_keys=False, one_time_keys=False): + keys = self.olm.account.identity_keys() if device_keys else None + + # TODO generate one time keys and upload them as well + message = MatrixKeyUploadMessage(self.client, self.user_id, + self.device_id, self.olm.account, + keys, None) + self.send_queue.append(message) + def login(self): # type: (MatrixServer) -> None message = MatrixLoginMessage(self.client, self.user, self.password,