diff --git a/voice.py b/voice.py index 80a4581..b860802 100644 --- a/voice.py +++ b/voice.py @@ -441,20 +441,21 @@ async def _confluence_recent_pages(limit: int = 5) -> list[dict]: def _build_e2ee_options() -> rtc.E2EEOptions: - """Build E2EE options — Rust FFI applies HKDF internally (KDF_HKDF=1). + """Build E2EE options matching Element Call / LiveKit JS SDK defaults. - 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. + Use PBKDF2=0 (default, no custom Rust KDF) so libwebrtc's C++ FrameCryptor + handles key derivation the same way as the JS SDK. The custom HKDF=1 path + in the Rust FFI fork uses different output sizes, causing DEC_FAILED. + + Element Call uses: ratchetWindowSize=0, keyringSize=16, ratchetSalt="LKFrameEncryptionKey" """ key_opts = rtc.KeyProviderOptions( shared_key=b"", # empty = per-participant mode - ratchet_window_size=10, + ratchet_window_size=0, ratchet_salt=b"LKFrameEncryptionKey", failure_tolerance=10, - key_ring_size=256, - key_derivation_function=KDF_HKDF, # Rust FFI applies HKDF; we pass raw base keys + key_ring_size=16, + key_derivation_function=0, # PBKDF2=0 = use libwebrtc default (no custom Rust KDF) ) return rtc.E2EEOptions( encryption_type=rtc.EncryptionType.GCM,