heavy logging

This commit is contained in:
callebtc
2025-07-20 13:53:58 +02:00
parent d507996da8
commit ec66b41609
4 changed files with 110 additions and 16 deletions
@@ -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")
} }
@@ -189,8 +199,6 @@ class NoiseSession(
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
} }
@@ -23,6 +23,14 @@ class NoiseSessionManager(
// 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()
} }
/** /**
@@ -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.
* *
@@ -511,11 +524,19 @@ public class HandshakeState implements Destroyable {
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)
@@ -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));
} }
/** /**