fix(e2ee): revert incorrect HKDF patch, remove pre-ratcheting
The HKDF sed patch in Dockerfile was wrong — it swapped salt/info based on incorrect analysis of minified JS. The original Rust FFI parameters are correct: salt="LKFrameEncryptionKey", info=[0;128]. Also removed Python-side HMAC pre-ratcheting of keys. Element Call uses explicit key rotation via Matrix events, not HMAC ratcheting. Added diagnostic logging to trace exact key bytes during E2EE setup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
33
voice.py
33
voice.py
@@ -295,18 +295,14 @@ class VoiceSession:
|
||||
if not self._caller_key:
|
||||
self._caller_key = key
|
||||
self._caller_identity = f"{sender}:{device_id}"
|
||||
# Pre-compute ratcheted keys from this base key to cover EC's key rotation.
|
||||
# EC rotates (via HMAC ratchet) when new participants join — the rotated key
|
||||
# arrives via Matrix sync with ~30s delay. Setting ratcheted indices 0..N
|
||||
# proactively means decryption works immediately without waiting for Matrix.
|
||||
ratcheted = _ratchet_keys(key, count=8)
|
||||
for ridx, rkey in ratcheted.items():
|
||||
actual_idx = index + ridx
|
||||
if actual_idx not in self._caller_all_keys: # don't overwrite real received keys
|
||||
self._caller_all_keys[actual_idx] = rkey
|
||||
self._caller_all_keys[index] = key # always store the real key at its index
|
||||
logger.info("E2EE key received from %s:%s (index=%d, %d bytes) — pre-computed ratchets [%d..%d]",
|
||||
sender, device_id, index, len(key), index, index + 7)
|
||||
# Store only the real key at its received index (no pre-ratcheting).
|
||||
# EC distributes keys explicitly via Matrix — no HMAC ratcheting.
|
||||
self._caller_all_keys[index] = key
|
||||
logger.info("E2EE key received from %s:%s (index=%d, %d bytes, raw=%s)",
|
||||
sender, device_id, index, len(key), key.hex())
|
||||
# Diagnostic: compute Python HKDF to compare with what Rust FFI should derive
|
||||
derived = _hkdf_derive(key)
|
||||
logger.info("E2EE_DIAG: Python HKDF(raw_key) = %s (expected AES-128-GCM key)", derived.hex())
|
||||
# Live-update key on rotation — use set_key() which applies HKDF via Rust FFI.
|
||||
# At this point the track is usually already subscribed so frame cryptor exists.
|
||||
if self.lk_room and self._caller_identity:
|
||||
@@ -465,27 +461,28 @@ class VoiceSession:
|
||||
# Solution: set caller key HERE, after frame cryptor is initialized.
|
||||
if int(t.kind) == 1 and e2ee_opts is not None: # audio track only
|
||||
caller_id = p.identity
|
||||
logger.info("E2EE_DIAG: track_subscribed for %s, have %d caller keys",
|
||||
caller_id, len(self._caller_all_keys))
|
||||
try:
|
||||
kp_local = self.lk_room.e2ee_manager.key_provider
|
||||
if self._caller_all_keys:
|
||||
for idx, base_k in sorted(self._caller_all_keys.items()):
|
||||
ok = kp_local.set_key(caller_id, base_k, idx)
|
||||
logger.info("on_ts: set_key[%d] for %s (ok=%s, %d bytes)",
|
||||
idx, caller_id, ok, len(base_k))
|
||||
logger.info("on_ts: set_key[%d] for %s (ok=%s, %d bytes, raw=%s)",
|
||||
idx, caller_id, ok, len(base_k), base_k.hex())
|
||||
else:
|
||||
logger.warning("on_ts: no caller keys available yet")
|
||||
except Exception as exc:
|
||||
logger.warning("on_ts: set_key failed: %s", exc)
|
||||
# Delayed retry — frame cryptor may not be ready at track_subscribed time
|
||||
# Delayed retry with additional diagnostics
|
||||
async def _delayed_set_key(pid=caller_id):
|
||||
await asyncio.sleep(1.0)
|
||||
await asyncio.sleep(1.5)
|
||||
try:
|
||||
kp_d = self.lk_room.e2ee_manager.key_provider
|
||||
if self._caller_all_keys:
|
||||
for idx, base_k in sorted(self._caller_all_keys.items()):
|
||||
ok = kp_d.set_key(pid, base_k, idx)
|
||||
logger.info("on_ts_delayed: set_key[%d] for %s (ok=%s, %d bytes)",
|
||||
idx, pid, ok, len(base_k))
|
||||
logger.info("on_ts_delayed: set_key[%d] for %s (ok=%s)", idx, pid, ok)
|
||||
except Exception as exc:
|
||||
logger.warning("on_ts_delayed: set_key failed: %s", exc)
|
||||
asyncio.ensure_future(_delayed_set_key())
|
||||
|
||||
Reference in New Issue
Block a user