0

I try to cipher and decipher a string in the simplest way but it does not work ...

After few hours of research I try to post my problem here. I have reduce the problem at its minimum but it still doesn't work and I don't understand the error.

Here is my code :

class MainActivity : AppCompatActivity()
{
override fun onCreate(savedInstanceState: Bundle?)
{
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val password = "passwordpassword"
    val plainText = "tototiti123"

    val encryptText = encrypt(plainText, password)
    text.text = decrypt(encryptText, password)
}

private fun encrypt(plainText: String, password: String): String
{
    val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
    val key = SecretKeySpec(password.toByteArray(charset("UTF-8")), "AES")

    cipher.init(Cipher.ENCRYPT_MODE, key)
    return String(cipher.doFinal(plainText.toByteArray(charset("UTF-8"))))
}

private fun decrypt(encrypted: String, password: String): String
{
    val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
    val key = SecretKeySpec(password.toByteArray(charset("UTF-8")), "AES")

    val r = SecureRandom()
    r.setSeed(r.generateSeed(16))

    val byteIV = ByteArray(16)
    r.nextBytes(byteIV)

    cipher.init(Cipher.DECRYPT_MODE, key, IvParameterSpec(byteIV))
    return String(cipher.doFinal(encrypted.toByteArray(charset("UTF-8"))))
}
}

and here is my error :

AndroidRuntime: FATAL EXCEPTION: main
Process: com.cryptapp, PID: 17710
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.cryptapp/com.cryptapp.MainActivity}: javax.crypto.IllegalBlockSizeException: error:1e00007b:Cipher functions:OPENSSL_internal:WRONG_FINAL_BLOCK_LENGTH
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
  at android.app.ActivityThread.-wrap11(Unknown Source:0)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
  at android.os.Handler.dispatchMessage(Handler.java:106)
  at android.os.Looper.loop(Looper.java:164)
  at android.app.ActivityThread.main(ActivityThread.java:6494)
  at java.lang.reflect.Method.invoke(Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: javax.crypto.IllegalBlockSizeException: error:1e00007b:Cipher functions:OPENSSL_internal:WRONG_FINAL_BLOCK_LENGTH
  at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
  at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:570)
  at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:351)
  at javax.crypto.Cipher.doFinal(Cipher.java:1741)
  at com.cryptapp.MainActivity.decrypt(MainActivity.kt:47)
  at com.cryptapp.MainActivity.onCreate(MainActivity.kt:23)
  at android.app.Activity.performCreate(Activity.java:7009)
  at android.app.Activity.performCreate(Activity.java:7000)
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)

Does anyone know what is going wrong with my code ?

Thank you per advance.

Enzokie
  • 7,365
  • 6
  • 33
  • 39
Liam
  • 469
  • 1
  • 6
  • 16

2 Answers2

4

The issue happens when you create a String out of the bytes returned by Cipher.doFinal, which are not meant to be used to create a String directly.

Indeed, if you print the 2 byte arrays you get this:

Cipher.doFinal(..) -> [-124, -59, 116, -79, 27, 67, -75, 5, -6, -58, 9, -104, 16, 65, -9, -95]
encryptText.toByteArray() -> [-17, -65, -67, -17, -65, -67, 116, -17, -65, -67, 27, 67, -17, -65, -67, 5, -17, -65, -67, -17, -65, -67, 9, -17, -65, -67, 16, 65, -17, -65, -67, -17, -65, -67]

You should save directly the byte array or convert it to something else, like Base64. Moreover, in the decryption Cipher you randomly generate an initialization vector, while in the encryption Cipher you don't, so you'll never be able to decrypt what you encrypted.

A full example:

import java.security.SecureRandom
import java.util.*
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec

fun main(args: Array<String>) {

    val password = "passwordpassword"
    val plainText = "tototiti123"

    val r = SecureRandom()
    r.setSeed(r.generateSeed(16))

    val byteIV = ByteArray(16)
    r.nextBytes(byteIV)

    val encryptText = encrypt(plainText, password, byteIV)
    val bytes = Base64.getDecoder().decode(encryptText)
    println(decrypt(bytes, password, byteIV))
}

fun encrypt(plainText: String, password: String, byteIV: ByteArray): String {
    val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
    val key = SecretKeySpec(password.toByteArray(charset("UTF-8")), "AES")

    cipher.init(Cipher.ENCRYPT_MODE, key, IvParameterSpec(byteIV))
    val bytes = cipher.doFinal(plainText.toByteArray(charset("UTF-8")))
    return Base64.getEncoder().encodeToString(bytes)
}

fun decrypt(bytes: ByteArray, password: String, byteIV: ByteArray): String {
    val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
    val key = SecretKeySpec(password.toByteArray(charset("UTF-8")), "AES")

    cipher.init(Cipher.DECRYPT_MODE, key, IvParameterSpec(byteIV))
    return String(cipher.doFinal(bytes))
}
user2340612
  • 10,053
  • 4
  • 41
  • 66
0

You are getting this error because the input data is not a multiple of the block-size (16 bytes for AES).

This is possible a duplicate of Cipher: What is the reason for IllegalBlockSizeException?

  • I've tried to give it a 16 characters string to decipher but it still give me the same error. I've already read the "What is the reason for IllegalBlockSizeException" but it didn't help me on it ... – Liam Mar 15 '18 at 15:08
  • Like that : return String(cipher.doFinal("tototiti12345678".toByteArray(charset("UTF-8")))) – Liam Mar 15 '18 at 15:18
  • @E Notice the `PKCS5Padding"` in `"AES/CBC/PKCS5Padding"`, that handles encryption input that is not a block multiple.. – zaph Mar 15 '18 at 18:05