Skip to content

fix(exchange): handle encrypted frame during server key exchange#1777

Merged
ernado merged 1 commit into
mainfrom
fix/exchange-unexpected-encrypted
Jun 14, 2026
Merged

fix(exchange): handle encrypted frame during server key exchange#1777
ernado merged 1 commit into
mainfrom
fix/exchange-unexpected-encrypted

Conversation

@ernado

@ernado ernado commented Jun 14, 2026

Copy link
Copy Markdown
Member

Problem

The server-side key-exchange read path treated every frame it read as an unencrypted exchange message. When a client reuses an already-established auth key on a connection the server still considers to be performing key exchange, the caller could not distinguish this from a malformed message and would typically reply auth_key_not_found (-404).

Clients such as Telegram Desktop treat a -404 on a temporary key as "key destroyed", discard the key and re-run key exchange — producing a reconnect/key-exchange storm (hundreds of connect/exchange/disconnect cycles per second, with the client logging -404 error received ... with temporary key, assuming it was destroyed).

Fix

On the server side, detect a non-zero leading auth_key_id while reading an unencrypted exchange message and return the raw frame as a new exported error type, *exchange.UnexpectedEncryptedError, instead of failing the exchange.

This lets the caller resolve the key and dispatch the frame as a normal encrypted message (or reply -404 only when the key is genuinely unknown), rather than blindly tearing down a still-valid key.

Verification

Wired into a downstream MTProto server (gotd/teled) via replace, rebuilt and restarted against a live Telegram Desktop client:

  • Before: continuous storm — hundreds of Client connected / Key exchange failed: EOF per second; client logged 185 -404 ... temporary key ... destroyed.
  • After: 0 -404 sent, 0 key-exchange failures, ~12 stable connections, normal RPC traffic; client resumed normal sync.

Adds TestServerUnexpectedEncrypted covering the new behavior.

The server key-exchange read path treated every frame it read as an
unencrypted exchange message. When a client reuses an already-established
auth key on a connection the server still considers to be performing key
exchange, the caller could not tell this apart from a malformed message
and would typically reply auth_key_not_found (-404). Clients such as
Telegram Desktop treat a -404 on a temporary key as "key destroyed",
discard it and re-run key exchange, producing a reconnect/key-exchange
storm.

Detect a non-zero leading auth_key_id on the server side and return the
raw frame as the new exported UnexpectedEncryptedError, so callers can
resolve the key and dispatch the frame as a normal encrypted message
instead of failing the exchange.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ernado ernado merged commit a8dd8b8 into main Jun 14, 2026
12 checks passed
@ernado ernado deleted the fix/exchange-unexpected-encrypted branch June 14, 2026 12:37
@codecov

codecov Bot commented Jun 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.19%. Comparing base (406a51b) to head (32b5952).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
exchange/server_flow.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1777      +/-   ##
==========================================
- Coverage   71.23%   71.19%   -0.04%     
==========================================
  Files         503      503              
  Lines       23577    23585       +8     
==========================================
- Hits        16795    16792       -3     
- Misses       5550     5563      +13     
+ Partials     1232     1230       -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant