olm: One time key creation/uploading.
This commit is contained in:
parent
27b376e1f5
commit
36cd12225b
4 changed files with 76 additions and 21 deletions
|
@ -224,7 +224,7 @@ class MatrixClient:
|
||||||
h = HttpRequest(RequestType.POST, self.host, path, content)
|
h = HttpRequest(RequestType.POST, self.host, path, content)
|
||||||
return h
|
return h
|
||||||
|
|
||||||
def keys_upload(self, user_id, device_id, account, keys=None,
|
def keys_upload(self, user_id, device_id, olm, keys=None,
|
||||||
one_time_keys=None):
|
one_time_keys=None):
|
||||||
query_parameters = {"access_token": self.access_token}
|
query_parameters = {"access_token": self.access_token}
|
||||||
|
|
||||||
|
@ -235,7 +235,6 @@ class MatrixClient:
|
||||||
|
|
||||||
content = {}
|
content = {}
|
||||||
|
|
||||||
# TODO one time keys
|
|
||||||
if keys:
|
if keys:
|
||||||
device_keys = {
|
device_keys = {
|
||||||
"algorithms": [
|
"algorithms": [
|
||||||
|
@ -250,12 +249,7 @@ class MatrixClient:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signature = account.sign(json.dumps(
|
signature = olm.sign_json(device_keys)
|
||||||
device_keys,
|
|
||||||
ensure_ascii=False,
|
|
||||||
separators=(',', ':'),
|
|
||||||
sort_keys=True,
|
|
||||||
))
|
|
||||||
|
|
||||||
device_keys["signatures"] = {
|
device_keys["signatures"] = {
|
||||||
user_id: {
|
user_id: {
|
||||||
|
@ -265,6 +259,24 @@ class MatrixClient:
|
||||||
|
|
||||||
content["device_keys"] = device_keys
|
content["device_keys"] = device_keys
|
||||||
|
|
||||||
|
if one_time_keys:
|
||||||
|
one_time_key_dict = {}
|
||||||
|
|
||||||
|
for key_id, key in one_time_keys.items():
|
||||||
|
key_dict = {"key": key}
|
||||||
|
signature = olm.sign_json(key_dict)
|
||||||
|
|
||||||
|
one_time_key_dict["signed_curve25519:" + key_id] = {
|
||||||
|
"key": key_dict.pop("key"),
|
||||||
|
"signatures": {
|
||||||
|
user_id: {
|
||||||
|
"ed25519:" + device_id: signature
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content["one_time_keys"] = one_time_key_dict
|
||||||
|
|
||||||
return HttpRequest(RequestType.POST, self.host, path, content)
|
return HttpRequest(RequestType.POST, self.host, path, content)
|
||||||
|
|
||||||
def mxc_to_http(self, mxc):
|
def mxc_to_http(self, mxc):
|
||||||
|
@ -557,20 +569,22 @@ class MatrixKickMessage(MatrixMessage):
|
||||||
|
|
||||||
class MatrixKeyUploadMessage(MatrixMessage):
|
class MatrixKeyUploadMessage(MatrixMessage):
|
||||||
|
|
||||||
def __init__(self, client, user_id, device_id, account, keys=None,
|
def __init__(self, client, user_id, device_id, olm, keys=None,
|
||||||
one_time_keys=None):
|
one_time_keys=None):
|
||||||
data = {
|
data = {
|
||||||
"device_id": device_id,
|
"device_id": device_id,
|
||||||
"user_id": user_id,
|
"user_id": user_id,
|
||||||
"account": account,
|
"olm": olm,
|
||||||
"keys": keys,
|
"keys": keys,
|
||||||
"one_time_keys": one_time_keys
|
"one_time_keys": one_time_keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.device_keys = True if keys else False
|
||||||
|
|
||||||
MatrixMessage.__init__(self, client.keys_upload, data)
|
MatrixMessage.__init__(self, client.keys_upload, data)
|
||||||
|
|
||||||
def decode_body(self, server):
|
def decode_body(self, server):
|
||||||
object_hook = partial(MatrixEvents.MatrixKeyUploadEvent.from_dict,
|
object_hook = partial(MatrixEvents.MatrixKeyUploadEvent.from_dict,
|
||||||
server)
|
server, self.device_keys)
|
||||||
|
|
||||||
return self._decode(server, object_hook)
|
return self._decode(server, object_hook)
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
# pylint: disable=redefined-builtin
|
# pylint: disable=redefined-builtin
|
||||||
from builtins import str
|
from builtins import str
|
||||||
|
@ -188,3 +189,13 @@ class Olm():
|
||||||
f.write(pickle)
|
f.write(pickle)
|
||||||
except OlmAccountError as error:
|
except OlmAccountError as error:
|
||||||
raise EncryptionError(error)
|
raise EncryptionError(error)
|
||||||
|
|
||||||
|
def sign_json(self, json_dict):
|
||||||
|
signature = self.account.sign(json.dumps(
|
||||||
|
json_dict,
|
||||||
|
ensure_ascii=False,
|
||||||
|
separators=(',', ':'),
|
||||||
|
sort_keys=True,
|
||||||
|
))
|
||||||
|
|
||||||
|
return signature
|
||||||
|
|
|
@ -69,19 +69,23 @@ class MatrixErrorEvent(MatrixEvent):
|
||||||
|
|
||||||
class MatrixKeyUploadEvent(MatrixEvent):
|
class MatrixKeyUploadEvent(MatrixEvent):
|
||||||
|
|
||||||
def __init__(self, server):
|
def __init__(self, server, device_keys):
|
||||||
|
self.device_keys = device_keys
|
||||||
MatrixEvent.__init__(self, server)
|
MatrixEvent.__init__(self, server)
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
message = "{prefix}matrix: Uploaded olm device keys.".format(
|
if not self.device_keys:
|
||||||
|
return
|
||||||
|
|
||||||
|
message = "{prefix}matrix: Uploaded Olm device keys.".format(
|
||||||
prefix=W.prefix("network"))
|
prefix=W.prefix("network"))
|
||||||
|
|
||||||
W.prnt(self.server.server_buffer, message)
|
W.prnt(self.server.server_buffer, message)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, server, parsed_dict):
|
def from_dict(cls, server, device_keys, parsed_dict):
|
||||||
try:
|
try:
|
||||||
return cls(server)
|
return cls(server, device_keys)
|
||||||
except (KeyError, TypeError, ValueError):
|
except (KeyError, TypeError, ValueError):
|
||||||
return MatrixErrorEvent.from_dict(server, "Error uploading device"
|
return MatrixErrorEvent.from_dict(server, "Error uploading device"
|
||||||
"keys", False, parsed_dict)
|
"keys", False, parsed_dict)
|
||||||
|
@ -415,10 +419,12 @@ class MatrixBacklogEvent(MatrixEvent):
|
||||||
|
|
||||||
class MatrixSyncEvent(MatrixEvent):
|
class MatrixSyncEvent(MatrixEvent):
|
||||||
|
|
||||||
def __init__(self, server, next_batch, room_infos, invited_infos):
|
def __init__(self, server, next_batch, room_infos, invited_infos,
|
||||||
|
one_time_key_count):
|
||||||
self.next_batch = next_batch
|
self.next_batch = next_batch
|
||||||
self.joined_room_infos = room_infos
|
self.joined_room_infos = room_infos
|
||||||
self.invited_room_infos = invited_infos
|
self.invited_room_infos = invited_infos
|
||||||
|
self.one_time_key_count = one_time_key_count
|
||||||
|
|
||||||
MatrixEvent.__init__(self, server)
|
MatrixEvent.__init__(self, server)
|
||||||
|
|
||||||
|
@ -439,12 +445,21 @@ class MatrixSyncEvent(MatrixEvent):
|
||||||
def from_dict(cls, server, parsed_dict):
|
def from_dict(cls, server, parsed_dict):
|
||||||
try:
|
try:
|
||||||
next_batch = sanitize_id(parsed_dict["next_batch"])
|
next_batch = sanitize_id(parsed_dict["next_batch"])
|
||||||
|
one_time_key_count = 0
|
||||||
|
|
||||||
|
if "device_one_time_keys_count" in parsed_dict:
|
||||||
|
if ("signed_curve25519" in
|
||||||
|
parsed_dict["device_one_time_keys_count"]):
|
||||||
|
one_time_key_count = (
|
||||||
|
parsed_dict["device_one_time_keys_count"]["signed_curve25519"])
|
||||||
|
|
||||||
room_info_dict = parsed_dict["rooms"]
|
room_info_dict = parsed_dict["rooms"]
|
||||||
|
|
||||||
join_infos, invite_infos = MatrixSyncEvent._infos_from_dict(
|
join_infos, invite_infos = MatrixSyncEvent._infos_from_dict(
|
||||||
room_info_dict)
|
room_info_dict)
|
||||||
|
|
||||||
return cls(server, next_batch, join_infos, invite_infos)
|
return cls(server, next_batch, join_infos, invite_infos,
|
||||||
|
one_time_key_count)
|
||||||
except (KeyError, ValueError, TypeError):
|
except (KeyError, ValueError, TypeError):
|
||||||
return MatrixErrorEvent.from_dict(server, "Error syncing", False,
|
return MatrixErrorEvent.from_dict(server, "Error syncing", False,
|
||||||
parsed_dict)
|
parsed_dict)
|
||||||
|
@ -475,5 +490,6 @@ class MatrixSyncEvent(MatrixEvent):
|
||||||
|
|
||||||
self._queue_joined_info()
|
self._queue_joined_info()
|
||||||
server.next_batch = self.next_batch
|
server.next_batch = self.next_batch
|
||||||
|
server.check_one_time_keys(self.one_time_key_count)
|
||||||
|
|
||||||
server.handle_events()
|
server.handle_events()
|
||||||
|
|
|
@ -40,7 +40,7 @@ from matrix.api import (
|
||||||
MatrixKeyUploadMessage
|
MatrixKeyUploadMessage
|
||||||
)
|
)
|
||||||
|
|
||||||
from matrix.encryption import Olm, EncryptionError
|
from matrix.encryption import Olm, EncryptionError, encrypt_enabled
|
||||||
|
|
||||||
try:
|
try:
|
||||||
FileNotFoundError
|
FileNotFoundError
|
||||||
|
@ -464,12 +464,26 @@ class MatrixServer:
|
||||||
def upload_keys(self, device_keys=False, one_time_keys=False):
|
def upload_keys(self, device_keys=False, one_time_keys=False):
|
||||||
keys = self.olm.account.identity_keys() if device_keys else None
|
keys = self.olm.account.identity_keys() if device_keys else None
|
||||||
|
|
||||||
# TODO generate one time keys and upload them as well
|
one_time_keys = (self.olm.account.one_time_keys()["curve25519"] if
|
||||||
|
one_time_keys else None)
|
||||||
|
|
||||||
message = MatrixKeyUploadMessage(self.client, self.user_id,
|
message = MatrixKeyUploadMessage(self.client, self.user_id,
|
||||||
self.device_id, self.olm.account,
|
self.device_id, self.olm,
|
||||||
keys, None)
|
keys, one_time_keys)
|
||||||
self.send_queue.append(message)
|
self.send_queue.append(message)
|
||||||
|
|
||||||
|
@encrypt_enabled
|
||||||
|
def check_one_time_keys(self, key_count):
|
||||||
|
max_keys = self.olm.account.max_one_time_keys()
|
||||||
|
|
||||||
|
key_count = (max_keys / 2) - key_count
|
||||||
|
|
||||||
|
if key_count <= 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.olm.account.generate_one_time_keys(key_count)
|
||||||
|
self.upload_keys(device_keys=False, one_time_keys=True)
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
# type: (MatrixServer) -> None
|
# type: (MatrixServer) -> None
|
||||||
message = MatrixLoginMessage(self.client, self.user, self.password,
|
message = MatrixLoginMessage(self.client, self.user, self.password,
|
||||||
|
|
Loading…
Add table
Reference in a new issue