feat: Implement JSON serialization for message attachments with decryption support

This commit is contained in:
k1ngsterr1
2026-01-13 05:04:05 +05:00
parent af10005879
commit f6409a9474
3 changed files with 223 additions and 4 deletions

View File

@@ -637,6 +637,88 @@ object MessageCrypto {
return plaintext
}
/**
* Расшифровка MESSAGES attachment blob
* Формат: ivBase64:ciphertextBase64
* Использует PBKDF2 + AES-256-CBC + zlib decompression
*/
fun decryptAttachmentBlob(
encryptedData: String,
encryptedKey: String,
myPrivateKey: String
): String? {
return try {
// 1. Расшифровываем ChaCha ключ (как для сообщений)
val keyAndNonce = decryptKeyFromSender(encryptedKey, myPrivateKey)
// 2. Конвертируем key+nonce в строку (как в RN: key.toString('utf-8'))
val chachaKeyString = String(keyAndNonce, Charsets.UTF_8)
// 3. Генерируем PBKDF2 ключ (salt='rosetta', 1000 iterations, sha256)
val pbkdf2Key = generatePBKDF2Key(chachaKeyString)
// 4. Расшифровываем AES-256-CBC
decryptWithPBKDF2Key(encryptedData, pbkdf2Key)
} catch (e: Exception) {
android.util.Log.e("MessageCrypto", "❌ Failed to decrypt attachment blob", e)
null
}
}
/**
* Генерация PBKDF2 ключа (совместимо с RN)
*/
private fun generatePBKDF2Key(password: String, salt: String = "rosetta", iterations: Int = 1000): ByteArray {
val factory = javax.crypto.SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
val spec = javax.crypto.spec.PBEKeySpec(
password.toCharArray(),
salt.toByteArray(Charsets.UTF_8),
iterations,
256 // 32 bytes
)
return factory.generateSecret(spec).encoded
}
/**
* Расшифровка с PBKDF2 ключом (AES-256-CBC + zlib)
* Формат: ivBase64:ciphertextBase64
*/
private fun decryptWithPBKDF2Key(encryptedData: String, pbkdf2Key: ByteArray): String? {
return try {
val parts = encryptedData.split(":")
if (parts.size != 2) {
android.util.Log.e("MessageCrypto", "Invalid encrypted data format")
return null
}
val iv = android.util.Base64.decode(parts[0], android.util.Base64.DEFAULT)
val ciphertext = android.util.Base64.decode(parts[1], android.util.Base64.DEFAULT)
// AES-256-CBC расшифровка
val cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding")
val secretKey = javax.crypto.spec.SecretKeySpec(pbkdf2Key, "AES")
val ivSpec = javax.crypto.spec.IvParameterSpec(iv)
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKey, ivSpec)
val decrypted = cipher.doFinal(ciphertext)
// Zlib декомпрессия
val inflater = java.util.zip.Inflater()
inflater.setInput(decrypted)
val outputStream = java.io.ByteArrayOutputStream()
val buffer = ByteArray(1024)
while (!inflater.finished()) {
val count = inflater.inflate(buffer)
outputStream.write(buffer, 0, count)
}
inflater.end()
String(outputStream.toByteArray(), Charsets.UTF_8)
} catch (e: Exception) {
android.util.Log.e("MessageCrypto", "❌ Failed to decrypt with PBKDF2 key", e)
null
}
}
}
// Extension functions для конвертации