Skip to content

Replace custom WebRTC encryption with invite-authenticated signaling - #488

Merged
muke1908 merged 4 commits into
masterfrom
copilot/custom-encryption-webrtc-audio-call
Aug 29, 2026
Merged

Replace custom WebRTC encryption with invite-authenticated signaling#488
muke1908 merged 4 commits into
masterfrom
copilot/custom-encryption-webrtc-audio-call

Conversation

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

WebRTC already encrypts peer-to-peer media with DTLS-SRTP, while unauthenticated signaling still allowed SDP substitution. This change moves trust to a client-generated invite secret and removes redundant media encryption.

  • Invite security

    • Generate a 256-bit client-side secret.
    • Encode room and secret in a URL fragment:
      #room=<public-room-id>&secret=<base64url-secret>
      
    • Send only the public room ID to the server.
    • Remove PIN-based joining.
  • End-to-end signaling and chat

    • Derive separate signaling and chat keys with HKDF-SHA-256.
    • Encrypt payloads with AES-256-GCM using version and room as authenticated data.
    • Reject invalid versions, tampering, wrong-room payloads, and replays without plaintext fallback.
  • Opaque relay

    • Move chat and WebRTC signaling to socket-bound relay events.
    • Stop trusting client-provided sender and room fields after joining.
    • Add payload-size and per-socket rate limits.
    • Remove obsolete key-exchange and signaling endpoints.
  • WebRTC simplification

    • Rely on native DTLS-SRTP for media encryption.
    • Remove encoded-frame transforms, workers, browser capability gates, and associated key handling.
  • Lifecycle

    • Clear invite-derived keys and replay state when deleting or disposing of a channel.
    • Update client flows, public SDK types, tests, and security documentation for secret-bearing invitations.

Copilot AI and others added 2 commits August 29, 2026 12:25
…, remove RSA/PIN/encoded-transforms

Co-authored-by: muke1908 <20297989+muke1908@users.noreply.github.com>
Co-authored-by: muke1908 <20297989+muke1908@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The client currently acknowledges delivered before decrypting/replay-checking incoming envelopes and raw socket handlers lack error isolation, which can produce incorrect delivery signals and unhandled exceptions.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR redesigns the chat + WebRTC call security model by removing the prior RSA/AES key-exchange and custom per-frame media encryption, replacing it with invite-secret–derived AEAD envelopes for all signaling and chat while relying on WebRTC’s native DTLS-SRTP for media.

Changes:

  • Introduces client-generated invite secrets and derives chat/signaling keys via HKDF-SHA-256; seals all payloads in a versioned, room-bound AES-GCM envelope.
  • Moves chat + WebRTC signaling onto socket relay events with server-side size checks and per-socket token-bucket rate limiting; removes legacy REST endpoints and PIN-based joining.
  • Removes encoded-frame transform infrastructure (workers, codecs, capability gates) and simplifies WebRTC support detection.
File summaries
File Description
service/src/webrtc/webrtcCall.ts Simplifies call construction and WebRTC support detection; injects signaling sender.
service/src/webrtc/webrtcCall.test.ts Updates tests for new constructor and isSupported() behavior.
service/src/webrtc/types.ts Removes Insertable Streams helper interfaces (no encoded transforms).
service/src/webrtc/peer.ts Removes per-frame encryption/decryption; injects async signal sender; uses standard RTCPeerConnection config.
service/src/webrtc/peer.test.ts Updates mocks/tests for injected signaling and removal of encoded transforms.
service/src/webrtc/frameData.ts Removed (no longer framing encrypted media frames).
service/src/webrtc/frameCodec.ts Removed (no longer encrypting encoded media frames).
service/src/webrtc/frameCodec.test.ts Removed (codec no longer exists).
service/src/webrtc/encodedTransformWorkerFactory.ts Removed (no worker-based script transform).
service/src/webrtc/encodedTransform.worker.ts Removed (no worker transform implementation).
service/src/webrtc/encodedTransform.ts Removed (no encoded transforms selection/installation).
service/src/webrtc/encodedTransform.test.ts Removed (encoded transforms removed).
service/src/webrtc/mocks/encodedTransformWorkerFactory.ts Removed (worker factory mock no longer needed).
service/src/utils/replayGuard.ts Adds simple per-context monotonic sequence replay protection.
service/src/utils/replayGuard.test.ts Unit tests for ReplayGuard semantics.
service/src/socket/socket.ts Adds raw encrypted message routing + ack-based emits for chat/signaling; narrows public event surface.
service/src/socket/socket.test.ts Updates socket tests for raw handlers, acks, and new join payload shape.
service/src/sdk.ts Replaces RSA-era flow with invite-derived keys + sealed envelopes; decrypts inbound envelopes and drops invalid/replays.
service/src/sdk.test.ts Updates SDK tests for invite join, envelope sealing/opening, replay dropping, and call preconditions.
service/src/public/types.ts Updates public SDK types to invite-based join and removes RSA-era APIs.
service/src/keyExchange/keyExchangeManager.ts Removed (RSA/AES handshake removed).
service/src/crypto/secureEnvelope.ts Adds versioned, room-bound AES-GCM envelope (AAD binds version+room).
service/src/crypto/secureEnvelope.test.ts Tests envelope round-trip, tamper rejection, version/room checks, malformed handling.
service/src/crypto/inviteCrypto.ts Adds invite secret generation + HKDF key derivation for chat/signaling.
service/src/crypto/inviteCrypto.test.ts Tests base64url helpers, secret entropy, HKDF determinism and domain separation.
service/src/crypto/encryptionFactory.ts Removed (pluggable RSA/AES strategy layer removed).
service/src/crypto/cryptoRSA.ts Removed (RSA helpers removed).
service/src/crypto/cryptoAES.ts Removed (legacy symmetric strategy removed).
service/src/crypto/crypto.test.ts Removed (legacy crypto tests removed).
service/src/crypto/base64url.ts Adds RFC4648 base64url helpers for secrets and envelope fields.
service/src/api/webrtcSession.ts Removed (signaling no longer over REST).
service/src/api/publicKey.ts Removed (RSA key exchange removed).
service/src/api/messages.ts Removes REST sendMessage; keeps getUsersInChannel.
service/src/api/links.ts Generates invite secret client-side and returns #room=...&secret=... fragment links.
service/README.md Updates SDK docs to invite-secret model, envelope security properties, and DTLS-SRTP media encryption.
service/jest.config.js Removes encodedTransform worker mapper exclusion; restores normal coverage collection.
service/build.js Removes worker build + URL rewrite plugin (no worker emitted).
README.md Updates top-level security/call description for invite-derived envelopes and DTLS-SRTP media.
jest.config.js Ignores Playwright e2e specs in Jest.
e2e/join-session.spec.ts Updates e2e join flow to invitation-link fragment; adds regression for missing secret.
client/src/utils/urlHash.ts Replaces simple hash helpers with invite fragment parsing + updating.
client/src/types/index.ts Updates app types for invite info; removes private key from state; updates join/create signatures.
client/src/hooks/useUrlHash.ts Tracks parsed invite fragment instead of raw hash string.
client/src/context/ChatContext.tsx Removes client-side private-key decrypt flow; joins with (roomId, secret); uses SDK plaintext callbacks.
client/src/components/SetupOverlay/SetupOverlay.tsx Updates setup UI to generate/copy/paste invitation links; validates invite input.
client/src/components/SetupOverlay/JoinHashView.tsx Join UI now accepts invitation link/fragment; auto-populates from URL fragment.
client/src/components/SetupOverlay/InitialActions.tsx Updates copy/join affordances and adds stable ids for e2e tests.
client/src/components/SetupOverlay/CreateHashView.tsx Shows invitation link instead of hash; disables next until generated.
client/src/components/common/Input.tsx Adds optional id passthrough for test selectors.
client/src/components/common/Button.tsx Adds optional id passthrough for test selectors.
client/src/components/ChatContainer/ChatHeader.tsx Adds stable id to participant info for e2e assertions.
client/src/App.tsx Setup completion now joins with (roomId, secret) and updates URL fragment accordingly.
client/README.md Updates documentation references from hash to invitation-link fragment.
client/app.ts Removed legacy vanilla TS client implementation.
backend/socket.io/rateLimiter.ts Adds in-memory token bucket rate limiter for per-socket event throttling.
backend/socket.io/rateLimiter.test.ts Unit tests for rate limiter behavior and reset.
backend/socket.io/listeners.ts Moves chat + signaling relay into socket events with size checks + rate limiting; removes trust in client sender/channel fields.
backend/socket.io/index.ts Adds envelope typing and transport-level maxHttpBufferSize; updates emitted payload shapes.
backend/README.md Updates backend docs for new socket event contract and envelope model.
backend/db/const.ts Removes unused PUBLIC_KEY_COLLECTION constant.
backend/api/messaging/types.ts Removes legacy message/public-key/webrtc types; keeps users-in-channel response type.
backend/api/messaging/index.ts Removes REST messaging + public-key endpoints; retains users-in-channel.
backend/api/index.ts Removes call/session router.
backend/api/chatHash/utils/pin.ts Removed (PIN joining removed).
backend/api/chatHash/utils/pin.test.js Removed (PIN tests removed).
backend/api/chatHash/utils/link.ts Removes PIN generation; now only returns room id + status.
backend/api/chatHash/utils/link.test.ts Updates link generation test to assert no PIN fields.
backend/api/chatHash/index.ts Removes PIN lookup route and unique-PIN recursion; simply creates room ids.
backend/api/call/session.ts Removed (REST signaling endpoint removed).
Review details
  • Files reviewed: 68/69 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +56 to 62
this.socket.on(WIRE_EVENTS.CHAT_MESSAGE, (msg: RawChatMessage) => {
this.rawHandlers.onRawChatMessage(msg);
this.markDelivered(msg);
});
this.socket.on(WIRE_EVENTS.WEBRTC_SIGNAL, (msg: RawSignalMessage) => {
this.rawHandlers.onRawWebrtcSignal(msg);
});
Comment thread service/src/socket/socket.ts Outdated
Comment on lines +47 to +50
const secretBytes = fromBase64Url(secret);
if (secretBytes.byteLength < SECRET_BYTE_LENGTH) {
throw new Error('Invalid invite secret: expected 256 bits of entropy.');
}
Co-authored-by: muke1908 <20297989+muke1908@users.noreply.github.com>
Co-authored-by: muke1908 <20297989+muke1908@users.noreply.github.com>
@sonarqubecloud

Copy link
Copy Markdown

@muke1908
muke1908 marked this pull request as ready for review August 29, 2026 20:32
@muke1908
muke1908 merged commit 563dd91 into master Aug 29, 2026
1 check passed
@muke1908
muke1908 deleted the copilot/custom-encryption-webrtc-audio-call branch August 29, 2026 20:32
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.

3 participants