fix: handle Element X to-device keys format ({index,key} object, not array)

Element X sends keys as a single dict {index, key} not a list
[{index, key}]. The handler iterated over dict keys ('index','key')
instead of the actual key data. Also extracts device_id from
member.claimed_device_id (Element X format).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Christian Gick
2026-03-24 09:58:49 +02:00
parent dd904c6928
commit 621aca19ad

19
bot.py
View File

@@ -3890,11 +3890,19 @@ class Bot:
sender = source.get("sender", getattr(event, "sender", ""))
if evt_type == ENCRYPTION_KEYS_TYPE:
device_id = content.get("device_id", "")
room_id = content.get("room_id", content.get("call_id", ""))
keys_list = content.get("keys", [])
logger.info("Got to-device encryption_keys from %s (device=%s, room=%s, keys=%d)",
sender, device_id, room_id, len(keys_list))
# Element X to-device format: keys is a single {index, key} object
# Legacy format: keys is a list [{index, key}, ...]
raw_keys = content.get("keys", {})
if isinstance(raw_keys, dict):
keys_list = [raw_keys] if raw_keys.get("key") else []
else:
keys_list = raw_keys
# Device ID may be in member.claimed_device_id (Element X) or device_id
member = content.get("member", {})
device_id = member.get("claimed_device_id", content.get("device_id", ""))
logger.info("Got to-device encryption_keys from %s (device=%s, room=%s, keys=%d, raw_type=%s)",
sender, device_id, room_id, len(keys_list), type(raw_keys).__name__)
# Try to find the active voice session for this room
vs = None
@@ -3914,7 +3922,8 @@ class Bot:
key_b64 += "=" * (-len(key_b64) % 4)
key_bytes = base64.urlsafe_b64decode(key_b64)
vs.on_encryption_key(sender, device_id, key_bytes, key_index)
logger.info("Delivered to-device encryption key (index=%d) to voice session", key_index)
logger.info("Delivered to-device encryption key (index=%d, device=%s, %d bytes) to voice session",
key_index, device_id, len(key_bytes))
elif not vs:
logger.warning("Got to-device encryption_keys but no matching voice session (room=%s)", room_id)
else: