Я использую шифрование и дешифрование с KeyStore следующим образом.
Это поток. После того, как я передаю строку в метод шифрования, я сохраняю как зашифрованные, так и iv, чтобы потом можно было восстановить значение с помощью этого. Проблема иногда возникает, некоторые зашифрованные значения не могут быть восстановлены правильно ... не все из них! Так что, думаю, я зашифровал 10 элементов и сохранил их где-то (как зашифрованные, так и iv). Тогда, когда я хочу получить, один из них не может получить правильно!
init {
keyStore = KeyStore.getInstance(ANDROID_KEY_STORE)
keyStore.load(null)
cipher = Cipher.getInstance("AES/GCM/NoPadding")
}
fun encryptData(text: String): Pair<ByteArray, String>? {
try {
cipher.init(Cipher.ENCRYPT_MODE, getSecretKet(ALIAS))
val iv = cipher.iv.toString(Charsets.ISO_8859_1)
val result = cipher.doFinal(text.toByteArray(Charsets.ISO_8859_1))
Timber.i("$TAG encrypted data $result")
Timber.i("$TAG encrypted iv $iv")
return if (result != null) {
Pair(result, iv)
} else {
null
}
} catch (e: Exception) {
Timber.e("$TAG error encryptData", e)
return null
}
}
fun decryptData(encryptedData: ByteArray, iv: ByteArray): String {
return try {
val spec = GCMParameterSpec(128, iv)
cipher.init(Cipher.DECRYPT_MODE, getSecretKet(ALIAS), spec)
val result = cipher.doFinal(encryptedData).toString(Charsets.ISO_8859_1)
Timber.i("$TAG decrypted data $result")
result
} catch (e: Exception) {
Timber.e("$TAG decryptData error may string was not encrypted", e)
encryptedData.toString()
}
}
И это для получения секретного ключа. Во-первых, возможно, проблема в моем ключе, поэтому я реализовал его таким образом, и этот класс является одиночным. Но иногда я снова открываю приложение, потому что этот ключ не тот (я думаю, потому что iv и зашифрованное значение, а также шифр исправлены). Я также использую Charsets.ISO_8859_1 . Обратите внимание, что эта кодировка лучше, чтобы сохранить все символы и меньше терять. Тогда я подумал, что проблема может быть в сохранении места, поэтому для теста я просто перехожу из комнаты db с полем sstring в SharePref со строкой. Но проблема та же, так что теперь я уверен, что речь идет не о Savig репозитории.
private fun getSecretKet(alias: String): Key {
if (keyStore.containsAlias(alias)) {
//Try for existing key
return keyStore.getKey(alias, null)
} else {
//Key is not present, create new one.
val keyGenerator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val kGenerator =
KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE)
val specs = KeyGenParameterSpec
.Builder(
alias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build()
kGenerator.init(specs)
kGenerator
} else {
KeyGenerator.getInstance(ANDROID_KEY_STORE);
}
return keyGenerator.generateKey()
}
}
Я думаю, что это должно работать так же хорошо, как работает в основном, но в конечном итоге я не могу получить некоторые из моих зашифрованных данных как Я упоминал выше. Любое тело есть идеи?