【发布时间】:2019-04-13 12:17:28
【问题描述】:
我正在尝试创建一个简单的 Kotlin 对象,该对象通过在保存内容之前加密内容来包装对应用程序共享首选项的访问。
加密似乎工作正常,但是当我尝试解密时,我得到一个 javax.crypto.AEADBadTagException,它从“android.security.KeyStoreException:签名/MAC 验证失败”触发。
我已尝试调试以查看根本问题是什么,但我找不到任何东西。没有搜索给我任何线索,我似乎遵循了一些指南,但没有成功。
private val context: Context?
get() = this.application?.applicationContext
private var application: Application? = null
private val transformation = "AES/GCM/NoPadding"
private val androidKeyStore = "AndroidKeyStore"
private val ivPrefix = "_iv"
private val keyStore by lazy { this.createKeyStore() }
private fun createKeyStore(): KeyStore {
val keyStore = KeyStore.getInstance(this.androidKeyStore)
keyStore.load(null)
return keyStore
}
private fun createSecretKey(alias: String): SecretKey {
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, this.androidKeyStore)
keyGenerator.init(
KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build()
)
return keyGenerator.generateKey()
}
private fun getSecretKey(alias: String): SecretKey {
return if (this.keyStore.containsAlias(alias)) {
(this.keyStore.getEntry(alias, null) as KeyStore.SecretKeyEntry).secretKey
} else {
this.createSecretKey(alias)
}
}
private fun removeSecretKey(alias: String) {
this.keyStore.deleteEntry(alias)
}
private fun encryptText(alias: String, textToEncrypt: String): String {
val cipher = Cipher.getInstance(this.transformation)
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(alias))
val ivString = Base64.encodeToString(cipher.iv, Base64.DEFAULT)
this.storeInSharedPrefs(alias + this.ivPrefix, ivString)
val byteArray = cipher.doFinal(textToEncrypt.toByteArray(charset("UTF-8")))
return String(byteArray)
}
private fun decryptText(alias: String, textToDecrypt: String): String? {
val ivString = this.retrieveFromSharedPrefs(alias + this.ivPrefix) ?: return null
val iv = Base64.decode(ivString, Base64.DEFAULT)
val spec = GCMParameterSpec(iv.count() * 8, iv)
val cipher = Cipher.getInstance(this.transformation)
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(alias), spec)
try {
val byteArray = cipher.doFinal(textToDecrypt.toByteArray(charset("UTF-8")))
return String(byteArray)
} catch (e: Exception) {
e.printStackTrace()
return null
}
}
private fun storeInSharedPrefs(key: String, value: String) {
this.context?.let {
PreferenceManager.getDefaultSharedPreferences(it).edit()?.putString(key, value)?.apply()
}
}
private fun retrieveFromSharedPrefs(key: String): String? {
val validContext = this.context ?: return null
return PreferenceManager.getDefaultSharedPreferences(validContext).getString(key, null)
}
谁能指出我正确的方向?
【问题讨论】:
-
你找到解决办法了吗?
-
不,我暂时不用,因为这对我来说不是硬性要求。
-
可能是特定于设备的问题吗?我在装有 Android 9 的“HUAWEI P smart 2020”上看到了这个异常。其他设备似乎可以工作。
-
您不定期地启动密码,在解密时使用规范,而在未加密时使用规范。您的显式规范是否与加密中使用的默认规范相同?
标签: android encryption kotlin keystore android-keystore