mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-08-29 07:27:16 +00:00
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d5cf64f99e
|
Require signed sender for broadcast file transfers (#1406 follow-up) (#1407)
* Require signed sender for broadcast file transfers (#1406 follow-up) Broadcast file transfers trusted the packet's claimed senderID whenever the peer was merely connected (resolveKnownPeer allowConnectedUnverified: true), unlike public messages and public voice frames, which both require a valid packet signature from the claimed sender. Codex flagged the consequence on PR #1406: a peer that observed a public voice burst could broadcast a spoofed voice_<burstID>.m4a note under the talker's senderID, and ChatLiveVoiceCoordinator.absorbFinalizedVoiceNote would replace the signature-verified live bubble with attacker audio (senderPeerID + scope were the only bindings, both attacker-forgeable on this path). Bring broadcast file transfers up to the same bar as public messages: verify the packet signature against the registry signing key, falling back to the persisted-identity signature lookup, before trusting the sender. Directed (private) transfers keep the lenient connected-peer path — they are addressed to us specifically and carry no broadcast exposure. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Exempt self broadcasts from the file-transfer signature gate Review of #1407 caught a regression: our own broadcast files replayed via gossip sync arrive with ttl==0 (so isSelfEcho does not drop them) and cannot be verified against the peer registry or identity cache, so the new broadcast signature guard would drop them. Mirror BLEPublicMessageHandler's self exemption — self packets are trivially authentic — and add a regression test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Stop relaying broadcast file packets that fail sender authentication Codex review on #1407: the new signature gate dropped spoofed broadcast files locally, but BLEService's .fileTransfer case still fell through to scheduleRelayIfNeeded, so a forged file kept propagating to downstream (possibly older, ungated) nodes. Have the handler report failed sender authentication and skip the relay step, like invalid board posts and voice frames. Local-only drops (malformed payload, quota, save failure) and files directed to other peers still relay unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Fix CI hang: sign the max-size reassembly file transfer, unhang timeouts Both CI runs on #1407 died at the 5-minute watchdog (SIGKILL, exit 137) with the test process fully idle. Root cause was a pair of issues in FragmentationTests: - "Max-sized file transfer survives reassembly" injected an UNSIGNED broadcast file from an unknown peer, which the new broadcast signature gate now drops by design. Sign the packet and preseed the sender's signing key, mirroring the public-message reassembly tests. - CaptureDelegate's wait helpers could never time out: the timeout task threw, but withThrowingTaskGroup then awaited the sibling child that was parked in a non-cancellable withCheckedContinuation, deadlocking the whole run (hang instead of a 5s failure). Resume the parked continuation from a cancellation handler so timeouts now fail fast. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
35fb9fdd42
|
Fix received DM images stuck as grey box: stamp incoming media delivered, reveal tap as Button (#1402)
* Make image tap-to-reveal a Button so the DM sheet can't swallow it Received images in a DM rendered as a grey "tap to reveal" box that never revealed: the DM sheet wraps the whole conversation in a high-priority swipe-to-close DragGesture (ContentSheetViews), and an ancestor high-priority gesture starves descendant TapGestures — the image's reveal/open tap never fired. Button actions survive that suppression (the sheet's own header buttons work for the same reason), so the tap now lives on a plain-style Button wrapping the image; swipe-to-hide stays attached as a simultaneous gesture. Fixes #1388 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Move the cancel control out of the reveal Button Nested buttons don't get reliable independent hit testing, and the outer reveal tap is a no-op while sending, so the in-flight cancel x could become untappable. The cancel overlay now sits on the Button rather than inside its label. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Root cause: received media stuck in .sending — grey box, dead tap Field testing showed the Button conversion alone didn't fix #1388: a received DM image still rendered as a flat grey box with a dead tap. The real culprit is BitchatMessage's initializer, which defaults every private message without an explicit status to `.sending`. BLEFileTransferHandler built incoming media messages without one, so every received private image/voice note was permanently "sending": mediaSendState returned progress 0 → BlockRevealMask rendered 0% of the image (the flat grey box is the blur overlay over an empty mask), and the reveal tap was disabled by the isSending guard — regardless of which gesture carried it. Two layers: - BLEFileTransferHandler now stamps incoming private media `.delivered(to: <local nickname>, at: <packet time>)`, matching the received-text path in ChatPrivateConversationCoordinator. - MediaMessageView treats received messages as never-sending, so no other construction path can reproduce the grey-box state. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3a995e20b6 |
Extract BLE packet handlers and migrate coordinators to narrow contexts
BLEService's per-packet-type orchestration moves into owned, tested components (BLEAnnounceHandler, BLEPublicMessageHandler, BLENoisePacketHandler, BLEFileTransferHandler, BLEFragmentHandler), each taking an environment struct of closures so every queue hop stays in BLEService and the handlers are synchronously testable. Behavior is preserved verbatim, including Noise session recovery on decrypt failure and single-block UI event ordering. handleLeave/handleRequestSync stay in place as already-thin delegations. BLEService drops to 3393 lines. Four coordinators (delivery, private conversation, Nostr, public conversation) drop their unowned/weak ChatViewModel back-references for narrow @MainActor context protocols, with ChatViewModel conformances as single shared witnesses for overlapping members. Their true coupling is now an explicit, reviewable surface, and each gains a mock-context test suite covering flows previously testable only through the full view model. Delivery/read acks now also clear the router's retained-send outbox via the delivery context. New LargeTopologyTests exercise production-shaped meshes with the in-memory harness: an 8-peer relay chain with per-hop TTL decay, a 14-peer cyclic mesh with exactly-once delivery, partition/heal, and topology churn. App-layer runtime/model files updated alongside. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |