the_dani
the_dani

Reputation: 2524

IllegalBlockSizeException when decrypting an encrypted JSON-String after reading from a file

I'm getting an IllegalBlockSizeException after reading a previously encrypted JSON-String from a file: javax.crypto.IllegalBlockSizeException error:1e00007b:Cipher functions:OPENSSL_internal:WRONG_FINAL_BLOCK_LENGTH

The following code works, when I do not write the String to a file, but directly decrypt the encrypted string:

object Crypto {

    const val BYTEARRAY_LENGTH = 16
    const val ALGORITHM = "AES"
    const val TRANSFORMATION = "AES/CBC/PKCS5PADDING"

    fun getKeyFromPassword(password: String): SecretKey {
        val keyBytes = password.toByteArray()

        if (keyBytes.size != BYTEARRAY_LENGTH) throw IllegalArgumentException("Length of password must be $BYTEARRAY_LENGTH bytes.")

        return SecretKeySpec(keyBytes, ALGORITHM)
    }

    fun encrypt(key: SecretKey, dataToEncrypt: ByteArray): ByteArray {
        val cipher = Cipher.getInstance(TRANSFORMATION)
        cipher.init(Cipher.ENCRYPT_MODE, key, IvParameterSpec(ByteArray(BYTEARRAY_LENGTH)))

        return cipher.doFinal(dataToEncrypt)
    }

    fun decrypt(key: SecretKey, dataToDecrypt: ByteArray): ByteArray {
        val cipher = Cipher.getInstance(TRANSFORMATION)
        cipher.init(Cipher.DECRYPT_MODE, key, IvParameterSpec(ByteArray(BYTEARRAY_LENGTH)))

        return cipher.doFinal(dataToDecrypt)
    }
}

I'm reading the string with the following code and converting it to a ByteArray using String.toByteArray():

private suspend fun readTextFromUri(uri: Uri): String = withContext(Dispatchers.IO) {
    val stringBuilder = StringBuilder()
    applicationContext.contentResolver.openInputStream(uri)?.use { inputStream ->
        BufferedReader(InputStreamReader(inputStream)).use { reader ->
            var line: String? = reader.readLine()
            while (line != null) {
                stringBuilder.append(line)
                line = reader.readLine()
            }
        }
    }
    return@withContext stringBuilder.toString()
}

This is how the file is written:

val encryptedExport = Crypto.encrypt(key, export.toByteArray())

try {
    withContext(Dispatchers.IO) {
        applicationContext.contentResolver.openFileDescriptor(fileUri, "w")?.use {
            FileOutputStream(it.fileDescriptor).use { stream ->
                stream.write(encryptedExport)
            }
        }
    }
} catch (e: FileNotFoundException) {
    e.printStackTrace()
    return Result.failure()
} catch (e: IOException) {
    e.printStackTrace()
    return Result.failure()
}

Upvotes: 0

Views: 1016

Answers (1)

David Soroko
David Soroko

Reputation: 9096

Looks like you are writing out a binary file, but reading it in as a text.

How about reading the file with code similar to:

fun readEncrypted(file: String): ByteArray =
    FileInputStream(file).use { it.readAllBytes() }

Once you decrypt the ByteArray you read from the file, you can convert the resulting ByteArray to a String.

Upvotes: 1

Related Questions