From a88792ed38d652ea703b04cb341280d8bfef02a3 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Wed, 9 Feb 2022 09:36:52 +0200 Subject: [PATCH] Encrypt backup without Crypto class --- .../main/kotlin/com/tutpro/baresip/Utils.kt | 64 +++++++++++++++---- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt index 21d95224..eff82c1d 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt @@ -548,15 +548,19 @@ object Utils { return true } - class Crypto(val salt: ByteArray, val iter: Int, val iv: ByteArray, val data: ByteArray): - Serializable { + class Crypto(val salt: ByteArray, val iter: Int, val iv: ByteArray, val data: ByteArray): Serializable { companion object { private const val serialVersionUID: Long = -29238082928391L } } - private fun encrypt(content: ByteArray, password: CharArray): Crypto? { - var obj: Crypto? = null + private fun encrypt(content: ByteArray, password: CharArray): ByteArray? { + fun intToByteArray(int: Int): ByteArray { + val bytes = ByteArray(2) + bytes[0] = (int shr 0).toByte() + bytes[1] = (int shr 8).toByte() + return bytes + } try { val sr = SecureRandom() val salt = ByteArray(128) @@ -573,15 +577,42 @@ object Utils { val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding") cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec) val cipherData = cipher.doFinal(content) - obj = Crypto(salt, iterationCount, iv, cipherData) + val res = ByteArray(128 + 2 + 16 + cipherData.size) + salt.copyInto(res, 0) + intToByteArray(iterationCount).copyInto(res, salt.size) + iv.copyInto(res, salt.size + 2) + cipherData.copyInto(res, salt.size + 2 + iv.size) + return res } catch (e: Exception) { Log.e(TAG, "Encrypt failed: ${e.printStackTrace()}") } - return obj - + return null } - private fun decrypt(obj: Crypto, password: CharArray): ByteArray? { + private fun decrypt(content: ByteArray, password: CharArray): ByteArray? { + fun byteArrayToInt(bytes: ByteArray) : Int { + return (bytes[1].toInt() and 0xff shl 8) or (bytes[0].toInt() and 0xff) + } + try { + val salt = content.copyOfRange(0, 128) + val iterationCount = byteArrayToInt(content.copyOfRange(128, 130)) + val iv = content.copyOfRange(130, 146) + val data = content.copyOfRange(146, content.size) + val pbKeySpec = PBEKeySpec(password, salt, iterationCount, 128) + val secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") + val keyBytes = secretKeyFactory.generateSecret(pbKeySpec).encoded + val keySpec = SecretKeySpec(keyBytes, "AES") + val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding") + val ivSpec = IvParameterSpec(iv) + cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec) + return cipher.doFinal(data) + } catch (e: Exception) { + Log.e(TAG, "Decrypt failed: ${e.printStackTrace()}") + } + return null + } + + private fun decryptOld(obj: Crypto, password: CharArray): ByteArray? { var plainData: ByteArray? = null try { val pbKeySpec = PBEKeySpec(password, obj.salt, obj.iter, 128) @@ -613,13 +644,24 @@ object Utils { fun decryptFromStream(stream: FileInputStream?, password: String): ByteArray? { var plainData: ByteArray? = null + if (stream == null) + return null try { ObjectInputStream(stream).use { - val obj = it.readObject() as Crypto - plainData = decrypt(obj, password.toCharArray()) + val content = it.readObject() as ByteArray + plainData = decrypt(content, password.toCharArray()) } } catch (e: Exception) { - Log.w(TAG, "decryptFromStream failed: $e") + Log.w(TAG, "decryptFromStream as ByteArray failed: $e") + try { + stream.close() + ObjectInputStream(stream).use { + val obj = it.readObject() as Crypto + plainData = decryptOld(obj, password.toCharArray()) + } + } catch (e: Exception) { + Log.w(TAG, "decryptFromStream as Crypto failed: $e") + } } return plainData }