encryption: Initial key claiming support.
This commit is contained in:
parent
47fae308e0
commit
c8a7b4815d
4 changed files with 91 additions and 22 deletions
|
@ -306,7 +306,7 @@ class MatrixClient:
|
|||
|
||||
return HttpRequest(RequestType.POST, self.host, path, content)
|
||||
|
||||
def key_claim(self, key_dict):
|
||||
def keys_claim(self, key_dict):
|
||||
query_parameters = {"access_token": self.access_token}
|
||||
|
||||
path = ("{api}/keys/claim?"
|
||||
|
@ -315,7 +315,8 @@ class MatrixClient:
|
|||
query_parameters=urlencode(query_parameters))
|
||||
|
||||
content = {
|
||||
"one_time_keys": {key_dict}
|
||||
"one_time_keys": key_dict,
|
||||
"timeout": 10000
|
||||
}
|
||||
|
||||
return HttpRequest(RequestType.POST, self.host, path, content)
|
||||
|
@ -661,16 +662,17 @@ class MatrixKeyQueryMessage(MatrixMessage):
|
|||
|
||||
class MatrixKeyClaimMessage(MatrixMessage):
|
||||
|
||||
def __init__(self, client, key_dict):
|
||||
def __init__(self, client, room_id, key_dict):
|
||||
self.room_id = room_id
|
||||
data = {
|
||||
"key_dict": key_dict,
|
||||
}
|
||||
|
||||
MatrixMessage.__init__(self, client.keys_query, data)
|
||||
MatrixMessage.__init__(self, client.keys_claim, data)
|
||||
|
||||
def decode_body(self, server):
|
||||
object_hook = partial(MatrixEvents.MatrixKeyClaimEvent.from_dict,
|
||||
server)
|
||||
server, self.room_id)
|
||||
|
||||
return self._decode(server, object_hook)
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ import matrix.globals
|
|||
|
||||
try:
|
||||
from olm.account import Account, OlmAccountError
|
||||
from olm.session import (Session, InboundSession, OlmSessionError,
|
||||
OlmPreKeyMessage)
|
||||
from olm.session import (Session, InboundSession, OutboundSession,
|
||||
OlmSessionError, OlmPreKeyMessage)
|
||||
from olm.group_session import (
|
||||
InboundGroupSession,
|
||||
OutboundGroupSession,
|
||||
|
@ -193,6 +193,14 @@ class OlmDeviceKey():
|
|||
self.keys = key_dict
|
||||
|
||||
|
||||
class OneTimeKey():
|
||||
def __init__(self, user_id, device_id, key):
|
||||
# type: (str, str, str) -> None
|
||||
self.user_id = user_id
|
||||
self.device_id = device_id
|
||||
self.key = key
|
||||
|
||||
|
||||
class Olm():
|
||||
|
||||
@encrypt_enabled
|
||||
|
@ -245,6 +253,28 @@ class Olm():
|
|||
|
||||
return session
|
||||
|
||||
def create_session(self, user_id, device_id, one_time_key):
|
||||
W.prnt("", "matrix: Creating session for {}".format(user_id))
|
||||
id_key = None
|
||||
|
||||
for user, keys in self.device_keys.items():
|
||||
if user != user_id:
|
||||
continue
|
||||
|
||||
for key in keys:
|
||||
if key.device_id == device_id:
|
||||
id_key = key.keys["curve25519"]
|
||||
break
|
||||
|
||||
if not id_key:
|
||||
W.prnt("", "ERRR not found ID key")
|
||||
W.prnt("", "Found id key {}".format(id_key))
|
||||
session = OutboundSession(self.account, id_key, one_time_key)
|
||||
self._update_acc_in_db()
|
||||
self.sessions[user_id][device_id].append(session)
|
||||
self._store_session(user_id, device_id, session)
|
||||
W.prnt("", "matrix: Created session for {}".format(user_id))
|
||||
|
||||
def create_group_session(self, room_id, session_id, session_key):
|
||||
W.prnt("", "matrix: Creating group session for {}".format(room_id))
|
||||
session = InboundGroupSession(session_key)
|
||||
|
@ -270,10 +300,12 @@ class Olm():
|
|||
continue
|
||||
|
||||
if not self.sessions[user][key.device_id]:
|
||||
W.prnt("", "Missing session for device {}".format(key.device_id))
|
||||
devices.append(key.device_id)
|
||||
|
||||
if devices:
|
||||
missing[user] = {device: "ed25519" for device in devices}
|
||||
missing[user] = {device: "signed_curve25519" for
|
||||
device in devices}
|
||||
|
||||
return missing
|
||||
|
||||
|
@ -376,11 +408,16 @@ class Olm():
|
|||
}
|
||||
|
||||
for user in users:
|
||||
if user not in self.device_keys:
|
||||
continue
|
||||
|
||||
for key in self.device_keys[user]:
|
||||
if key.device_id == self.device_id:
|
||||
continue
|
||||
|
||||
if not self.sessions[user][key.device_id]:
|
||||
continue
|
||||
|
||||
device_payload_dict = payload_dict.copy()
|
||||
# TODO sort the sessions
|
||||
session = self.sessions[user][key.device_id][0]
|
||||
|
@ -389,8 +426,6 @@ class Olm():
|
|||
"ed25519": key.keys["ed25519"]
|
||||
}
|
||||
|
||||
W.prnt("", pprint.pformat(device_payload_dict))
|
||||
|
||||
olm_message = session.encrypt(
|
||||
Olm._to_json(device_payload_dict)
|
||||
)
|
||||
|
@ -414,6 +449,7 @@ class Olm():
|
|||
|
||||
to_device_dict["messages"][user][key.device_id] = olm_dict
|
||||
|
||||
# W.prnt("", pprint.pformat(to_device_dict))
|
||||
return to_device_dict
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -31,7 +31,7 @@ from matrix.rooms import (matrix_create_room_buffer, RoomInfo, RoomMessageText,
|
|||
RoomMessageEvent, RoomRedactedMessageEvent,
|
||||
RoomMessageEmote)
|
||||
|
||||
from matrix.encryption import OlmDeviceKey
|
||||
from matrix.encryption import OlmDeviceKey, OneTimeKey
|
||||
|
||||
try:
|
||||
from olm.session import OlmMessage, OlmPreKeyMessage
|
||||
|
@ -355,16 +355,38 @@ class MatrixKeyQueryEvent(MatrixEvent):
|
|||
|
||||
class MatrixKeyClaimEvent(MatrixEvent):
|
||||
|
||||
def __init__(self, server, keys):
|
||||
def __init__(self, server, room_id, keys):
|
||||
self.keys = keys
|
||||
self.room_id = room_id
|
||||
MatrixEvent.__init__(self, server)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, server, parsed_dict):
|
||||
raise NotImplementedError
|
||||
def from_dict(cls, server, room_id, parsed_dict):
|
||||
W.prnt("", pprint.pformat(parsed_dict))
|
||||
keys = []
|
||||
try:
|
||||
for user_id, user_dict in parsed_dict["one_time_keys"].items():
|
||||
for device_id, device_dict in user_dict.items():
|
||||
for key_dict in device_dict.values():
|
||||
# TODO check the signature of the key
|
||||
key = OneTimeKey(user_id, device_id, key_dict["key"])
|
||||
keys.append(key)
|
||||
|
||||
return cls(server, room_id, keys)
|
||||
except KeyError:
|
||||
return MatrixErrorEvent.from_dict(
|
||||
server, ("Error claiming onetime keys."), False, parsed_dict)
|
||||
|
||||
def execute(self):
|
||||
pass
|
||||
server = self.server
|
||||
olm = server.olm
|
||||
|
||||
for key in self.keys:
|
||||
olm.create_session(key.user_id, key.device_id, key.key)
|
||||
|
||||
while server.encryption_queue[self.room_id]:
|
||||
formatted_message = server.encryption_queue[self.room_id].popleft()
|
||||
server.send_room_message(self.room_id, formatted_message, True)
|
||||
|
||||
|
||||
class MatrixToDeviceEvent(MatrixEvent):
|
||||
|
@ -384,6 +406,7 @@ class MatrixToDeviceEvent(MatrixEvent):
|
|||
"device message"),
|
||||
False, parsed_dict)
|
||||
|
||||
|
||||
class MatrixBacklogEvent(MatrixEvent):
|
||||
|
||||
def __init__(self, server, room_id, end_token, events):
|
||||
|
|
|
@ -24,7 +24,7 @@ import time
|
|||
import datetime
|
||||
import pprint
|
||||
|
||||
from collections import deque
|
||||
from collections import deque, defaultdict
|
||||
from http_parser.pyparser import HttpParser
|
||||
|
||||
from matrix.plugin_options import Option, DebugType
|
||||
|
@ -40,7 +40,8 @@ from matrix.api import (
|
|||
MatrixKeyUploadMessage,
|
||||
MatrixKeyQueryMessage,
|
||||
MatrixToDeviceMessage,
|
||||
MatrixEncryptedMessage
|
||||
MatrixEncryptedMessage,
|
||||
MatrixKeyClaimMessage
|
||||
)
|
||||
|
||||
from matrix.encryption import Olm, EncryptionError, encrypt_enabled
|
||||
|
@ -63,7 +64,9 @@ class MatrixServer:
|
|||
self.options = dict() # type: Dict[str, weechat.config]
|
||||
self.device_name = "Weechat Matrix" # type: str
|
||||
self.device_id = "" # type: str
|
||||
|
||||
self.olm = None # type: Olm
|
||||
self.encryption_queue = defaultdict(deque)
|
||||
|
||||
self.user = "" # type: str
|
||||
self.password = "" # type: str
|
||||
|
@ -478,7 +481,12 @@ class MatrixServer:
|
|||
message = MatrixSyncMessage(self.client, self.next_batch, limit)
|
||||
self.send_queue.append(message)
|
||||
|
||||
def send_room_message(self, room_id, formatted_data):
|
||||
def send_room_message(
|
||||
self,
|
||||
room_id,
|
||||
formatted_data,
|
||||
already_claimed=False
|
||||
):
|
||||
# type: (str, Formatted) -> None
|
||||
room = self.rooms[room_id]
|
||||
|
||||
|
@ -488,13 +496,13 @@ class MatrixServer:
|
|||
# TODO don't send messages unless all the devices are verified
|
||||
missing = self.olm.get_missing_sessions(room.users.keys())
|
||||
|
||||
if missing:
|
||||
if missing and not already_claimed:
|
||||
W.prnt("", "{prefix}matrix: Olm session missing for room, can't"
|
||||
" encrypt message.")
|
||||
W.prnt("", pprint.pformat(missing))
|
||||
# message = MatrixKeyClaimMessage(self.client, missing)
|
||||
# self.send_or_queue(message)
|
||||
# TODO claim keys for the missing user/device combinations
|
||||
self.encryption_queue[room_id].append(formatted_data)
|
||||
message = MatrixKeyClaimMessage(self.client, room_id, missing)
|
||||
self.send_or_queue(message)
|
||||
return
|
||||
|
||||
body = {"msgtype": "m.text", "body": formatted_data.to_plain()}
|
||||
|
|
Loading…
Add table
Reference in a new issue