mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 21:05:24 +00:00
wip noise
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user