mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 14:25:21 +00:00
heavy logging
This commit is contained in:
@@ -123,9 +123,17 @@ class NoiseSession(
|
|||||||
try {
|
try {
|
||||||
Log.d(TAG, "Creating HandshakeState with role: ${if (role == HandshakeState.INITIATOR) "INITIATOR" else "RESPONDER"}")
|
Log.d(TAG, "Creating HandshakeState with role: ${if (role == HandshakeState.INITIATOR) "INITIATOR" else "RESPONDER"}")
|
||||||
|
|
||||||
|
// LOGGING: Track Android handshake initialization (matching iOS)
|
||||||
|
Log.d(TAG, "=== ANDROID NOISE SESSION - BEFORE HANDSHAKE INIT ===")
|
||||||
|
Log.d(TAG, "Creating NoiseHandshakeState for peer: $peerID")
|
||||||
|
Log.d(TAG, "Role: ${if (role == HandshakeState.INITIATOR) "INITIATOR" else "RESPONDER"}")
|
||||||
|
|
||||||
handshakeState = HandshakeState(PROTOCOL_NAME, role)
|
handshakeState = HandshakeState(PROTOCOL_NAME, role)
|
||||||
Log.d(TAG, "HandshakeState created successfully")
|
Log.d(TAG, "HandshakeState created successfully")
|
||||||
|
|
||||||
|
Log.d(TAG, "=== ANDROID NOISE SESSION - AFTER HANDSHAKE INIT ===")
|
||||||
|
Log.d(TAG, "NoiseHandshakeState created and mixPreMessageKeys() completed")
|
||||||
|
|
||||||
if (handshakeState?.needsLocalKeyPair() == true) {
|
if (handshakeState?.needsLocalKeyPair() == true) {
|
||||||
Log.d(TAG, "Local static key pair is required for XX pattern")
|
Log.d(TAG, "Local static key pair is required for XX pattern")
|
||||||
|
|
||||||
@@ -181,6 +189,8 @@ class NoiseSession(
|
|||||||
*/
|
*/
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun startHandshake(): ByteArray {
|
fun startHandshake(): ByteArray {
|
||||||
|
Log.d(TAG, "Starting noise XX handshake with $peerID as INITIATOR")
|
||||||
|
|
||||||
if (!isInitiator) {
|
if (!isInitiator) {
|
||||||
throw IllegalStateException("Only initiator can start handshake")
|
throw IllegalStateException("Only initiator can start handshake")
|
||||||
}
|
}
|
||||||
@@ -188,9 +198,7 @@ class NoiseSession(
|
|||||||
if (state != NoiseSessionState.Uninitialized) {
|
if (state != NoiseSessionState.Uninitialized) {
|
||||||
throw IllegalStateException("Handshake already started")
|
throw IllegalStateException("Handshake already started")
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "Starting real XX handshake with $peerID as initiator")
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Initialize handshake as initiator
|
// Initialize handshake as initiator
|
||||||
initializeNoiseHandshake(HandshakeState.INITIATOR)
|
initializeNoiseHandshake(HandshakeState.INITIATOR)
|
||||||
@@ -262,7 +270,7 @@ class NoiseSession(
|
|||||||
HandshakeState.SPLIT -> {
|
HandshakeState.SPLIT -> {
|
||||||
// Handshake complete, split into transport keys
|
// Handshake complete, split into transport keys
|
||||||
completeHandshake()
|
completeHandshake()
|
||||||
Log.d(TAG, "XX handshake completed with $peerID")
|
Log.d(TAG, "🔒 XX handshake completed with $peerID")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,15 @@ class NoiseSessionManager(
|
|||||||
var onSessionFailed: ((String, Throwable) -> Unit)? = null
|
var onSessionFailed: ((String, Throwable) -> Unit)? = null
|
||||||
|
|
||||||
// MARK: - Simple Session Management
|
// MARK: - Simple Session Management
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new session for a peer
|
||||||
|
*/
|
||||||
|
fun addSession(peerID: String, session: NoiseSession) {
|
||||||
|
sessions[peerID] = session
|
||||||
|
Log.d(TAG, "Added new session for $peerID")
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get existing session for a peer
|
* Get existing session for a peer
|
||||||
*/
|
*/
|
||||||
@@ -45,6 +53,8 @@ class NoiseSessionManager(
|
|||||||
* SIMPLIFIED: Initiate handshake - no tie breaker, just start
|
* SIMPLIFIED: Initiate handshake - no tie breaker, just start
|
||||||
*/
|
*/
|
||||||
fun initiateHandshake(peerID: String): ByteArray {
|
fun initiateHandshake(peerID: String): ByteArray {
|
||||||
|
Log.d(TAG, "initiateHandshake($peerID)")
|
||||||
|
|
||||||
// Remove any existing session first
|
// Remove any existing session first
|
||||||
removeSession(peerID)
|
removeSession(peerID)
|
||||||
|
|
||||||
@@ -55,11 +65,12 @@ class NoiseSessionManager(
|
|||||||
localStaticPrivateKey = localStaticPrivateKey,
|
localStaticPrivateKey = localStaticPrivateKey,
|
||||||
localStaticPublicKey = localStaticPublicKey
|
localStaticPublicKey = localStaticPublicKey
|
||||||
)
|
)
|
||||||
sessions[peerID] = session
|
Log.d(TAG, "Storing new INITIATOR session for $peerID")
|
||||||
|
addSession(peerID, session)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val handshakeData = session.startHandshake()
|
val handshakeData = session.startHandshake()
|
||||||
Log.d(TAG, "Started handshake with $peerID as initiator")
|
Log.d(TAG, "Started handshake with $peerID as INITIATOR")
|
||||||
return handshakeData
|
return handshakeData
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
sessions.remove(peerID)
|
sessions.remove(peerID)
|
||||||
@@ -74,18 +85,18 @@ class NoiseSessionManager(
|
|||||||
Log.d(TAG, "handleIncomingHandshake($peerID, ${message.size} bytes)")
|
Log.d(TAG, "handleIncomingHandshake($peerID, ${message.size} bytes)")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var session = sessions[peerID]
|
var session = getSession(peerID)
|
||||||
|
|
||||||
// If no session exists, create one as responder
|
// If no session exists, create one as responder
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
Log.d(TAG, "Creating new responder session for $peerID")
|
Log.d(TAG, "Creating new RESPONDER session for $peerID")
|
||||||
session = NoiseSession(
|
session = NoiseSession(
|
||||||
peerID = peerID,
|
peerID = peerID,
|
||||||
isInitiator = false,
|
isInitiator = false,
|
||||||
localStaticPrivateKey = localStaticPrivateKey,
|
localStaticPrivateKey = localStaticPrivateKey,
|
||||||
localStaticPublicKey = localStaticPublicKey
|
localStaticPublicKey = localStaticPublicKey
|
||||||
)
|
)
|
||||||
sessions[peerID] = session
|
addSession(peerID, session)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process handshake message
|
// Process handshake message
|
||||||
@@ -114,7 +125,7 @@ class NoiseSessionManager(
|
|||||||
* SIMPLIFIED: Encrypt data
|
* SIMPLIFIED: Encrypt data
|
||||||
*/
|
*/
|
||||||
fun encrypt(data: ByteArray, peerID: String): ByteArray {
|
fun encrypt(data: ByteArray, peerID: String): ByteArray {
|
||||||
val session = sessions[peerID] ?: throw IllegalStateException("No session found for $peerID")
|
val session = getSession(peerID) ?: throw IllegalStateException("No session found for $peerID")
|
||||||
if (!session.isEstablished()) {
|
if (!session.isEstablished()) {
|
||||||
throw IllegalStateException("Session not established with $peerID")
|
throw IllegalStateException("Session not established with $peerID")
|
||||||
}
|
}
|
||||||
@@ -125,7 +136,7 @@ class NoiseSessionManager(
|
|||||||
* SIMPLIFIED: Decrypt data
|
* SIMPLIFIED: Decrypt data
|
||||||
*/
|
*/
|
||||||
fun decrypt(encryptedData: ByteArray, peerID: String): ByteArray {
|
fun decrypt(encryptedData: ByteArray, peerID: String): ByteArray {
|
||||||
val session = sessions[peerID]
|
val session = getSession(peerID)
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
Log.e(TAG, "No session found for $peerID when trying to decrypt")
|
Log.e(TAG, "No session found for $peerID when trying to decrypt")
|
||||||
throw IllegalStateException("No session found for $peerID")
|
throw IllegalStateException("No session found for $peerID")
|
||||||
@@ -141,7 +152,7 @@ class NoiseSessionManager(
|
|||||||
* Check if session is established with peer
|
* Check if session is established with peer
|
||||||
*/
|
*/
|
||||||
fun hasEstablishedSession(peerID: String): Boolean {
|
fun hasEstablishedSession(peerID: String): Boolean {
|
||||||
val hasSession = sessions[peerID]?.isEstablished() ?: false
|
val hasSession = getSession(peerID)?.isEstablished() ?: false
|
||||||
Log.d(TAG, "hasEstablishedSession($peerID): $hasSession")
|
Log.d(TAG, "hasEstablishedSession($peerID): $hasSession")
|
||||||
return hasSession
|
return hasSession
|
||||||
}
|
}
|
||||||
@@ -150,14 +161,14 @@ class NoiseSessionManager(
|
|||||||
* Get remote static public key for a peer (if session established)
|
* Get remote static public key for a peer (if session established)
|
||||||
*/
|
*/
|
||||||
fun getRemoteStaticKey(peerID: String): ByteArray? {
|
fun getRemoteStaticKey(peerID: String): ByteArray? {
|
||||||
return sessions[peerID]?.getRemoteStaticPublicKey()
|
return getSession(peerID)?.getRemoteStaticPublicKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get handshake hash for channel binding (if session established)
|
* Get handshake hash for channel binding (if session established)
|
||||||
*/
|
*/
|
||||||
fun getHandshakeHash(peerID: String): ByteArray? {
|
fun getHandshakeHash(peerID: String): ByteArray? {
|
||||||
return sessions[peerID]?.getHandshakeHash()
|
return getSession(peerID)?.getHandshakeHash()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+28
-1
@@ -35,6 +35,8 @@ import javax.crypto.ShortBufferException;
|
|||||||
*/
|
*/
|
||||||
public class HandshakeState implements Destroyable {
|
public class HandshakeState implements Destroyable {
|
||||||
|
|
||||||
|
private static final String TAG = "AndroidHandshake";
|
||||||
|
|
||||||
private SymmetricState symmetric;
|
private SymmetricState symmetric;
|
||||||
private boolean isInitiator;
|
private boolean isInitiator;
|
||||||
private DHState localKeyPair;
|
private DHState localKeyPair;
|
||||||
@@ -465,6 +467,17 @@ public class HandshakeState implements Destroyable {
|
|||||||
// Empty value for when the prologue is not supplied.
|
// Empty value for when the prologue is not supplied.
|
||||||
private static final byte[] emptyPrologue = new byte [0];
|
private static final byte[] emptyPrologue = new byte [0];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a byte array to hex string for logging (matching iOS hex format)
|
||||||
|
*/
|
||||||
|
private static String bytesToHex(byte[] bytes) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte b : bytes) {
|
||||||
|
sb.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the handshake running.
|
* Starts the handshake running.
|
||||||
*
|
*
|
||||||
@@ -510,12 +523,20 @@ public class HandshakeState implements Destroyable {
|
|||||||
if (preSharedKey == null)
|
if (preSharedKey == null)
|
||||||
throw new IllegalStateException("Pre-shared key required");
|
throw new IllegalStateException("Pre-shared key required");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log the symmetric state BEFORE any mixing operations (matching iOS)
|
||||||
|
Log.d(TAG, "=== ANDROID HANDSHAKE START - INITIAL STATE ===");
|
||||||
|
Log.d(TAG, "Protocol: " + symmetric.getProtocolName());
|
||||||
|
Log.d(TAG, "Role: " + (isInitiator ? "INITIATOR" : "RESPONDER"));
|
||||||
|
Log.d(TAG, "Initial symmetric hash: " + bytesToHex(symmetric.getHandshakeHash()));
|
||||||
|
|
||||||
// Hash the prologue value.
|
// Hash the prologue value.
|
||||||
|
Log.d(TAG, "Mixing empty prologue");
|
||||||
if (prologue != null)
|
if (prologue != null)
|
||||||
symmetric.mixHash(prologue, 0, prologue.length);
|
symmetric.mixHash(prologue, 0, prologue.length);
|
||||||
else
|
else
|
||||||
symmetric.mixHash(emptyPrologue, 0, 0);
|
symmetric.mixHash(emptyPrologue, 0, 0);
|
||||||
|
Log.d(TAG, "Hash after empty prologue: " + bytesToHex(symmetric.getHandshakeHash()));
|
||||||
|
|
||||||
// Hash the pre-shared key into the chaining key and handshake hash.
|
// Hash the pre-shared key into the chaining key and handshake hash.
|
||||||
if (preSharedKey != null)
|
if (preSharedKey != null)
|
||||||
@@ -523,6 +544,7 @@ public class HandshakeState implements Destroyable {
|
|||||||
|
|
||||||
// Mix the pre-supplied public keys into the handshake hash.
|
// Mix the pre-supplied public keys into the handshake hash.
|
||||||
if (isInitiator) {
|
if (isInitiator) {
|
||||||
|
Log.d(TAG, "XX pattern - no pre-message keys to mix");
|
||||||
if ((requirements & LOCAL_PREMSG) != 0)
|
if ((requirements & LOCAL_PREMSG) != 0)
|
||||||
symmetric.mixPublicKey(localKeyPair);
|
symmetric.mixPublicKey(localKeyPair);
|
||||||
if ((requirements & FALLBACK_PREMSG) != 0) {
|
if ((requirements & FALLBACK_PREMSG) != 0) {
|
||||||
@@ -535,6 +557,7 @@ public class HandshakeState implements Destroyable {
|
|||||||
if ((requirements & REMOTE_PREMSG) != 0)
|
if ((requirements & REMOTE_PREMSG) != 0)
|
||||||
symmetric.mixPublicKey(remotePublicKey);
|
symmetric.mixPublicKey(remotePublicKey);
|
||||||
} else {
|
} else {
|
||||||
|
Log.d(TAG, "XX pattern - no pre-message keys to mix");
|
||||||
if ((requirements & REMOTE_PREMSG) != 0)
|
if ((requirements & REMOTE_PREMSG) != 0)
|
||||||
symmetric.mixPublicKey(remotePublicKey);
|
symmetric.mixPublicKey(remotePublicKey);
|
||||||
if ((requirements & FALLBACK_PREMSG) != 0) {
|
if ((requirements & FALLBACK_PREMSG) != 0) {
|
||||||
@@ -547,7 +570,11 @@ public class HandshakeState implements Destroyable {
|
|||||||
if ((requirements & LOCAL_PREMSG) != 0)
|
if ((requirements & LOCAL_PREMSG) != 0)
|
||||||
symmetric.mixPublicKey(localKeyPair);
|
symmetric.mixPublicKey(localKeyPair);
|
||||||
}
|
}
|
||||||
// Log the symmetric.hash in hex:
|
|
||||||
|
// Log final state after all initialization (matching iOS)
|
||||||
|
Log.d(TAG, "=== ANDROID HANDSHAKE START - FINAL STATE ===");
|
||||||
|
Log.d(TAG, "Final symmetric hash after mixPreMessageKeys(): " + bytesToHex(symmetric.getHandshakeHash()));
|
||||||
|
Log.d(TAG, "===========================================");
|
||||||
|
|
||||||
// The handshake has officially started - set the first action.
|
// The handshake has officially started - set the first action.
|
||||||
if (isInitiator)
|
if (isInitiator)
|
||||||
|
|||||||
+48
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
package com.bitchat.android.noise.southernstorm.protocol;
|
package com.bitchat.android.noise.southernstorm.protocol;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.security.DigestException;
|
import java.security.DigestException;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
@@ -36,6 +38,8 @@ import javax.crypto.ShortBufferException;
|
|||||||
*/
|
*/
|
||||||
class SymmetricState implements Destroyable {
|
class SymmetricState implements Destroyable {
|
||||||
|
|
||||||
|
private static final String TAG = "AndroidSymmetric";
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private CipherState cipher;
|
private CipherState cipher;
|
||||||
private MessageDigest hash;
|
private MessageDigest hash;
|
||||||
@@ -43,6 +47,17 @@ class SymmetricState implements Destroyable {
|
|||||||
private byte[] h;
|
private byte[] h;
|
||||||
private byte[] prev_h;
|
private byte[] prev_h;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a byte array to hex string for logging (matching iOS hex format)
|
||||||
|
*/
|
||||||
|
private static String bytesToHex(byte[] bytes) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte b : bytes) {
|
||||||
|
sb.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new symmetric state object.
|
* Constructs a new symmetric state object.
|
||||||
*
|
*
|
||||||
@@ -79,6 +94,14 @@ class SymmetricState implements Destroyable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
System.arraycopy(h, 0, ck, 0, hashLength);
|
System.arraycopy(h, 0, ck, 0, hashLength);
|
||||||
|
|
||||||
|
// LOGGING: Initial symmetric state after protocol name initialization (matching iOS)
|
||||||
|
Log.d(TAG, "=== ANDROID SYMMETRIC STATE INITIALIZED ===");
|
||||||
|
Log.d(TAG, "Protocol: " + protocolName);
|
||||||
|
Log.d(TAG, "Initial hash (h): " + bytesToHex(h));
|
||||||
|
Log.d(TAG, "Initial chaining key (ck): " + bytesToHex(ck));
|
||||||
|
Log.d(TAG, "Hash length: " + h.length);
|
||||||
|
Log.d(TAG, "=========================================");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,6 +134,14 @@ class SymmetricState implements Destroyable {
|
|||||||
*/
|
*/
|
||||||
public void mixKey(byte[] data, int offset, int length)
|
public void mixKey(byte[] data, int offset, int length)
|
||||||
{
|
{
|
||||||
|
// LOGGING: Before mixKey operation (matching iOS)
|
||||||
|
byte[] inputData = new byte[length];
|
||||||
|
System.arraycopy(data, offset, inputData, 0, length);
|
||||||
|
Log.d(TAG, "*** Android mixKey() BEFORE ***");
|
||||||
|
Log.d(TAG, "Input data (" + length + " bytes): " + bytesToHex(inputData));
|
||||||
|
Log.d(TAG, "Current CK: " + bytesToHex(ck));
|
||||||
|
Log.d(TAG, "Current Hash: " + bytesToHex(h));
|
||||||
|
|
||||||
int keyLength = cipher.getKeyLength();
|
int keyLength = cipher.getKeyLength();
|
||||||
byte[] tempKey = new byte [keyLength];
|
byte[] tempKey = new byte [keyLength];
|
||||||
try {
|
try {
|
||||||
@@ -119,6 +150,12 @@ class SymmetricState implements Destroyable {
|
|||||||
} finally {
|
} finally {
|
||||||
Noise.destroy(tempKey);
|
Noise.destroy(tempKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LOGGING: After mixKey operation (matching iOS)
|
||||||
|
Log.d(TAG, "*** Android mixKey() AFTER ***");
|
||||||
|
Log.d(TAG, "New CK: " + bytesToHex(ck));
|
||||||
|
Log.d(TAG, "Hash unchanged: " + bytesToHex(h));
|
||||||
|
Log.d(TAG, "Cipher now has key: " + (cipher.getMACLength() > 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,7 +167,18 @@ class SymmetricState implements Destroyable {
|
|||||||
*/
|
*/
|
||||||
public void mixHash(byte[] data, int offset, int length)
|
public void mixHash(byte[] data, int offset, int length)
|
||||||
{
|
{
|
||||||
|
// LOGGING: Before mixHash operation (matching iOS)
|
||||||
|
byte[] inputData = new byte[length];
|
||||||
|
System.arraycopy(data, offset, inputData, 0, length);
|
||||||
|
Log.d(TAG, "*** Android mixHash() BEFORE ***");
|
||||||
|
Log.d(TAG, "Input data (" + length + " bytes): " + bytesToHex(inputData));
|
||||||
|
Log.d(TAG, "Current Hash: " + bytesToHex(h));
|
||||||
|
|
||||||
hashTwo(h, 0, h.length, data, offset, length, h, 0, h.length);
|
hashTwo(h, 0, h.length, data, offset, length, h, 0, h.length);
|
||||||
|
|
||||||
|
// LOGGING: After mixHash operation (matching iOS)
|
||||||
|
Log.d(TAG, "*** Android mixHash() AFTER ***");
|
||||||
|
Log.d(TAG, "New Hash: " + bytesToHex(h));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user