From 30327fade29675bb9907cd350b75ffa7ed2d6969 Mon Sep 17 00:00:00 2001 From: k1ngsterr1 Date: Fri, 10 Apr 2026 02:20:46 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81:=20=D1=80=D0=B0=D1=81?= =?UTF-8?q?=D1=88=D0=B8=D1=84=D1=80=D0=BE=D0=B2=D0=BA=D0=B0=20=D0=B3=D1=80?= =?UTF-8?q?=D1=83=D0=BF=D0=BF=D0=BE=D0=B2=D1=8B=D1=85=20=D1=84=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=20=E2=80=94=20fallback=20=D0=BD=D0=B0=20hex=20group=20ke?= =?UTF-8?q?y=20(Desktop=20v1.2.1=20parity)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Desktop теперь шифрует аттачменты в группах hex-версией ключа. Android пробует raw key, при неудаче — hex key. Фикс в 3 местах: processDownloadedImage, downloadAndDecryptImage, loadBitmapForViewerImage. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../com/rosetta/messenger/MainActivity.kt | 1 + .../chats/components/AttachmentComponents.kt | 14 +++++++++++++- .../AttachmentDownloadDebugLogger.kt | 19 ++++++++++++++++--- .../ui/chats/components/ImageViewerScreen.kt | 11 +++++++++-- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/rosetta/messenger/MainActivity.kt b/app/src/main/java/com/rosetta/messenger/MainActivity.kt index 0fcc30e..f598a6b 100644 --- a/app/src/main/java/com/rosetta/messenger/MainActivity.kt +++ b/app/src/main/java/com/rosetta/messenger/MainActivity.kt @@ -141,6 +141,7 @@ class MainActivity : FragmentActivity() { // 🔥 Инициализируем ProtocolManager для обработки онлайн статусов ProtocolManager.initialize(this) CallManager.initialize(this) + com.rosetta.messenger.ui.chats.components.AttachmentDownloadDebugLogger.init(this) // 🔔 Инициализируем Firebase для push-уведомлений initializeFirebase() diff --git a/app/src/main/java/com/rosetta/messenger/ui/chats/components/AttachmentComponents.kt b/app/src/main/java/com/rosetta/messenger/ui/chats/components/AttachmentComponents.kt index 886ac8f..b355d91 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/chats/components/AttachmentComponents.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/chats/components/AttachmentComponents.kt @@ -2851,7 +2851,14 @@ private suspend fun processDownloadedImage( var decryptDebug = MessageCrypto.AttachmentDecryptDebugResult(null, emptyList()) val decrypted = if (groupPassword != null) { - val plain = CryptoManager.decryptWithPassword(encryptedContent, groupPassword!!) + // Try raw group key first, then hex-encoded (Desktop v1.2.1+ sends hex-encrypted attachments) + var plain = CryptoManager.decryptWithPassword(encryptedContent, groupPassword!!) + if (plain == null) { + val hexKey = groupPassword!!.toByteArray(Charsets.ISO_8859_1) + .joinToString("") { "%02x".format(it.toInt() and 0xff) } + logPhotoDebug("Group raw key failed, trying hex key: id=$idShort, hexKeyLen=${hexKey.length}") + plain = CryptoManager.decryptWithPassword(encryptedContent, hexKey) + } decryptDebug = MessageCrypto.AttachmentDecryptDebugResult(plain, emptyList()) plain } else { @@ -2968,6 +2975,11 @@ internal suspend fun downloadAndDecryptImage( } else if (isGroupStoredKey(chachaKey)) { val groupPassword = decodeGroupPassword(chachaKey, privateKey) ?: return@withContext null CryptoManager.decryptWithPassword(encryptedContent, groupPassword) + ?: run { + val hexKey = groupPassword.toByteArray(Charsets.ISO_8859_1) + .joinToString("") { "%02x".format(it.toInt() and 0xff) } + CryptoManager.decryptWithPassword(encryptedContent, hexKey) + } } else { val keyCandidates = MessageCrypto.decryptKeyFromSenderCandidates(chachaKey, privateKey) if (keyCandidates.isEmpty()) return@withContext null diff --git a/app/src/main/java/com/rosetta/messenger/ui/chats/components/AttachmentDownloadDebugLogger.kt b/app/src/main/java/com/rosetta/messenger/ui/chats/components/AttachmentDownloadDebugLogger.kt index 728b2c2..0df58ce 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/chats/components/AttachmentDownloadDebugLogger.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/chats/components/AttachmentDownloadDebugLogger.kt @@ -8,9 +8,22 @@ object AttachmentDownloadDebugLogger { private val _logs = MutableStateFlow>(emptyList()) val logs: StateFlow> = _logs.asStateFlow() - fun log(@Suppress("UNUSED_PARAMETER") message: String) { - // Disabled by request: no runtime accumulation of photo debug logs. - return + private var appContext: android.content.Context? = null + + fun init(context: android.content.Context) { + appContext = context.applicationContext + } + + fun log(message: String) { + val ctx = appContext ?: return + try { + val ts = java.text.SimpleDateFormat("HH:mm:ss.SSS", java.util.Locale.getDefault()).format(java.util.Date()) + val line = "$ts [PhotoDL] $message" + android.util.Log.d("PhotoDL", message) + val dir = java.io.File(ctx.filesDir, "crash_reports") + if (!dir.exists()) dir.mkdirs() + java.io.File(dir, "image_logs.txt").appendText("$line\n") + } catch (_: Exception) {} } fun clear() { diff --git a/app/src/main/java/com/rosetta/messenger/ui/chats/components/ImageViewerScreen.kt b/app/src/main/java/com/rosetta/messenger/ui/chats/components/ImageViewerScreen.kt index 225ca0c..7180cef 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/chats/components/ImageViewerScreen.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/chats/components/ImageViewerScreen.kt @@ -984,7 +984,7 @@ private fun viewerLog(context: Context, msg: String) { val ts = java.text.SimpleDateFormat("HH:mm:ss.SSS", java.util.Locale.getDefault()).format(java.util.Date()) val dir = java.io.File(context.filesDir, "crash_reports") if (!dir.exists()) dir.mkdirs() - java.io.File(dir, "rosettadev1.txt").appendText("$ts [Viewer] $msg\n") + java.io.File(dir, "image_logs.txt").appendText("$ts [Viewer] $msg\n") } catch (_: Exception) {} } @@ -1062,7 +1062,14 @@ private suspend fun loadBitmapForViewerImage( val groupPassword = CryptoManager.decryptWithPassword( image.chachaKey.removePrefix("group:"), privateKey ) - if (groupPassword != null) CryptoManager.decryptWithPassword(encryptedContent, groupPassword) else null + if (groupPassword != null) { + CryptoManager.decryptWithPassword(encryptedContent, groupPassword) + ?: run { + val hexKey = groupPassword.toByteArray(Charsets.ISO_8859_1) + .joinToString("") { "%02x".format(it.toInt() and 0xff) } + CryptoManager.decryptWithPassword(encryptedContent, hexKey) + } + } else null } else if (image.chachaKey.isNotEmpty()) { val decryptedKeyAndNonce = MessageCrypto.decryptKeyFromSender(image.chachaKey, privateKey) MessageCrypto.decryptAttachmentBlobWithPlainKey(encryptedContent, decryptedKeyAndNonce)