Шифрование Symmetri c с использованием AES вызывает исключение NullPointerException для cipher.init - PullRequest
1 голос
/ 10 января 2020

Я пытаюсь настроить шифрование AES симметрии c, работающее в моем приложении android, и мне трудно заставить его работать.

Пример кода ниже

Активность

override fun onCreate() {
  ...
  val key = KeyGenerator().generateSymemetricKey(ANDROID_KEYSTORE, "token", AES, PKCS7, CBC, PURPOSE_ENCRYPT or PURPOSE_DECRYPT)

  val encryptionPair = EncryptionHelper.encrypt(AES, "Testing", key)
  encryptionPair?.let {
    val decryptedString = EncryptionHelper.decrypt(AES, it.first, key, it.second)
    Timber.d(decryptedString)
  }
class KeyGenerator {
    fun generateSymemetricKey(keystoreName: String, alias: String, algorithm: String, padding: String, blockMode: String, purposes: Int): Key {

        val keystore = KeyStore.getInstance(keystoreName)
        keystore.load(null)

        if (!keystore.containsAlias(alias)) {
            val keyGenerator = KeyGenerator.getInstance(algorithm, keystoreName)


            val keyGenParameterSpec = KeyGenParameterSpec.Builder(alias, purposes)
                .setBlockModes(blockMode)
                .setEncryptionPaddings(padding)
                .build()

            keyGenerator.init(keyGenParameterSpec)

            return keyGenerator.generateKey()

        } else {

            return keystore.getKey(alias, null) as Key
        }
    }
}
object EncryptionHelper {

    fun encrypt(algorithm: String, text: String, key: Key): Pair<ByteArray, ByteArray>? = try {
        val cipher = Cipher.getInstance(algorithm)

        cipher.init(Cipher.ENCRYPT_MODE, key)

        val cipherText = cipher.doFinal(text.toByteArray())

        Pair(cipherText, cipher.iv)

    } catch (exception: GeneralSecurityException) {

        null
    }

    fun decrypt(algorithm: String, cipherText: ByteArray, key: Key, iv: ByteArray): String? = try {
        val cipher = Cipher.getInstance(algorithm)

        cipher.init(Cipher.DECRYPT_MODE, key, IvParameterSpec(iv))

        val plainText = cipher.doFinal(cipherText).toString()

        plainText

    } catch (exception: GeneralSecurityException) {
        null
    }
}

При вызове cipher.init в encrypt BouncyCastle выдает следующее исключение

2020-01-09 17:05:13.743 24911-24911/com.smartrent.alloytile E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.smartrent.alloytile, PID: 24911
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.smartrent.alloytile/com.smartrent.alloytile.MainActivity}: java.lang.NullPointerException: Attempt to get length of null array
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3092)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3235)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:6986)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
     Caused by: java.lang.NullPointerException: Attempt to get length of null array
        at com.android.org.bouncycastle.crypto.params.KeyParameter.<init>(KeyParameter.java:13)
        at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(BaseBlockCipher.java:692)
        at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(BaseBlockCipher.java:1076)
        at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984)
        at javax.crypto.Cipher.tryCombinations(Cipher.java:2891)
        at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796)
        at javax.crypto.Cipher.chooseProvider(Cipher.java:773)
        at javax.crypto.Cipher.init(Cipher.java:1143)
        at javax.crypto.Cipher.init(Cipher.java:1084)
        at com.smartrent.crypto.EncryptionHelper.encrypt(EncryptionHelper.kt:17)
        at com.smartrent.alloytile.MainActivity.onCreate(MainActivity.kt:62)
        at android.app.Activity.performCreate(Activity.java:7326)
        at android.app.Activity.performCreate(Activity.java:7317)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3072)

При отладке обнаруженная ошибка key.encoded нуль, что в конечном итоге вызывает проблему. Однако именно так все учебники, которые я нашел, обрабатывали симметричное шифрование c, и никто, похоже, не имел этой проблемы.

1 Ответ

1 голос
/ 14 января 2020

В размещенном коде в системе хранилища ключей Android генерируется ключ для шифрования с помощью AES с использованием режима CB C и заполнения PKCS7. Для этого созвездия "AES/CBC/PKCS7Padding" должно быть передано в качестве аргумента Cipher.getInstance(), как указано в этом списке шифров, поддерживаемых системой Android хранилища ключей.

...