wip noise

This commit is contained in:
callebtc
2025-07-17 11:36:40 +02:00
parent 10e5e9fff3
commit 03ac7ba09b
2 changed files with 94 additions and 37 deletions
@@ -41,6 +41,7 @@ class BluetoothMeshService(private val context: Context) {
// Core components - each handling specific responsibilities // Core components - each handling specific responsibilities
private val encryptionService = EncryptionService(context) private val encryptionService = EncryptionService(context)
private val noiseEncryptionService = com.bitchat.android.noise.NoiseEncryptionService(context)
private val peerManager = PeerManager() private val peerManager = PeerManager()
private val fragmentManager = FragmentManager() private val fragmentManager = FragmentManager()
private val securityManager = SecurityManager(encryptionService, myPeerID) private val securityManager = SecurityManager(encryptionService, myPeerID)
@@ -123,11 +124,40 @@ class BluetoothMeshService(private val context: Context) {
override fun processNoiseHandshake(peerID: String, payload: ByteArray, isInitiation: Boolean): Boolean { override fun processNoiseHandshake(peerID: String, payload: ByteArray, isInitiation: Boolean): Boolean {
return try { return try {
// For now, treat as legacy key exchange until full Noise implementation Log.d(TAG, "Processing Noise handshake from $peerID, payload size: ${payload.size} bytes")
encryptionService.addPeerPublicKey(peerID, payload)
// Use proper Noise protocol implementation
val response = noiseEncryptionService.processHandshakeMessage(payload, peerID)
if (response != null) {
// Send response back
val responsePacket = BitchatPacket(
version = 1u,
type = MessageType.NOISE_HANDSHAKE_RESP.value,
senderID = hexStringToByteArray(myPeerID),
recipientID = hexStringToByteArray(peerID),
timestamp = System.currentTimeMillis().toULong(),
payload = response,
ttl = 1u
)
connectionManager.broadcastPacket(RoutedPacket(responsePacket))
Log.d(TAG, "Sent Noise handshake response to $peerID")
}
// Check if session is now established
if (noiseEncryptionService.hasEstablishedSession(peerID)) {
Log.d(TAG, "Noise session established with $peerID")
// Get the peer's public key for fingerprinting
val peerPublicKey = noiseEncryptionService.getPeerPublicKeyData(peerID)
if (peerPublicKey != null) {
// Notify delegate about successful handshake
delegate?.registerPeerPublicKey(peerID, peerPublicKey)
}
}
true true
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Failed to process Noise handshake: ${e.message}") Log.e(TAG, "Failed to process Noise handshake from $peerID: ${e.message}")
false false
} }
} }
@@ -203,16 +233,34 @@ class BluetoothMeshService(private val context: Context) {
// Noise protocol operations // Noise protocol operations
override fun hasNoiseSession(peerID: String): Boolean { override fun hasNoiseSession(peerID: String): Boolean {
// For now, return false since we don't have full Noise implemented return noiseEncryptionService.hasEstablishedSession(peerID)
// This will be updated when NoiseEncryptionService is fully integrated
return false
} }
override fun initiateNoiseHandshake(peerID: String) { override fun initiateNoiseHandshake(peerID: String) {
// For now, send a basic key exchange instead of full Noise handshake try {
// This will be updated when NoiseEncryptionService is fully integrated // Initiate proper Noise handshake with specific peer
Log.d(TAG, "TODO: Initiate full Noise handshake with $peerID") val handshakeData = noiseEncryptionService.initiateHandshake(peerID)
sendKeyExchangeToDevice()
if (handshakeData != null) {
val packet = BitchatPacket(
version = 1u,
type = MessageType.NOISE_HANDSHAKE_INIT.value,
senderID = hexStringToByteArray(myPeerID),
recipientID = hexStringToByteArray(peerID),
timestamp = System.currentTimeMillis().toULong(),
payload = handshakeData,
ttl = 1u
)
connectionManager.broadcastPacket(RoutedPacket(packet))
Log.d(TAG, "Initiated Noise handshake with $peerID (${handshakeData.size} bytes)")
} else {
Log.w(TAG, "Failed to generate Noise handshake data for $peerID")
}
} catch (e: Exception) {
Log.e(TAG, "Failed to initiate Noise handshake with $peerID: ${e.message}")
}
} }
override fun updatePeerIDBinding(newPeerID: String, fingerprint: String, nickname: String, override fun updatePeerIDBinding(newPeerID: String, fingerprint: String, nickname: String,
@@ -324,6 +372,11 @@ class BluetoothMeshService(private val context: Context) {
} }
override fun onDeviceConnected(device: android.bluetooth.BluetoothDevice) { override fun onDeviceConnected(device: android.bluetooth.BluetoothDevice) {
// Send initial announcements after services are ready
serviceScope.launch {
delay(100)
sendBroadcastAnnounce()
}
// Send key exchange to newly connected device // Send key exchange to newly connected device
serviceScope.launch { serviceScope.launch {
delay(100) // Ensure connection is stable delay(100) // Ensure connection is stable
@@ -354,11 +407,6 @@ class BluetoothMeshService(private val context: Context) {
if (connectionManager.startServices()) { if (connectionManager.startServices()) {
isActive = true isActive = true
// Send initial announcements after services are ready
serviceScope.launch {
delay(1000)
sendBroadcastAnnounce()
}
} else { } else {
Log.e(TAG, "Failed to start Bluetooth services") Log.e(TAG, "Failed to start Bluetooth services")
} }
@@ -540,19 +588,25 @@ class BluetoothMeshService(private val context: Context) {
} }
/** /**
* Send key exchange * Send identity announcement (broadcast our static public key)
*/ */
private fun sendKeyExchangeToDevice() { private fun sendKeyExchangeToDevice() {
val publicKeyData = securityManager.getCombinedPublicKeyData() // For discovery, broadcast our static identity key (32 bytes) so peers can identify us
// This is not a handshake initiation, but identity announcement
val identityData = noiseEncryptionService.getStaticPublicKeyData()
val packet = BitchatPacket( val packet = BitchatPacket(
type = MessageType.NOISE_HANDSHAKE_INIT.value, version = 1u,
ttl = 1u, type = MessageType.NOISE_IDENTITY_ANNOUNCE.value, // Changed to identity announce
senderID = myPeerID, senderID = hexStringToByteArray(myPeerID),
payload = publicKeyData recipientID = SpecialRecipients.BROADCAST,
timestamp = System.currentTimeMillis().toULong(),
payload = identityData,
ttl = 1u
) )
connectionManager.broadcastPacket(RoutedPacket(packet)) connectionManager.broadcastPacket(RoutedPacket(packet))
Log.d(TAG, "Sent key exchange") Log.d(TAG, "Sent Noise identity announcement (${identityData.size} bytes)")
} }
/** /**
@@ -84,14 +84,14 @@ class NoiseSession(
val role = if (isInitiator) HandshakeState.INITIATOR else HandshakeState.RESPONDER val role = if (isInitiator) HandshakeState.INITIATOR else HandshakeState.RESPONDER
handshakeState = HandshakeState(PROTOCOL_NAME, role) handshakeState = HandshakeState(PROTOCOL_NAME, role)
// Check if we need to set a local key pair // Set up local static key pair properly
if (handshakeState?.needsLocalKeyPair() == true) { if (handshakeState?.needsLocalKeyPair() == true) {
val staticKeyPair = Noise.createDH("25519")
staticKeyPair.setPrivateKey(localStaticPrivateKey, 0)
// Set the local key pair on the handshake state
val localKeyPair = handshakeState?.getLocalKeyPair() val localKeyPair = handshakeState?.getLocalKeyPair()
localKeyPair?.setPrivateKey(localStaticPrivateKey, 0) if (localKeyPair != null) {
// Set the static private key we loaded/generated
localKeyPair.setPrivateKey(localStaticPrivateKey, 0)
Log.d(TAG, "Set local static key for handshake state")
}
} }
// Start the handshake // Start the handshake
@@ -121,8 +121,9 @@ class NoiseSession(
try { try {
state = NoiseSessionState.Handshaking state = NoiseSessionState.Handshaking
val messageBuffer = ByteArray(256) // Max handshake message size val messageBuffer = ByteArray(512) // Increased buffer size for XX pattern
val messageLength = handshakeState?.writeMessage(ByteArray(0), 0, messageBuffer, 0, 0) ?: 0 val handshakeStateLocal = handshakeState ?: throw IllegalStateException("Handshake state is null")
val messageLength = handshakeStateLocal.writeMessage(ByteArray(0), 0, messageBuffer, 0, 0)
val firstMessage = messageBuffer.copyOf(messageLength) val firstMessage = messageBuffer.copyOf(messageLength)
Log.d(TAG, "Sent real XX handshake message 1 to $peerID (${firstMessage.size} bytes)") Log.d(TAG, "Sent real XX handshake message 1 to $peerID (${firstMessage.size} bytes)")
@@ -154,19 +155,21 @@ class NoiseSession(
} }
val payloadBuffer = ByteArray(256) // Buffer for any payload data val payloadBuffer = ByteArray(256) // Buffer for any payload data
val handshakeStateLocal = handshakeState ?: throw IllegalStateException("Handshake state is null")
// Read the incoming message // Read the incoming message
val payloadLength = handshakeState?.readMessage(message, 0, message.size, payloadBuffer, 0) ?: 0 val payloadLength = handshakeStateLocal.readMessage(message, 0, message.size, payloadBuffer, 0)
Log.d(TAG, "Read handshake message, payload length: $payloadLength") Log.d(TAG, "Read handshake message, payload length: $payloadLength")
// Check the handshake action state // Check the handshake action state
val action = handshakeState?.getAction() ?: HandshakeState.FAILED val action = handshakeStateLocal.getAction()
Log.d(TAG, "Handshake action after read: $action")
return when (action) { return when (action) {
HandshakeState.WRITE_MESSAGE -> { HandshakeState.WRITE_MESSAGE -> {
// Need to send a response // Need to send a response
val responseBuffer = ByteArray(256) val responseBuffer = ByteArray(512) // Increased buffer size for XX pattern message 2
val responseLength = handshakeState?.writeMessage(ByteArray(0), 0, responseBuffer, 0, 0) ?: 0 val responseLength = handshakeStateLocal.writeMessage(ByteArray(0), 0, responseBuffer, 0, 0)
responseBuffer.copyOf(responseLength).also { responseBuffer.copyOf(responseLength).also {
Log.d(TAG, "Generated handshake response: ${it.size} bytes") Log.d(TAG, "Generated handshake response: ${it.size} bytes")
} }
@@ -180,18 +183,18 @@ class NoiseSession(
} }
HandshakeState.FAILED -> { HandshakeState.FAILED -> {
throw Exception("Handshake failed") throw Exception("Handshake failed - action state is FAILED")
} }
else -> { else -> {
Log.d(TAG, "Handshake action: $action") Log.d(TAG, "Handshake action: $action - no response needed")
null null
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
state = NoiseSessionState.Failed(e) state = NoiseSessionState.Failed(e)
Log.e(TAG, "Real handshake failed with $peerID: ${e.message}") Log.e(TAG, "Real handshake failed with $peerID: ${e.message}", e)
throw e throw e
} }
} }