From a6469a3d73c6fe5d4a26d6fca451b8f8e90f7b8a Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Mon, 21 Jul 2025 23:35:23 +0200 Subject: [PATCH] refactor but untested --- .../android/mesh/BluetoothMeshService.kt | 157 +++++++++++------- .../bitchat/android/mesh/PacketProcessor.kt | 2 +- 2 files changed, 96 insertions(+), 63 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt index 3e91d6e4..d5dc3e92 100644 --- a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt +++ b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt @@ -472,54 +472,46 @@ class BluetoothMeshService(private val context: Context) { fun sendPrivateMessage(content: String, recipientPeerID: String, recipientNickname: String, messageID: String? = null) { if (content.isEmpty() || recipientPeerID.isEmpty() || recipientNickname.isEmpty()) return - serviceScope.launch { - val nickname = delegate?.getNickname() ?: myPeerID - - val message = BitchatMessage( - id = messageID ?: UUID.randomUUID().toString(), - sender = nickname, - content = content, - timestamp = Date(), - isRelay = false, - isPrivate = true, - recipientNickname = recipientNickname, - senderPeerID = myPeerID - ) - - message.toBinaryPayload()?.let { messageData -> - try { - // Pad and encrypt - val blockSize = MessagePadding.optimalBlockSize(messageData.size) - val paddedData = MessagePadding.pad(messageData, blockSize) - val encryptedPayload = securityManager.encryptForPeer(paddedData, recipientPeerID) - - if (encryptedPayload != null) { - // Sign - // val signature = securityManager.signPacket(encryptedPayload) - - val packet = BitchatPacket( - type = MessageType.NOISE_ENCRYPTED.value, - senderID = hexStringToByteArray(myPeerID), - recipientID = hexStringToByteArray(recipientPeerID), - timestamp = System.currentTimeMillis().toULong(), - payload = encryptedPayload, - signature = null, - ttl = MAX_TTL - ) - - // Cache for offline favorites - if (storeForwardManager.shouldCacheForPeer(recipientPeerID)) { - storeForwardManager.cacheMessage(packet, messageID ?: message.id) - } - - // Send with delay - delay(Random.nextLong(50, 500)) - connectionManager.broadcastPacket(RoutedPacket(packet)) - } - - } catch (e: Exception) { - Log.e(TAG, "Failed to send private message: ${e.message}") + val nickname = delegate?.getNickname() ?: myPeerID + + val message = BitchatMessage( + id = messageID ?: UUID.randomUUID().toString(), + sender = nickname, + content = content, + timestamp = Date(), + isRelay = false, + isPrivate = true, + recipientNickname = recipientNickname, + senderPeerID = myPeerID + ) + + message.toBinaryPayload()?.let { messageData -> + try { + // Pad the message data + val blockSize = MessagePadding.optimalBlockSize(messageData.size) + val paddedData = MessagePadding.pad(messageData, blockSize) + + // Create inner packet with the padded message data + val innerPacket = BitchatPacket( + type = MessageType.MESSAGE.value, + senderID = hexStringToByteArray(myPeerID), + recipientID = hexStringToByteArray(recipientPeerID), + timestamp = System.currentTimeMillis().toULong(), + payload = paddedData, + signature = null, + ttl = MAX_TTL + ) + + // Cache for offline favorites + if (storeForwardManager.shouldCacheForPeer(recipientPeerID)) { + storeForwardManager.cacheMessage(innerPacket, messageID ?: message.id) } + + // Use the new encrypt and broadcast function + encryptAndBroadcastNoisePacket(innerPacket, recipientPeerID) + + } catch (e: Exception) { + Log.e(TAG, "Failed to send private message: ${e.message}") } } } @@ -528,34 +520,75 @@ class BluetoothMeshService(private val context: Context) { * Send delivery acknowledgment for a received private message */ fun sendDeliveryAck(message: BitchatMessage, senderPeerID: String) { - serviceScope.launch { - val nickname = delegate?.getNickname() ?: myPeerID - val ack = DeliveryAck( - originalMessageID = message.id, - recipientID = myPeerID, - recipientNickname = nickname, - hopCount = 0u // Will be calculated during relay + val nickname = delegate?.getNickname() ?: myPeerID + val ack = DeliveryAck( + originalMessageID = message.id, + recipientID = myPeerID, + recipientNickname = nickname, + hopCount = 0u // Will be calculated during relay + ) + + try { + val ackData = ack.encode() ?: return + + // Create inner packet with the delivery ACK data + val innerPacket = BitchatPacket( + type = MessageType.DELIVERY_ACK.value, + senderID = hexStringToByteArray(myPeerID), + recipientID = hexStringToByteArray(senderPeerID), + timestamp = System.currentTimeMillis().toULong(), + payload = ackData, + signature = null, + ttl = 3u ) + // Use the new encrypt and broadcast function + encryptAndBroadcastNoisePacket(innerPacket, senderPeerID) + + } catch (e: Exception) { + Log.e(TAG, "Failed to send delivery ACK: ${e.message}") + } + } + + /** + * Encrypt a BitchatPacket and broadcast it as a NOISE_ENCRYPTED message + * This is the correct protocol implementation - encrypt the entire packet, not just the payload + */ + private fun encryptAndBroadcastNoisePacket(innerPacket: BitchatPacket, recipientPeerID: String) { + serviceScope.launch { try { - val ackData = ack.encode() ?: return@launch - val encryptedPayload = securityManager.encryptForPeer(ackData, senderPeerID) + // Serialize the inner packet to binary data + val innerPacketData = innerPacket.toBinaryData() + if (innerPacketData == null) { + Log.e(TAG, "Failed to serialize inner packet for encryption") + return@launch + } + + // Encrypt the serialized packet using Noise encryption + val encryptedPayload = securityManager.encryptForPeer(innerPacketData, recipientPeerID) + if (encryptedPayload != null) { - val packet = BitchatPacket( - type = MessageType.DELIVERY_ACK.value, + // Create the outer NOISE_ENCRYPTED packet + val outerPacket = BitchatPacket( + type = MessageType.NOISE_ENCRYPTED.value, senderID = hexStringToByteArray(myPeerID), - recipientID = hexStringToByteArray(senderPeerID), + recipientID = hexStringToByteArray(recipientPeerID), timestamp = System.currentTimeMillis().toULong(), payload = encryptedPayload, signature = null, - ttl = 3u + ttl = MAX_TTL ) - connectionManager.broadcastPacket(RoutedPacket(packet)) + // Broadcast the encrypted packet + connectionManager.broadcastPacket(RoutedPacket(outerPacket)) + + Log.d(TAG, "Encrypted and sent packet type ${innerPacket.type} to $recipientPeerID (${encryptedPayload.size} bytes encrypted)") + } else { + Log.w(TAG, "Failed to encrypt packet for $recipientPeerID - no session available") } } catch (e: Exception) { - Log.e(TAG, "Failed to send delivery ACK: ${e.message}") + Log.e(TAG, "Failed to encrypt and broadcast Noise packet to $recipientPeerID: ${e.message}") } } } diff --git a/app/src/main/java/com/bitchat/android/mesh/PacketProcessor.kt b/app/src/main/java/com/bitchat/android/mesh/PacketProcessor.kt index 62038248..272ab8dc 100644 --- a/app/src/main/java/com/bitchat/android/mesh/PacketProcessor.kt +++ b/app/src/main/java/com/bitchat/android/mesh/PacketProcessor.kt @@ -39,7 +39,7 @@ class PacketProcessor(private val myPeerID: String) { Log.d(TAG, "🎭 Created packet actor for peer: $peerID") try { for (packet in channel) { - Log.d(TAG, "Processing packet type ${packet.packet.type} from $peerID (serialized)") + Log.d(TAG, "📦 Processing packet type ${packet.packet.type} from $peerID (serialized)") handleReceivedPacket(packet) Log.d(TAG, "Completed packet type ${packet.packet.type} from $peerID") }