加密密码和解密

时间:2018-03-15 14:26:17

标签: android cryptography kotlin

我尝试以最简单的方式对字符串进行密码和解密,但它不起作用...

经过几个小时的研究,我试着在这里发布我的问题。 我已经将问题减少到最低限度,但它仍然无法正常工作,我也不了解错误。

这是我的代码:

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"))))
}
}

这是我的错误:

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)

有谁知道我的代码出了什么问题?

先谢谢你。

2 个答案:

答案 0 :(得分:2)

当您从String返回的字节中创建Cipher.doFinal时,会出现问题,这些字节不能用于直接创建String

实际上,如果你打印2字节数组就可以得到这个:

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]

您应该直接保存字节数组或将其转换为其他内容,如Base64。 此外,在解密Cipher中,您随机生成初始化向量,而在加密Cipher中则不然,因此您永远无法解密加密的内容。

一个完整的例子:

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))
}

答案 1 :(得分:0)

您收到此错误是因为输入数据不是块大小的倍数(AES为16字节)。

这可能是Cipher: What is the reason for IllegalBlockSizeException?

的副本