fix: republish caller E2EE key as shared key, fallback to no-E2EE

Bot now publishes the same key as the caller so both sides can decrypt.
Falls back to no-encryption if no caller key received.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Christian Gick
2026-02-21 17:35:31 +02:00
parent 08f4e115b9
commit 1bc044eaae
2 changed files with 20 additions and 14 deletions

View File

@@ -83,7 +83,8 @@ def _build_e2ee_options(shared_key: bytes) -> rtc.E2EEOptions:
class VoiceSession:
def __init__(self, nio_client, room_id, device_id, lk_url, model="claude-sonnet"):
def __init__(self, nio_client, room_id, device_id, lk_url, model="claude-sonnet",
publish_key_cb=None):
self.nio_client = nio_client
self.room_id = room_id
self.device_id = device_id
@@ -94,6 +95,7 @@ class VoiceSession:
self._task = None
self._http_session = None
self._e2ee_key: bytes | None = None
self._publish_key_cb = publish_key_cb
def on_encryption_key(self, sender, device_id, key, index):
"""Receive E2EE key from Element Call participant."""
@@ -186,14 +188,15 @@ class VoiceSession:
if self._e2ee_key:
shared_key = self._e2ee_key
logger.info("Using E2EE key (%d bytes)", len(shared_key))
logger.info("Using caller E2EE key (%d bytes)", len(shared_key))
# Republish caller's key as our own so both sides share the same key
if self._publish_key_cb:
self._publish_key_cb(shared_key)
e2ee_opts = _build_e2ee_options(shared_key)
else:
# Generate our own key as fallback — bot.py already published one
import secrets
shared_key = secrets.token_bytes(32)
logger.warning("No caller E2EE key received — using generated key")
e2ee_opts = _build_e2ee_options(shared_key)
# No key received — connect WITHOUT E2EE so at least audio works
logger.warning("No caller E2EE key received — connecting WITHOUT encryption")
e2ee_opts = None
room_opts = rtc.RoomOptions(e2ee=e2ee_opts)
self.lk_room = rtc.Room()