Android加密无法使用KeyStore生成的kaypair解密数据KeyStoreException:未知错误

问题描述

我正在尝试使用Android用RSA加密和解密数据。这是我的加密/解密代码

fun encryptStringRSA(str: String,publicKey: PublicKey): String{
    val encryptedBytes: ByteArray? = Cipher.getInstance("RSA/NONE/PKCS1Padding").run {
        init(Cipher.ENCRYPT_MODE,publicKey)
        doFinal(str.toByteArray(Charsets.UTF_8))
    }

    return Base64.encodetoString(encryptedBytes,EncryptionConstants.BASE_64_OPTIONS)
}

fun decryptStringRSA(str: String,privateKey: PrivateKey): String{
    val decryptedBytes: ByteArray = Cipher.getInstance("RSA/NONE/PKCS1Padding").run {
        init(Cipher.DECRYPT_MODE,privateKey)
        doFinal(Base64.decode(str,EncryptionConstants.BASE_64_OPTIONS))
    }

    return String(decryptedBytes)
}

当我使用Node JS服务器生成的密钥(这是用于同步算法参数)时,效果很好,但是现在我需要在Android端生成密钥,这就是我的方法

fun generateRSAKeyPair(keyAlias: String): KeyPair {
    val startDate = GregorianCalendar()
    val endDate = GregorianCalendar()
    endDate.add(Calendar.YEAR,1)

    val keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA,ANDROID_KEYSTORE)

    val parameterSpec: KeyGenParameterSpec = KeyGenParameterSpec.Builder(keyAlias,KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY or KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT).run {
        setDigests(KeyProperties.DIGEST_SHA256)
        setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
        setKeySize(2048)
        setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
        setCertificateNotBefore(startDate.time)
        setCertificateNotAfter(endDate.time)
        setUserAuthenticationrequired(true)
        setUserAuthenticationValidityDurationSeconds(30)
        build()
    }

    keyPairGenerator.initialize(parameterSpec)
    val keyPair = keyPairGenerator.genKeyPair()

    val publicKey = getPublicKey(
        Base64.encodetoString(
            keyPair.public.encoded,EncryptionConstants.BASE_64_OPTIONS
        )
    )
    return KeyPair(publicKey,keyPair.private)
}

然后从Keystore获取

fun initKeyPair(keyAlias: String): KeyPair{
    try {
        val keyStore: KeyStore = KeyStore.getInstance(ANDROID_KEYSTORE).apply {
            load(null)
        }

        val entry: KeyStore.Entry = keyStore.getEntry(keyAlias,null)
        val privateKey: PrivateKey? = (entry as KeyStore.PrivateKeyEntry).privateKey
        val publicKey: PublicKey? = keyStore.getCertificate(keyAlias).publicKey

        return if (privateKey == null || publicKey == null) {
            KeyHolderUtils().generateRSAKeyPair(keyAlias)
        } else {
            val publicKey2 = getPublicKey(
                Base64.encodetoString(
                    publicKey.encoded,EncryptionConstants.BASE_64_OPTIONS
                )
            )
            KeyPair(publicKey2,privateKey)
        }
    }catch (ex: Exception){
        return KeyHolderUtils().generateRSAKeyPair(keyAlias)
    }
}

加密,签名和验证有效,但是当我尝试解密时始终会收到KeyStoreException:未知错误

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:526)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
 Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950) 
 Caused by: java.io.IOException: javax.crypto.IllegalBlockSizeException
    at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:133)
    at javax.crypto.CipherInputStream.read(CipherInputStream.java:202)
    at com.test.communication.encryption.utils.EncryptionUtils.decryptStringRSA(EncryptionUtils.kt:46)
    at com.test.communication.encryption.AndroidEncryptionBase.decryptMessage(AndroidEncryptionBase.kt:72)
    at com.test.communication.encryption.AndroidEncryption.decryptMessage(AndroidEncryption.kt:37)
    at com.test.communication.server.MessageServiceImpl.send(MessageServiceImpl.kt:97)
    at com.test.app.presentation.ui.main.CommunicationActivity$initButtons$1.onClick(CommunicationActivity.kt:64)
    at android.view.View.performClick(View.java:7201)
    at android.view.View.performClickInternal(View.java:7170)
    at android.view.View.access$3500(View.java:806)
    at android.view.View$PerformClick.run(View.java:27562)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7682)
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950) 
 Caused by: javax.crypto.IllegalBlockSizeException
    at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:519)
    at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:531)
    at javax.crypto.Cipher.doFinal(Cipher.java:2002)
    at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:130)
    at javax.crypto.CipherInputStream.read(CipherInputStream.java:202) 
    at com.test.communication.encryption.utils.EncryptionUtils.decryptStringRSA(EncryptionUtils.kt:46) 
    at com.test.communication.encryption.AndroidEncryptionBase.decryptMessage(AndroidEncryptionBase.kt:72) 
    at com.test.communication.encryption.AndroidEncryption.decryptMessage(AndroidEncryption.kt:37) 
    at com.test.communication.server.MessageServiceImpl.send(MessageServiceImpl.kt:97) 
    at com.test.app.presentation.ui.main.CommunicationActivity$initButtons$1.onClick(CommunicationActivity.kt:64) 
    at android.view.View.performClick(View.java:7201) 
    at android.view.View.performClickInternal(View.java:7170) 
    at android.view.View.access$3500(View.java:806) 
    at android.view.View$PerformClick.run(View.java:27562) 
    at android.os.Handler.handleCallback(Handler.java:883) 
    at android.os.Handler.dispatchMessage(Handler.java:100) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7682) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950) 
 Caused by: android.security.KeyStoreException: UnkNown error
    at android.security.KeyStore.getKeyStoreException(KeyStore.java:1303)
    at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224)
    at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506)
    at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:531) 
    at javax.crypto.Cipher.doFinal(Cipher.java:2002) 
    at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:130) 
    at javax.crypto.CipherInputStream.read(CipherInputStream.java:202) 
    at com.test.communication.encryption.utils.EncryptionUtils.decryptStringRSA(EncryptionUtils.kt:46) 
    at com.test.communication.encryption.AndroidEncryptionBase.decryptMessage(AndroidEncryptionBase.kt:72) 
    at com.test.communication.encryption.AndroidEncryption.decryptMessage(AndroidEncryption.kt:37) 
    at com.test.communication.server.MessageServiceImpl.send(MessageServiceImpl.kt:97) 
    at com.test.app.presentation.ui.main.CommunicationActivity$initButtons$1.onClick(CommunicationActivity.kt:64) 
    at android.view.View.performClick(View.java:7201) 
    at android.view.View.performClickInternal(View.java:7170) 
    at android.view.View.access$3500(View.java:806) 
    at android.view.View$PerformClick.run(View.java:27562) 
    at android.os.Handler.handleCallback(Handler.java:883) 
    at android.os.Handler.dispatchMessage(Handler.java:100) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7682) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950) 

我尝试使用变化的KeyGenParameterSpec参数setEncryptionPaddingssetBlockModes来改变bloks(ECB,NONE)和填充(nopadding,PKCS1Padding,OAEPPadding,OAEPwithSHA-1和MGF1Padding和OAEPwithSHA-256andMGF1Padding)的不同组合根据组合,我也看到过类似Android KeyStoreException Unknown Error这样的帖子 并尝试更改其中的代码,但始终会出现相同的异常。 顺便说一句,尝试在不同的模拟器上运行,并且真实设备OnePlus 6的结果相同-KeyStoreException:未知错误

更新!!! 我发现有些怪异的想法,如果我将所有这些代码复制到Activity都可以正常工作,但是当我从另一个调用它时出现错误。例如:

fun fire(){

    val str = "test"
    val encryptionUtils = EncryptionUtils()

    generateRSAKeyPair("testKeys")

    val encryptStringRSA = encryptionUtils.encryptStringRSA(str,keyPair.public)
    val decryptStringRSA = decryptStringRSA(encryptStringRSA,keyPair.private)
    println(decryptStringRSA)
}

代码可以正常工作,但是

fun fire(){

    val str = "test"
    val encryptionUtils = EncryptionUtils()

    generateRSAKeyPair("testKeys")

    val encryptStringRSA = encryptionUtils.encryptStringRSA(str,keyPair.public)
    val decryptStringRSA = encryptionUtils.decryptStringRSA(encryptStringRSA,keyPair.private)
    println(decryptStringRSA)
}

代码导致en异常。 Encryption使用与Activity中100%相同的代码的类(我的意思是cryptoStringRSA,decryptStringRSA等)

解决方法

我找到了临时解决方案。我只是重命名了EncryptionUtils-> EncryptionHelper 现在可以使用了,但是过了一段时间,错误又回来了,每次重命名都不是解决方案! 希望有人对此提供帮助