diff --git a/core/preferences/src/androidMain/kotlin/dev/alvr/katana/core/preferences/di/module.android.kt b/core/preferences/src/androidMain/kotlin/dev/alvr/katana/core/preferences/di/module.android.kt index 9a6f48f62..75bb5d418 100644 --- a/core/preferences/src/androidMain/kotlin/dev/alvr/katana/core/preferences/di/module.android.kt +++ b/core/preferences/src/androidMain/kotlin/dev/alvr/katana/core/preferences/di/module.android.kt @@ -1,9 +1,14 @@ package dev.alvr.katana.core.preferences.di +import android.content.Context +import android.os.Build +import androidx.annotation.RequiresApi import com.google.crypto.tink.Aead import com.google.crypto.tink.KeyTemplates +import com.google.crypto.tink.RegistryConfiguration import com.google.crypto.tink.aead.AeadConfig import com.google.crypto.tink.integration.android.AndroidKeysetManager +import com.google.crypto.tink.integration.android.AndroidKeystore import dev.alvr.katana.core.preferences.encrypt.AndroidPreferencesEncrypt import dev.alvr.katana.core.preferences.encrypt.PreferencesEncrypt import org.koin.android.ext.koin.androidApplication @@ -13,15 +18,11 @@ import org.koin.dsl.module private val aeadModule = module { single { - AeadConfig.register() - - AndroidKeysetManager.Builder() - .withSharedPref(androidApplication(), KEYSET_NAME, PREFERENCE_FILE) - .withKeyTemplate(KeyTemplates.get(TEMPLATE_NAME)) - .withMasterKeyUri(MASTER_KEY_URI) - .build() - .keysetHandle - .getPrimitive(Aead::class.java) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + android23Aead() + } else { + androidCompatAead(androidApplication()) + } } } @@ -33,7 +34,29 @@ internal actual fun encryptionModule() = module { includes(aeadModule, securerModule) } +private fun androidCompatAead(context: Context): Aead { + AeadConfig.register() + + return AndroidKeysetManager.Builder() + .withSharedPref(context, KEYSET_NAME, PREFERENCE_FILE) + .withKeyTemplate(KeyTemplates.get(TEMPLATE_NAME)) + .withMasterKeyUri(MASTER_KEY_URI) + .build() + .keysetHandle + .getPrimitive(RegistryConfiguration.get(), Aead::class.java) +} + +@RequiresApi(Build.VERSION_CODES.M) +private fun android23Aead(): Aead { + if (!AndroidKeystore.hasKey(KeyStoreAlias)) { + AndroidKeystore.generateNewAes256GcmKey(KeyStoreAlias) + } + return AndroidKeystore.getAead(KeyStoreAlias) +} + private const val KEYSET_NAME = "master_keyset" private const val PREFERENCE_FILE = "master_key_preference" private const val MASTER_KEY_URI = "android-keystore://master_key" private const val TEMPLATE_NAME = "AES256_GCM" + +private const val KeyStoreAlias = "katana" diff --git a/core/preferences/src/androidMain/kotlin/dev/alvr/katana/core/preferences/encrypt/AndroidPreferencesEncrypt.kt b/core/preferences/src/androidMain/kotlin/dev/alvr/katana/core/preferences/encrypt/AndroidPreferencesEncrypt.kt index e6dcea58a..6ca3bef47 100644 --- a/core/preferences/src/androidMain/kotlin/dev/alvr/katana/core/preferences/encrypt/AndroidPreferencesEncrypt.kt +++ b/core/preferences/src/androidMain/kotlin/dev/alvr/katana/core/preferences/encrypt/AndroidPreferencesEncrypt.kt @@ -8,11 +8,11 @@ internal class AndroidPreferencesEncrypt( private val aead: Aead, ) : PreferencesEncrypt { override fun decrypt(input: ByteArray): ByteArray = operation("Aead decrypt") { - aead.decrypt(input, null) + aead.decrypt(input, byteArrayOf()) } override fun encrypt(input: ByteArray): ByteArray = operation("Aead encrypt") { - aead.encrypt(input, null) + aead.encrypt(input, byteArrayOf()) } private inline fun operation(message: String, block: () -> R): R = try { diff --git a/core/preferences/src/androidUnitTest/kotlin/dev/alvr/katana/core/preferences/encrypt/AndroidPreferencesEncryptTest.kt b/core/preferences/src/androidUnitTest/kotlin/dev/alvr/katana/core/preferences/encrypt/AndroidPreferencesEncryptTest.kt index 57bfa1d49..722affb93 100644 --- a/core/preferences/src/androidUnitTest/kotlin/dev/alvr/katana/core/preferences/encrypt/AndroidPreferencesEncryptTest.kt +++ b/core/preferences/src/androidUnitTest/kotlin/dev/alvr/katana/core/preferences/encrypt/AndroidPreferencesEncryptTest.kt @@ -18,7 +18,7 @@ internal class AndroidPreferencesEncryptTest : FreeSpec() { val input = "Test".encodeToByteArray() encrypt.decrypt(input) shouldBe "tseT".encodeToByteArray() - verify(exactly = 1) { aead.decrypt(input, null) } + verify(exactly = 1) { aead.decrypt(input, byteArrayOf()) } } "encrypt using Aead" { @@ -27,7 +27,7 @@ internal class AndroidPreferencesEncryptTest : FreeSpec() { val input = "Test".encodeToByteArray() encrypt.encrypt(input) shouldBe "tseT".encodeToByteArray() - verify(exactly = 1) { aead.encrypt(input, null) } + verify(exactly = 1) { aead.encrypt(input, byteArrayOf()) } } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 347566348..dac398277 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -38,7 +38,7 @@ orbit = "9.0.0" sentry = "7.19.0" sentry-multiplatform = "0.10.0" sentry-plugin = "4.14.1" -tink = "1.15.0" +tink = "1.16.0" turbine = "1.2.0" [plugins]