1aba435af38d51aebdecf83e253667f82a63325f
Root cause: web client's bundle included OTPKs, so X3DH initiate() did 4 DH ops (DH4 with OTPK). But decrypt_wire_message() called respond() with None for OTPK, doing only 3 DH ops. Different DH concat → different shared secret → decrypt fails. Fix: web client bundles have one_time_pre_key: None. initiate() skips DH4 when no OTPK present. respond() also skips DH4 with None. Both sides now do exactly 3 DH ops → shared secrets match. OTPKs are an anti-replay optimization, not required for E2E. Will add OTPK support to web client in Phase 2 with proper server-side OTPK storage and consumption tracking. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Description
No description provided
Languages
Rust
84%
Python
11.7%
Shell
4.3%