rustdesk/rustdesk · critical
WebRTC peer identity could not be verified (refusing unbound
Error message
WebRTC peer identity could not be verified (refusing unbound channel)
What it means
In secure_connection(), if the SignedId payload cannot be decoded/verified under the trusted signing key (the outer `else` of the decode), a non-WebRTC transport falls back to a non-secure connection. A WebRTC transport cannot safely do that without identity binding, so it refuses the unbound channel and raises this error instead.
Source
Thrown at src/client.rs:1678
create_symmetric_key_msg(their_pk_b);
let mut msg_out = Message::new();
msg_out.set_public_key(PublicKey {
asymmetric_value,
symmetric_value,
..Default::default()
});
timeout(CONNECT_TIMEOUT, conn.send(&msg_out)).await??;
conn.set_key(key);
} else {
if is_webrtc {
bail!("WebRTC handshake id mismatch (possible MITM)");
}
log::error!("Handshake failed: sign failure");
conn.send(&Message::new()).await?;
}
} else {
if is_webrtc {
bail!("WebRTC peer identity could not be verified (refusing unbound channel)");
}
// fall back to non-secure connection in case pk mismatch
log::info!("pk mismatch, fall back to non-secure");
let mut msg_out = Message::new();
msg_out.set_public_key(PublicKey::new());
conn.send(&msg_out).await?;
}
} else {
if is_webrtc {
bail!("WebRTC handshake received an unexpected message type");
}
log::error!("Handshake failed: invalid message type");
conn.send(&Message::new()).await?;
}
} else {
if is_webrtc {
bail!("WebRTC handshake received a malformed message");
}View on GitHub (pinned to 91c9fccbb0)
Solutions
- Align the client's configured `key` with the server's actual signing public key
- Upgrade the remote peer/client to compatible versions so SignedId verifies
- Verify rendezvous/relay infrastructure integrity (tampering produces unverifiable blobs)
- Retry after server key rotation completes on both ends
Example fix
// before --key <stale-key> // after --key <current server signing key> // SignedId then verifies and WebRTC channel is bound
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check that a signing key is configured so SignedId can verify
if get_rs_pk(key).is_none() {
eprintln!("No valid signing key: WebRTC identity verification will refuse the channel");
} Try / catch
match Client::connect(...).await {
Err(e) if e.to_string().contains("peer identity could not be verified") => {
// fix key config / versions before retrying
}
r => r?,
} Prevention
- Keep the client `key` equal to the server's signing public key
- Upgrade both endpoints in lockstep to keep crypto compatible
- Audit relay infrastructure for tampering if failures persist
When it happens
Trigger: `is_webrtc` is true and `decode_id_pk_dtls(&si.id, &sign_pk)` failed (or an earlier arm left identity unverified) — the peer's signed identity blob did not verify under the configured rs_pk/sign_pk.
Common situations: Client key mismatch with the server's signing key; corrupted SignedId payload from a relay; peer running incompatible crypto or a tampered server; MITM replacing the SignedId blob.
Related errors
- WebRTC handshake id mismatch (possible MITM)
- WebRTC local DTLS fingerprint unavailable
- e
- WebRTC DTLS fingerprint unavailable
- WebRTC DTLS fingerprint not bound to peer identity (possible
AI-assisted analysis of rustdesk/rustdesk@91c9fccbb0 (2026-09-10).
Data as JSON: /api/errors/887affba3e3bb503.
Report an issue: GitHub.