InvalidAlgorithmParameterException: Nicht unterstützte IV-Länge: 16 Bytes. Nur 12 Byte lange IV unterstütztAndroid

Forum für diejenigen, die für Android programmieren
Anonymous
 InvalidAlgorithmParameterException: Nicht unterstützte IV-Länge: 16 Bytes. Nur 12 Byte lange IV unterstützt

Post by Anonymous »

Ich versuche, die Datenverschlüsselung und -entschlüsselung mithilfe von Cipher zu implementieren. Das ist mein Code:

Code: Select all

class CryptographyManagerImpl : CryptographyManager {
private val KEY_SIZE_BITS: Int = 256
private val GCM_TAG_BITS: Int = 128
private val ANDROID_KEYSTORE = "AndroidKeyStore"

private val KEY_NAME = "MySecretKey"
private val ENCRYPTION_BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM
private val ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_NONE
private val ENCRYPTION_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES

@Throws(BiometricEncryptionException::class)
override fun getInitializedCypherForEncryption(): Cipher {
try {
val cipher = getCipher()
val secretKey = getOrCreateSecretKey(KEY_NAME)
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
return cipher
} catch (e: Exception) {
throw BiometricEncryptionException()
}
}

@Throws(BiometricEncryptionException::class)
@OptIn(ExperimentalEncodingApi::class)
override fun getInitializedCypherForDecryption(
encryptedData: String
): Cipher {
try {
val cipher = getCipher()
val secretKey = getOrCreateSecretKey(KEY_NAME)
val parts = encryptedData.split(":")
val iv = Base64.decode(parts[1], android.util.Base64.DEFAULT)
cipher.init(
Cipher.DECRYPT_MODE,
secretKey,
GCMParameterSpec(GCM_TAG_BITS, iv)
)
return cipher
} catch (e: Exception) {
throw BiometricEncryptionException()
}
}

@Throws(BiometricEncryptionException::class)
@OptIn(ExperimentalEncodingApi::class)
override fun encryptData(
data: String,
cipher: Cipher
): String {
try {
val byteArray = data.toByteArray(StandardCharsets.UTF_8)
val encryptedText = cipher.doFinal(byteArray)
val base64Text = Base64.encode(encryptedText, android.util.Base64.DEFAULT) + ":" + Base64.encode(cipher.iv, android.util.Base64.DEFAULT)
return base64Text
} catch (e: Exception) {
throw BiometricEncryptionException()
}
}

@Throws(BiometricEncryptionException::class)
@OptIn(ExperimentalEncodingApi::class)
override fun decryptData(
encryptedData: String,
cipher: Cipher
): String {
try {
val parts = encryptedData.split(":")
val encryptedText = Base64.decode(parts[0], android.util.Base64.DEFAULT)
val byteArray = cipher.doFinal(encryptedText)
val data = String(byteArray, StandardCharsets.UTF_8)
return data
} catch (e: Exception) {
throw BiometricEncryptionException()
}
}

private fun getCipher(): Cipher {
val transformation = "$ENCRYPTION_ALGORITHM/$ENCRYPTION_BLOCK_MODE/$ENCRYPTION_PADDING"
return Cipher.getInstance(transformation)
}

private fun getOrCreateSecretKey(keyName: String): SecretKey {
val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE).apply {
load(null)
}
keyStore.getKey(keyName, null)?.let {
return it as SecretKey
}

val paramsBuilder = KeyGenParameterSpec.Builder(
keyName,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
).apply {
setBlockModes(ENCRYPTION_BLOCK_MODE)
setEncryptionPaddings(ENCRYPTION_PADDING)
setKeySize(KEY_SIZE_BITS)
setUserAuthenticationRequired(true)
setInvalidatedByBiometricEnrollment(true)
}

val keyGenParams = paramsBuilder.build()
val keyGenerator = KeyGenerator.getInstance(
ENCRYPTION_ALGORITHM,
ANDROID_KEYSTORE
)
keyGenerator.init(keyGenParams)
return keyGenerator.generateKey()
}
}
Der obige Code funktioniert einwandfrei auf Android 16. Unter Android 10 erhalte ich jedoch die im Titel dieser Frage gezeigte Ausnahme, wenn ich versuche, cipher.init für die Entschlüsselungschiffre aufzurufen.
Einige Dinge, die ich beobachtet habe:
  • Beim Aufruf von getInitializedCypherForEncryption , wenn ich das überprüfe cipher.iv unmittelbar nach cipher.init erhalte ich immer ein 12-Byte-Array;
  • Da ich BiometricPrompt und CryptoObject für zusätzliche Sicherheit verwende, hat sich der IV in ein 16-Byte-Array mit unterschiedlichen Werten geändert, wenn ich cipher.iv direkt nach der Erfassung des verifizierten Chiffrierobjekts noch einmal überprüfe;
  • Jetzt löst getInitializedCypherForDecryption die oben genannte Ausnahme direkt auf cipher.init aus, da sich die IV von selbst geändert hat;
  • Ich habe versucht, die ursprüngliche 12-Byte-IV zu behalten, um sie später wiederzuverwenden, aber die resultierenden Daten werden falsch entschlüsselt;
  • Ich habe auch versucht, das Original beizubehalten Cipher-Objekt, anstatt das verifizierte über CryptoObject weiterzuleiten, aber ich erhalte offensichtlich eine android.security.KeyStoreException: Key user not Authenticated;
  • Ich habe auch versucht, meine eigene 12-Byte-IV zu generieren, und habe die cipher.init von getInitializedCypherForEncryption eingefügt. Das gleiche Problem besteht weiterhin und außerdem wird der Code für Android 16 beschädigt, da das manuelle Setzen eines IV zu einer Ausnahme führt.
Habe ich etwas übersehen? Vielen Dank im Voraus.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post