问题描述
我正在尝试使用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
参数setEncryptionPaddings
,setBlockModes
来改变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 现在可以使用了,但是过了一段时间,错误又回来了,每次重命名都不是解决方案! 希望有人对此提供帮助