mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 00:25:20 +00:00
fix keys
This commit is contained in:
@@ -5,6 +5,7 @@ import com.bitchat.android.crypto.EncryptionService
|
|||||||
import com.bitchat.android.protocol.BitchatPacket
|
import com.bitchat.android.protocol.BitchatPacket
|
||||||
import com.bitchat.android.protocol.MessageType
|
import com.bitchat.android.protocol.MessageType
|
||||||
import com.bitchat.android.model.RoutedPacket
|
import com.bitchat.android.model.RoutedPacket
|
||||||
|
import com.bitchat.android.util.toHexString
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.mutableSetOf
|
import kotlin.collections.mutableSetOf
|
||||||
@@ -93,8 +94,12 @@ class SecurityManager(private val encryptionService: EncryptionService, private
|
|||||||
val packet = routed.packet
|
val packet = routed.packet
|
||||||
val peerID = routed.peerID ?: "unknown"
|
val peerID = routed.peerID ?: "unknown"
|
||||||
|
|
||||||
Log.d(TAG, "Processing Noise handshake step $step from $peerID (${packet.payload.size} bytes)")
|
// Skip handshakes not addressed to us
|
||||||
|
if (packet.recipientID?.toHexString() != myPeerID) {
|
||||||
|
Log.d(TAG, "Skipping handshake not addressed to us: $peerID")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Skip our own handshake messages
|
// Skip our own handshake messages
|
||||||
if (peerID == myPeerID) return false
|
if (peerID == myPeerID) return false
|
||||||
|
|
||||||
@@ -115,7 +120,7 @@ class SecurityManager(private val encryptionService: EncryptionService, private
|
|||||||
Log.d(TAG, "Already processed handshake: $exchangeKey")
|
Log.d(TAG, "Already processed handshake: $exchangeKey")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
Log.d(TAG, "Processing Noise handshake step $step from $peerID (${packet.payload.size} bytes)")
|
||||||
processedKeyExchanges.add(exchangeKey)
|
processedKeyExchanges.add(exchangeKey)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -304,20 +304,32 @@ class NoiseSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Complete handshake and derive real transport keys
|
* Complete handshake and derive transport keys
|
||||||
*/
|
*/
|
||||||
|
@Synchronized
|
||||||
private fun completeHandshake() {
|
private fun completeHandshake() {
|
||||||
if (currentPattern < NOISE_XX_PATTERN_LENGTH) {
|
if (currentPattern < NOISE_XX_PATTERN_LENGTH) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "Completing real XX handshake with $peerID")
|
Log.d(TAG, "Completing XX handshake with $peerID")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Split handshake state into transport ciphers
|
// Split handshake state into transport ciphers
|
||||||
val cipherPair = handshakeState?.split()
|
val cipherPair = handshakeState?.split()
|
||||||
sendCipher = cipherPair?.getSender()
|
|
||||||
receiveCipher = cipherPair?.getReceiver()
|
// CRITICAL FIX: Assign ciphers based on role to match iOS implementation
|
||||||
|
// Initiator uses getSender() for sending, getReceiver() for receiving
|
||||||
|
// Responder uses getReceiver() for sending, getSender() for receiving
|
||||||
|
if (isInitiator) {
|
||||||
|
sendCipher = cipherPair?.getSender()
|
||||||
|
receiveCipher = cipherPair?.getReceiver()
|
||||||
|
Log.d(TAG, "INITIATOR: sendCipher = getSender(), receiveCipher = getReceiver()")
|
||||||
|
} else {
|
||||||
|
sendCipher = cipherPair?.getReceiver()
|
||||||
|
receiveCipher = cipherPair?.getSender()
|
||||||
|
Log.d(TAG, "RESPONDER: sendCipher = getReceiver(), receiveCipher = getSender()")
|
||||||
|
}
|
||||||
|
|
||||||
// Extract remote static key if available
|
// Extract remote static key if available
|
||||||
if (handshakeState?.hasRemotePublicKey() == true) {
|
if (handshakeState?.hasRemotePublicKey() == true) {
|
||||||
@@ -325,6 +337,7 @@ class NoiseSession(
|
|||||||
if (remoteDH != null) {
|
if (remoteDH != null) {
|
||||||
remoteStaticPublicKey = ByteArray(32)
|
remoteStaticPublicKey = ByteArray(32)
|
||||||
remoteDH.getPublicKey(remoteStaticPublicKey!!, 0)
|
remoteDH.getPublicKey(remoteStaticPublicKey!!, 0)
|
||||||
|
Log.d(TAG, "Remote static public key: ${remoteStaticPublicKey!!.joinToString("") { "%02x".format(it) }}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,7 +362,7 @@ class NoiseSession(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Real Transport Encryption
|
// MARK: - Transport Encryption
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt data in transport mode using real ChaCha20-Poly1305
|
* Encrypt data in transport mode using real ChaCha20-Poly1305
|
||||||
@@ -372,13 +385,17 @@ class NoiseSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val ciphertext = ByteArray(data.size + 16) // Add space for MAC tag
|
// assert that sendCipher!!.macLengt is 16:
|
||||||
val ciphertextLength = sendCipher!!.encryptWithAd(null, data, 0, ciphertext, 0, data.size)
|
if (sendCipher!!.macLength != 16) {
|
||||||
|
throw IllegalStateException("Send cipher MAC length is not 16")
|
||||||
|
}
|
||||||
|
|
||||||
|
val ciphertext = ByteArray(data.size + sendCipher!!.macLength) // Add space for MAC tag
|
||||||
|
val ciphertextLength = sendCipher!!.encryptWithAd(null, data, 0, ciphertext, 0, data.size)
|
||||||
messagesSent++
|
messagesSent++
|
||||||
|
|
||||||
val result = ciphertext.copyOf(ciphertextLength)
|
val result = ciphertext.copyOf(ciphertextLength)
|
||||||
Log.d(TAG, "Real encrypted ${data.size} bytes to ${result.size} bytes for $peerID (msg #$messagesSent)")
|
Log.d(TAG, "✅ ANDROID ENCRYPT: ${data.size} → ${result.size} bytes for $peerID (msg #$messagesSent, role: ${if (isInitiator) "INITIATOR" else "RESPONDER"})")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -420,7 +437,7 @@ class NoiseSession(
|
|||||||
messagesReceived++
|
messagesReceived++
|
||||||
|
|
||||||
val result = plaintext.copyOf(plaintextLength)
|
val result = plaintext.copyOf(plaintextLength)
|
||||||
Log.d(TAG, "Decrypted ${encryptedData.size} bytes to ${result.size} bytes from $peerID (msg #$messagesReceived)")
|
Log.d(TAG, "✅ ANDROID DECRYPT: ${encryptedData.size} → ${result.size} bytes from $peerID (msg #$messagesReceived, role: ${if (isInitiator) "INITIATOR" else "RESPONDER"})")
|
||||||
return result
|
return result
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Decryption failed - exception: ${e.message}")
|
Log.e(TAG, "Decryption failed - exception: ${e.message}")
|
||||||
|
|||||||
Reference in New Issue
Block a user