diff --git a/voice.py b/voice.py index b35e003..eeaa54f 100644 --- a/voice.py +++ b/voice.py @@ -220,17 +220,13 @@ def _ratchet_keys(base_raw: bytes, count: int = 6) -> dict[int, bytes]: def _derive_and_set_key(kp, identity: str, raw_key: bytes, index: int) -> None: - """Pre-derive HKDF key in Python, then set via KeyProvider (MAT-144). + """Set raw base key via KeyProvider — Rust HKDF derives AES key internally. - This replaces direct set_key(identity, raw_key, index) calls. - Pre-derivation in Python ensures exact match with Element Call JS HKDF, - eliminating Rust FFI HKDF implementation differences that caused - video frame decryption failures (audio worked, video didn't). + Wraps set_key() with diagnostic logging for MAT-144 investigation. """ - derived = _hkdf_derive(raw_key) - ok = kp.set_key(identity, derived, index) - logger.debug("set_key[%d] %s: raw=%s → derived=%s (ok=%s)", - index, identity, raw_key.hex()[:8], derived.hex(), ok) + ok = kp.set_key(identity, raw_key, index) + logger.debug("set_key[%d] %s: raw=%s (%d bytes, ok=%s)", + index, identity, raw_key.hex()[:8], len(raw_key), ok) async def _brave_search(query: str, count: int = 5) -> str: @@ -443,24 +439,21 @@ async def _confluence_recent_pages(limit: int = 5) -> list[dict]: return results -KDF_RAW = 0 # proto value 0 = PBKDF2 in proto, but Rust returns None (= no KDF = raw key) - - def _build_e2ee_options() -> rtc.E2EEOptions: - """Build E2EE options — Python pre-derives HKDF keys, Rust uses them raw (MAT-144). + """Build E2EE options — Rust FFI applies HKDF internally (KDF_HKDF=1). - We pre-derive AES keys via _hkdf_derive() in Python (matching EC's JS deriveEncryptionKey), - then pass derived keys to set_key() with KDF_RAW (proto 0 = no Rust-side derivation). - This eliminates any HKDF implementation mismatch between Rust FFI and Element Call JS. - Ratcheted keys are also pre-derived in Python via _ratchet_keys(). + Pass raw base keys from Matrix key exchange events directly to set_key(). + The Rust FFI derives the AES frame key via HKDF(base_key, ratchetSalt, ...) internally. + Element Call uses: ratchetWindowSize=10, keyringSize=256, ratchetSalt="LKFrameEncryptionKey" + NOTE: proto value 0 = PBKDF2 (NOT raw) — must use KDF_HKDF=1. """ key_opts = rtc.KeyProviderOptions( shared_key=b"", # empty = per-participant mode - ratchet_window_size=0, # we handle ratcheting in Python + ratchet_window_size=10, ratchet_salt=b"LKFrameEncryptionKey", failure_tolerance=10, key_ring_size=256, - key_derivation_function=KDF_RAW, # no Rust-side KDF; keys are pre-derived in Python + key_derivation_function=KDF_HKDF, # Rust FFI applies HKDF; we pass raw base keys ) return rtc.E2EEOptions( encryption_type=rtc.EncryptionType.GCM,