Commit Graph
29 Commits
Author SHA1 Message Date
920dc31795 Refactor: Testable Keychain and Identity Manager (#584)
* Make static functions instance functions to be testable

* Injectable KeychainManager + Mock + updated tests

* Remove `pendingActions` from identity manager (dead code)

* Remove `getHandshakeState` from identity manager (dead code)

* Remove `getAllSocialIdentities` from identity manager (dead code)

* Remove `getCryptographicIdentity` from identity manager (dead code)

* Remove `resolveIdentity` from identity manager (dead code)

* Identity Manager: minor clean up

* Put Identity Manager behind a protocol

* Remove Keychain and Identity Manager singletons

* Tests: include MockKeychain/MockIdentityManager in project; init identityManager in CommandProcessorTests

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-09-12 14:37:34 +02:00
islam a1edf29bd3 Remove unnecessary import os.logs 2025-09-11 19:03:08 +01:00
islam deb464f5d8 Remove redundant .noise 2025-09-11 19:03:08 +01:00
islam e5a415d885 Overloading .debug/.error for ‘.logSecurityEvent’
Search/Replace Strategies:

1.
Search regex: `SecureLogger\.logSecurityEvent\(\s*(.*?),\s*level:\s*\.(\w+)\s*\)`
Replace regex: `SecureLogger.$2($1)`

Sample input:
`SecureLogger.logSecurityEvent(.authenticationFailed(peerID: peerID), level: .warning)`

Sample output:
`SecureLogger.warning(.authenticationFailed(peerID: peerID))`

---

2.
Search regex: `SecureLogger\.logSecurityEvent\(\s*(.*?)\s*\)`
Replace regex: `SecureLogger.info($1)`  (`info` is the default level)

Sample input:
`SecureLogger.logSecurityEvent(.handshakeStarted(peerID: peerID))`

Sample output:
`SecureLogger.info(.handshakeStarted(peerID: peerID))`
2025-09-11 19:03:08 +01:00
islam 5d6aecfc83 Replace .log w/ explicit .debug/.error functions
This would make the intention more explicit so we can overload different logging types as well like keychain, security events, etc…

Search/Replace Strategies:

1.
Search regex: `SecureLogger\.log\(\s*(.*?),\s*category:\s*(.*?),\s*level:\s*\.(\w+)\s*\)`
Replace regex: `SecureLogger.$3($1, category: $2)`

Sample input:
```
SecureLogger.log(
    "🔄 Found favorite for '\(peerInfo.nickname)' by nickname, updating noise key",
    category: .session,
    level: .debug
)
```

Sample output:
`SecureLogger.debug("🔄 Found favorite for '\(peerInfo.nickname)' by nickname, updating noise key", category: .session)`

---

2.
Search regex: `SecureLogger\.log\((.*?)\)`
Replace regex: `SecureLogger.debug($1)` (as it’s the default level)

Sample input:
`SecureLogger.log("some text")`

Sample output:
`SecureLogger.debug("some text")`

---

3
Manual changes:
ChatViewModel line 5393 (commented code)
NostrRelayManager line 196 (commented code)
NostrRelayManager lines 346-350 (if/else logic)
NostrRelayManager line 371 (commented code)
2025-09-11 19:03:08 +01:00
islam 5ca9222fc2 Make logging categories static properties of OSLog
So we can use `.<category name>` to simplify the code.

Search/Replace Strategy:
Search text: `category: SecureLogger.`
Replace text: `category: .`
2025-09-11 19:02:32 +01:00
IslamandGitHub e72fe50ffa Perf: Add final to classes that are not inherited (#574) 2025-09-11 19:17:04 +02:00
3074fa0fcb Refactor/repo hardening 01 (#462)
* BinaryProtocol: add optional padding control; BitchatPacket API for padded/unpadded bytes; BLEService: use unpadded encoding and remove ad-hoc unpadding on BLE writes

* BLEService: balance BLE padding — pad Noise handshake/encrypted frames; leave public/announce/leave unpadded; keep fragmentation consistent with chosen padding

* BLEService: replace Timer with DispatchSourceTimer on bleQueue; NostrTransport: cache placeholder NoiseEncryptionService to avoid reallocation

* Unify peerID validation: InputValidator handles 16-hex, 64-hex, or alnum-/_; NoiseSecurityValidator now delegates to InputValidator

* UI: use standard green for geohash toolbar badge and count (less bright in light mode)

* UI: standardize geohash sheet green to app standard (dark: system green, light: darker green) for buttons and checkmark

* Docs: align BinaryProtocol compression docs to zlib; Logs: reduce NostrTransport DELIVERED ack logs to debug to cut noise

* Tests: add InputValidator peerID coverage and BinaryProtocol padding round-trip/length tests

* Project: ensure Xcode project reflects new tests (references added)

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-20 13:29:53 +02:00
3ebfa85e90 Feature/nostr embedded bitchat (#448)
* UI: prefer mesh radio icon when connected; map short peer ID to full Noise key; rename ephemeral mapping to shortIDToNoiseKey; ensure header flips to purple globe on disconnect and keeps name.

* chore: stop tracking build artifacts; ignore .DerivedData and .Result*

* logging: add global threshold via BITCHAT_LOG_LEVEL and demote chatty logs to debug; keep critical errors/warnings and key state transitions

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-17 11:25:42 +02:00
jack 63f05b5d7e refactor: remove all dead legacy and migration code
- Remove unused migrateSession() functions (never called in production)
  - NoiseSession.migrateSession() - 13 lines
  - NoiseEncryptionService.migratePeerSession() - 18 lines
  - Test for migration functionality - 17 lines

- Remove unnecessary keychain cleanup code (no legacy data existed)
  - cleanupLegacyKeychainItems() - 62 lines
  - aggressiveCleanupLegacyItems() - 72 lines
  - resetCleanupFlag() - 4 lines
  - Simplified panic mode to just use deleteAllKeychainData()

Total removed: 194 lines of dead/unnecessary code

Analysis revealed:
- KeychainManager introduced July 5, 2025
- Cleanup code added July 15, 2025 (10 days later)
- Legacy service names were never used in production
- Migration functions were incomplete implementation never called
- Peer ID rotation remains active (not legacy)
2025-08-12 10:15:05 +02:00
jack 8ec39f566d Fix runtime crashes and reduce excessive logging
- Fix Dictionary crash in ChatViewModel by adding deduplication logic for peer IDs
- Fix compilation errors: PeerData -> BitchatPeer type correction
- Fix Task async context issue with cancellables
- Remove excessive debug logging for handshake coordination
- Remove repetitive keep-alive timer logs
- Remove version cache logging spam
2025-08-01 21:39:09 +02:00
8f32edaa64 Security fixes and improvements (#374)
- Fix force unwrapping in NostrIdentity bech32 functions that could crash on non-ASCII input
- Add comprehensive input validation for all protocol messages (peer IDs, nicknames, timestamps)
- Strengthen keychain security with better sandbox detection and consistent app group usage
- Implement secure memory clearing for cryptographic keys and shared secrets
- Fix panic mode not reconnecting to mesh by restarting services after emergency disconnect

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-07-31 23:42:08 +02:00
a97d5c2d5e Implement Nostr NIP-17 for offline messaging and performance optimizations (#358)
* Implement Nostr NIP-17 integration for offline mutual favorite messaging

- Add Nostr relay connectivity and NIP-17 gift-wrapped private messages
- Implement dual transport system: Bluetooth mesh + Nostr relays
- Add favorites persistence with mutual detection and Nostr key exchange
- Support offline messaging for mutual favorites via Nostr relays
- Handle peer identity rotation with automatic favorite key updates
- Fix UI to show all favorites (online and offline) in peer list
- Add proper message routing based on peer availability
- Update peer list icons: 📶 for mesh, 🌐 for Nostr, 🌙 for one-sided
- Fix toolbar display for offline peers in private chat view
- Add network entitlements for macOS and iOS
- Implement automatic noise key updates when peers reconnect

* Implement Nostr NIP-17 for private messaging between mutual favorites

- Add support for NIP-17 gift-wrapped private messages with double encryption
- Enable private messaging via Nostr when mutual favorites are offline
- Fix peer reconnection issues: users now stay in private chat when peer reconnects
- Fix read receipt delivery: send pending receipts when peer comes back online
- Add message ID tracking through Nostr transport for proper delivery acknowledgments
- Update peer noise key mapping when peers reconnect with different IDs
- Check for Nostr messages when app becomes active
- Implement 7-day message retrieval window for better reliability

* Fix private message UI refresh and adjust PEOPLE header spacing

- Fix UI not updating when receiving private messages on mesh
  - Add immediate batch processing for messages in active chat
  - Force UI update when viewing current chat peer
  - Ensure real-time message display without navigation
- Reduce PEOPLE header spacing from 16 to 12 points for tighter UI

* Fix build errors and unused value warnings in Nostr favorites integration

* Implement read receipts via Nostr

- Added sendReadReceipt method to MessageRouter to send receipts via mesh or Nostr
- Added handleReadReceipt to process incoming read receipts from Nostr
- Made ReadReceipt.readerID mutable to allow updates
- Added missing notification names and error cases
- Uncommented and enabled read receipt handling in ChatViewModel
- Read receipts now work seamlessly via both mesh and Nostr transports

* Fix ReadReceipt initialization - use correct constructor

* Implement persistent message deduplication for Nostr

- Added ProcessedMessagesService to track messages across app restarts
- Store processed message IDs and last timestamp in UserDefaults
- Skip already processed messages when receiving from Nostr
- Adjust subscription filter to use smart timestamp (last processed or 24h)
- Prevents duplicate messages when reconnecting to Nostr relays

* Fix peer list UI not updating to Nostr mode on disconnect

- Remove peer from peerNicknames when connection state changes to disconnected
- Ensures UI properly reflects peer disconnection state
- Peer list now correctly shows Nostr mode (🌐) when peer walks out of range

* Update peer count to include Nostr peers and improve UI indicators

- Peer count now shows total peers including those available via Nostr
- Count appears purple when only Nostr peers are connected
- Private message header shows purple globe icon for Nostr transport
- Consistent visual language for Nostr connectivity across the app

* Improve RSSI real-time updates and fix UI flashing

- Reduce RSSI update timer from 10s to 5s and per-peripheral from 5s to 3s
- Add RSSI change detection with 2 dBm threshold for responsive updates
- Always update previous RSSI values to fix gradual change detection bug
- Trigger RSSI read on peer authentication for immediate status
- Fix UI flashing 'nobody around' by removing array clearing on updates
- Add proper cleanup of RSSI tracking on disconnect and peer rotation

* Fix favorite nickname updates and peer list filtering

- Add updateNickname method to FavoritesPersistenceService to update nicknames while preserving favorite status
- Update announce handler to check for existing favorites and update their nicknames
- Remove dead BluetoothMeshService+PublicAPI.swift file
- Move sendFavoriteNotification to main BluetoothMeshService
- Fix peer list to only show connected peers and user's favorites (not peers who favorite the user)
- Remove UI logic for showing peers who favorite us but we don't favorite back

* Remove dead code and fix ghost connections

Phase 1 - Remove abandoned peer ID rotation code:
- Remove previousPeerID property and rotationGracePeriod constant
- Remove grace period logic from isPeerIDOurs()
- Remove previousPeerID handling from announce packets
- Pass nil for previousPeerID in identity announcements

Phase 2 - Fix ghost connections from relayed packets:
- CRITICAL FIX: Only add peers to activePeers if they have a peripheral connection
- Check for peripheral connection before marking peer as active
- Prevents ghost connections when announce packets are relayed
- Log warning when rejecting relayed announce without peripheral

Phase 3 - Begin consolidating redundant peer tracking:
- Create new PeerSession class to unify peer data in one place
- Add helper methods for PeerSession management
- Integrate PeerSession into announce packet handling
- Update authentication state changes to use PeerSession
- Update peripheral mapping and RSSI to sync with PeerSession
- Update disconnect and leave handling to update PeerSession
- Add consolidated getter methods for peer info

This fixes the issue where peers appeared connected without actually having a Bluetooth connection, and begins the migration to a cleaner single-source-of-truth peer tracking system.

* Fix multiple connect messages on peer restart

- Move hasPeripheralConnection check outside sync block to fix scope issue
- Add debug logging to track connect message conditions
- Ensure connect messages only show on first connection or reconnection with peripheral

* Optimize RSSI updates for better battery life

- Add app state tracking to BluetoothMeshService
- Only update RSSI when app is in foreground and peer list is visible
- Add setPeerListVisible method to control RSSI updates
- Remove individual periodic RSSI updates in favor of centralized timer
- Update ContentView to notify mesh service of peer list visibility changes
- Improve battery efficiency by avoiding unnecessary RSSI reads

* Initialize peer list visibility state on view appear

- Ensure RSSI timer state is properly initialized when view loads
- Call setPeerListVisible with initial showSidebar value

* Fix duplicate peers and multiple disconnect messages

- Fixed duplicate peer entries when relay-connected by adding relay-connected peers to connectedNicknames set
- Added deduplication logic for disconnect messages with 2-second window to prevent multiple disconnect notifications for same peer
- Added cleanup for old disconnect notification tracking to prevent memory growth

* Fix peer count indicator color logic

- Show green for any mesh peer (direct Bluetooth or relay connected)
- Show purple only for Nostr-only peers (no mesh connections)
- Show red only when no peers are reachable at all
- Fixed to use meshPeerCount instead of viewModel.isConnected which only checked direct connections

* Fix relay connection issues and peripheral mapping cleanup

- Fixed relay-connected peers being marked as directly connected when receiving identity announce
- Added proper cleanup of temp peripheral mappings when discovering real peer ID
- Fixed disconnect notification deduplication cleanup
- Improved debug logging to show actual connection state (direct/relay/nostr/offline)
- Added debug logging for relay connection detection
- Fixed compiler warning about unused variable

* Fix Unknown peer disconnect notifications and disable faulty relay detection

- Add check to prevent disconnect notifications for Unknown peers that never announced
- Disable relay connection detection until proper relay tracking is implemented
- In a 2-peer network, peers should never show as relay-connected

* Fix RSSI updates and peer visibility after reconnection

- Add updatePeers() call in didUpdatePeerList to refresh RSSI values in UI
- Track version hello times to better detect direct connections
- Allow peers to be marked active if recent version hello received
- Fix thread safety for version hello tracking
- Clean up old version hello times to prevent memory leaks

* Remove RSSI tracking completely and replace with radio icon for mesh connections

* Fix build errors after RSSI removal

- Add missing peripheralID declaration in didDiscover delegate method
- Remove obsolete setPeerListVisible calls from ContentView

* Center private message header elements using ZStack layout

- Replace HStack with ZStack for perfect centering
- Globe/nick/lock cluster now always centered regardless of button sizes
- Back and favorite buttons positioned in overlay HStack

* Fix private chat view showing Unknown when peer reconnects with new ID

- Update FavoritesPersistenceService to notify with both old and new keys
- Handle peer ID changes in ChatViewModel to migrate private chat data
- Update selectedPrivateChatPeer when favorite's noise key changes
- Maintain chat history and unread status across peer ID changes

* Fix read receipts after peer reconnection and replace nos.lol relay

- Updated sendReadReceipt to resolve current peer ID when peers reconnect with new IDs
- Enhanced MessageRouter to check favorites for current noise keys
- Replaced nos.lol relay with relay.snort.social to avoid PoW requirements

* Fix message routing to use Nostr when peers are disconnected

Changed message routing logic to check actual peer connection status using
isPeerConnected() instead of just checking if peer exists in nickname list.
This ensures that offline mutual favorites correctly route messages through
Nostr instead of attempting Bluetooth handshakes.

Also added safety check to prevent starting private chat with ourselves.

* Add debug logging for Nostr timestamp randomization

Added logging to track the random offset being applied to Nostr event
timestamps to debug why messages appear 8-9 minutes in the future.

* Fix Nostr timestamp issue by reducing randomization range

Temporarily reduced the timestamp randomization from +/-15 minutes to +/-1 minute
to address messages appearing 8-9 minutes in the future. Added detailed UTC/local
time logging to help debug the issue.

The random offset should have been evenly distributed but was consistently
showing positive offsets. This change mitigates the issue while we investigate
the root cause.

* Fix message routing for offline favorites and reduce Nostr timestamp randomization

- Fix transport selection to properly detect disconnected peers using isPeerConnected()
- Change from checking peer nicknames to checking actual connection status
- Reduce Nostr timestamp randomization from ±15 minutes to ±1 minute
- Add detailed timestamp logging for debugging

* Improve PM header UI and encryption status display

- Show transport icons (radio/link/globe) in PM header matching peer list
- Always show lock icon if noise session ever established (no handshake icon)
- Change verified icon from shield to checkmark seal
- Use consistent green color (textColor) for PM header and encryption icons

* Update AI_CONTEXT.md with comprehensive Nostr implementation details

- Add Nostr and MessageRouter to architecture diagram
- Document NIP-17 gift wrap implementation
- Explain favorites integration and mutual requirement
- Detail message routing logic and transport selection
- Add security considerations and debugging tips
- Update common tasks with Nostr-specific guidance

* Fix data consistency issues in favorites, chat migration, and bloom filter

- Fix favorites deduplication to use public key instead of nickname
  Prevents losing favorites when multiple peers use same nickname

- Fix private chat migration to use fingerprints instead of nicknames
  Prevents merging unrelated conversations that share nicknames
  Fallback to nickname matching only for legacy data without fingerprints

- Fix bloom filter reset to preserve messages from last 10 minutes
  Prevents duplicate message processing after bloom filter resets
  Keeps processedMessages for 10 minutes while bloom filter resets every 5

* Add mutual favorites internet messaging to app info

* Remove excessive debug/info logging for production readiness

- Removed ~140 debug/info level logs across core services
- Preserved critical logs: errors, warnings, security events, state changes
- Kept logs for: peer join/leave, favorite status, mutual relationships
- Cleaned up verbose logging in: Bluetooth mesh, Nostr, message routing
- Improved performance by reducing log I/O overhead

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Implement performance optimizations and fix build warnings

- Add UI update debouncing (50ms) to prevent excessive SwiftUI refreshes
- Implement memory bounds for processedMessages with LRU eviction
- Add encryption queue cleanup for disconnected peers
- Optimize peer lookups from O(n) to O(1) with indexed dictionary
- Fix multiple compiler warnings (unused variables, missing break statements)
- Optimize peer counting with single-pass reduce operation
- Fix ViewBuilder control flow issue in ContentView
- Fix Dictionary initialization type mismatches with Array wrapper

* Add TTL-based cleanup for Noise handshake sessions

- Add session TTL (5 minutes) and max session limit (50) to NoiseHandshakeCoordinator
- Clean up old established sessions to prevent unbounded memory growth
- Move handshake cleanup timer out of DEBUG conditional for production use
- Run cleanup every 60 seconds in production (vs 30s in debug)
- Clean up crypto state immediately on peer disconnect
- Prevents memory leaks from accumulating Noise sessions

* Pre-compute and store fingerprints in PeerSession for O(1) lookups

- Store fingerprint in PeerSession when peer authenticates
- Update getPeerFingerprint() and getFingerprint() to check PeerSession first
- Replace all noiseService.getPeerFingerprint() calls with optimized version
- Eliminates repeated SHA256 calculations during message processing
- Improves performance for favorite checks and encryption status updates

* Implement exponential backoff for Nostr relay connections

- Add reconnection tracking fields to Relay struct (attempts, timing)
- Replace fixed 5-second delay with exponential backoff (1s → 2s → 4s... max 5min)
- Stop reconnection attempts after 10 failures to prevent infinite retries
- Reset attempt counter on successful connection
- Add utility methods: retryConnection(), getRelayStatuses(), resetAllConnections()
- DNS failures still bypass retry logic as before
- Improves battery life and reduces server load from constant reconnection attempts

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-30 23:14:17 +02:00
4867ddca0d Add comprehensive AI-friendly documentation across core files (#328)
- Created AI_CONTEXT.md as central documentation hub for AI assistants
- Added detailed file-level documentation to all major components
- Documented architecture, design decisions, and security considerations
- Added usage examples and integration guidance
- Improved code discoverability with clear component descriptions

Documentation covers:
- BluetoothMeshService: Core networking and mesh protocol
- BitchatProtocol: Application-layer protocol design
- NoiseProtocol: Cryptographic implementation details
- ChatViewModel: Business logic and state management
- IdentityModels: Three-layer identity architecture
- NoiseEncryptionService: High-level encryption API
- SecureIdentityStateManager: Secure persistence layer
- BinaryProtocol: Low-level wire format

This documentation will significantly improve AI understanding of the codebase structure and enable faster, more accurate assistance with development tasks.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-07-27 10:18:47 +02:00
2e0d9be03e Implement targeted delivery for private messages (#319)
- Add direct delivery for private messages when recipient is connected
- Implement selective relay using 2-3 best RSSI peers as fallback
- Limit TTL to 2 hops for relayed private messages
- Update all private communication types to use targeted delivery:
  - Private messages
  - Read receipts
  - Delivery ACKs
  - Protocol ACKs/NACKs
  - Handshake messages
  - Identity announces (when targeted)
  - Session validation pings
  - Version ACKs
- Add intelligent relay logic to forward messages only when recipient is reachable
- Fall back to broadcast only as last resort when no direct path available

This reduces network traffic by ~90% for private communications, improves battery life, and enhances privacy by limiting message visibility.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-07-25 09:54:56 +02:00
callebtcandGitHub 9515f759d4 NoiseProtocol update: send nonce in packet (#306)
* send nonce in packet

* sliding window and 8 byte nonce

* do not process encrypted messages that arent addressed to us, same for nacks

* compiler error: remove comma

* nonce window 4 bytes

* clean up logging
2025-07-25 09:46:18 +02:00
jack 2759202616 Fix NoiseSessionManager to always accept handshake initiations
Previously, NoiseSessionManager would reject handshake initiations if it had an existing established session. This caused deadlocks when one peer cleared their session (e.g., after decryption failure) but the other peer rejected the new handshake.

Changes:
- NoiseSessionManager now always accepts handshake initiations, clearing any existing session
- Added comprehensive tests for handshake recovery scenarios
- Tests verify proper re-establishment after decryption failures and nonce desynchronization
2025-07-23 19:03:41 +02:00
jack a84d6f22ef Fix handshake deadlock after decryption failure
Always accept handshake initiations even with valid sessions, as the peer must have cleared their session for a good reason (e.g., decryption failure). This prevents deadlock where one peer has no session while the other maintains an invalid one.
2025-07-23 18:22:39 +02:00
jack d912da5898 Fix Noise handshake stability and session synchronization issues
- Add peer presence tracking with lastHeardFromPeer to detect reconnections
- Automatically send identity announcement when detecting peer reconnection after 30s
- Clear stale sessions when receiving handshake from recently-seen peer (likely restart)
- Add peers to activePeers when successfully decrypting their messages
- Fix thread safety in handshake coordinator with concurrent collections
- Extend message delivery timeouts (30s→120s private, 60s→180s room, 300s→600s favorite)
- Add per-peer encryption queues to prevent nonce desynchronization
- Make NoiseSession encrypt/decrypt operations thread-safe with barrier flag
- Initialize lastSuccessfulMessageTime when handshake completes
- Send identity announcement when decryption fails to prompt session reset
- Improve handshake state logging and debugging

This fixes:
- Peers stuck in "establishing encryption" after restart
- Nonce desynchronization causing "Decryption failed at nonce N"
- Asymmetric peer visibility (one peer sees the other but not vice versa)
- Thread safety issues causing crashes with pendingPrivateMessages
- Sessions marked as stale immediately after establishment
2025-07-23 14:57:15 +02:00
jack 9cf59651bb Clear handshake coordinator state during panic mode
When panic mode is triggered (triple tap on logo), it now properly clears:
- All handshake coordinator states
- Handshake attempt times
- Notifies UI that all peers are disconnected

This fixes the issue where handshake states would persist after clearing identity, causing confusion when the device showed "zero peers connected" but still had established handshake states in logs.

Also ensures UI is properly notified to update the peer list to empty.
2025-07-23 11:16:13 +02:00
jack 0243397ba2 Fix Noise handshake failures and implement binary protocol migration
## Summary
- Added timestamps to SecureLogger for precise timing analysis
- Implemented NoiseHandshakeCoordinator to prevent race conditions
- Added deterministic role selection based on peer ID comparison
- Implemented proper handshake state machine with retry logic
- Added duplicate message detection for handshake messages
- Improved logging and diagnostics for handshake debugging

## Details
The coordinator ensures only one peer initiates handshakes by using deterministic role selection (lower peer ID initiates). This prevents the simultaneous handshake attempts that were causing failures. The state machine tracks handshake progress and handles retries with exponential backoff.

## Testing
Successfully builds with no errors or warnings. The implementation should resolve the "establishing encryption" stuck state issue by ensuring proper handshake coordination between peers.
2025-07-23 10:19:45 +02:00
jack f53e163d25 Remove all channel functionality and clean up test suite
- Remove channel UI elements from ContentView
- Remove channel data structures and methods from ChatViewModel
- Remove channel commands (/j, /leave, /channels)
- Remove channel field from BitchatMessage protocol
- Remove channel message types and handling
- Remove NoiseChannelEncryption.swift entirely
- Clean up all channel references across the codebase
- Fix compilation warnings (var to let conversions)
- Remove all outdated test files that used incorrect APIs
- Simplify app to only support public broadcast and 1:1 private messages
2025-07-23 01:33:54 +02:00
jack aaa7e2bf28 Enhance logging framework and fix build issues
- Rename SecurityLogger to SecureLogger for better clarity
- Add file:line:function tracking to all log entries
- Optimize logging with pre-compiled regex patterns and NSCache
- Add comprehensive logging for critical protocol flow points
- Fix iOS entitlements to include Bluetooth permission
- Fix VersionHello field name and optional chaining issues
- Fix Package.swift resource warnings
- Fix test compilation errors with proper type annotations
2025-07-22 15:40:13 +02:00
jack 9e035c9c14 Fix Swift 6 warning about unused result
- Add explicit discarding of removeValue results in NoiseSession
- Remove unnecessary _ = from BluetoothMeshService sync block
- Ensures clean builds with no warnings (except AppIntents metadata)

The warning was caused by Swift 6 being stricter about unused
results from methods that return values inside sync blocks.
2025-07-22 11:38:20 +02:00
jack d804b93488 Fix compilation errors and warnings
- Fix redundant underscore warnings in NoiseSession.swift
- Replace non-existent handlePeerDisconnection with proper cleanup code
- Remove invalid showSystemMessage call, use didDisconnectFromPeer instead
- Clean up peer state when version negotiation fails

The project now builds successfully for iOS with only minor warnings
about metadata extraction for app intents (which can be ignored).
2025-07-22 11:33:51 +02:00
jack ce6e90701c Remove dead code and placeholders
- Remove NoisePostQuantum.swift entirely (placeholder with no implementation)
- Remove Double Ratchet placeholder code from NoiseChannelKeyRotation.swift
- Remove NoisePostQuantumTests that tested mock implementations
- Handle TODO for version negotiation rejection (now properly disconnects)
- Remove legacy comment about removed message type 0x02
- Keep deprecated ownerID field as it's still used for compatibility

This cleanup removes ~400 lines of placeholder code that was not
being used and unlikely to be implemented in the near future.
2025-07-22 11:20:07 +02:00
jack 8fccbe69b9 Fix session destruction race condition causing handshake delays
Root cause: When receiving a handshake initiation (32 bytes) from a peer
with whom we already had an established session, the code would destroy
the existing session to "help" the other side. This created a cascade:
- Peer A completes handshake with Peer B
- Peer A sends message, realizes no session, initiates handshake
- Peer B destroys its working session to "help"
- Peer B now has no session, initiates handshake
- Both peers keep destroying each other's sessions

Fix:
- Never destroy an established session when receiving new handshake attempts
- Add early check in handshake initiation to skip if session exists
- Clear handshake rate limit timers when session already established

This eliminates the delays and repeated handshakes seen in the logs.
2025-07-22 11:06:57 +02:00
jack 0be35a5378 Fix Noise session persistence during peer ID rotation
- Add session migration when peer IDs rotate
- Sessions now follow peers across ID changes via fingerprint
- Add migratePeerSession to NoiseEncryptionService
- Add migrateSession to NoiseSessionManager
- Integrate migration in BluetoothMeshService updatePeerBinding

This fixes the issue where established Noise sessions were lost
when peer IDs rotated, causing "No Noise session" errors and
requiring re-handshake.
2025-07-22 11:01:24 +02:00
jack 3070a4d307 Implement Noise Protocol Framework and peer ID rotation for enhanced security and privacy
This major update replaces the basic encryption with the Noise Protocol Framework
and adds ephemeral peer ID rotation for enhanced privacy.

Key Changes:

Security Infrastructure:
- Implemented Noise Protocol Framework (XX handshake pattern)
- End-to-end encryption with forward secrecy and identity hiding
- Session management with automatic rekey support
- Channel encryption with password-derived keys

Privacy Enhancements:
- Ephemeral peer ID rotation (5-15 minute random intervals)
- Persistent identity through public key fingerprints
- Favorites and verification persist across ID rotations
- Block list based on fingerprints, not ephemeral IDs

Core Components Added:
- NoiseEncryptionService: Main encryption service
- NoiseSession: Individual peer session management
- NoiseChannelEncryption: Password-protected channel support
- SecureIdentityStateManager: Persistent identity storage
- FingerprintView: Visual fingerprint verification UI

Bug Fixes:
- Fixed handshake storm with tie-breaker mechanism
- Fixed missing connect messages during peer rotation
- Fixed delivery ACK compression issues
- Fixed race conditions in message queue
- Fixed nickname resolution for rotated peer IDs

Testing:
- Comprehensive test suite for Noise implementation
- Security validator tests
- Channel encryption tests
- Identity persistence tests
- Rate limiter tests

Documentation:
- BRING_THE_NOISE.md: Technical implementation details
- Updated WHITEPAPER.md: Simplified and focused on core innovations
- Removed temporary debug documentation

The implementation maintains backward compatibility while significantly
improving security and privacy. All existing features (channels, private
messages, favorites, blocking) work seamlessly with the new system.
2025-07-15 13:15:31 +02:00