diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java index 1422a818e..793228594 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java @@ -144,7 +144,7 @@ IterableKeychain getKeychain() { } if (keychain == null) { try { - keychain = new IterableKeychain(getMainActivityContext(), config.decryptionFailureHandler, null, config.disableKeychainEncryption); + keychain = new IterableKeychain(getMainActivityContext(), config.decryptionFailureHandler, null, config.keychainEncryption); } catch (Exception e) { IterableLogger.e(TAG, "Failed to create IterableKeychain", e); } diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java index d8b82dd8a..3c2d79641 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java @@ -97,7 +97,7 @@ public class IterableConfig { * When set to true, disables encryption for keychain storage. * By default, encryption is enabled for storing sensitive user data. */ - final boolean disableKeychainEncryption; + final boolean keychainEncryption; /** * Handler for decryption failures of PII information. @@ -127,7 +127,7 @@ private IterableConfig(Builder builder) { dataRegion = builder.dataRegion; useInMemoryStorageForInApps = builder.useInMemoryStorageForInApps; enableEmbeddedMessaging = builder.enableEmbeddedMessaging; - disableKeychainEncryption = builder.disableKeychainEncryption; + keychainEncryption = builder.keychainEncryption; decryptionFailureHandler = builder.decryptionFailureHandler; mobileFrameworkInfo = builder.mobileFrameworkInfo; } @@ -148,7 +148,7 @@ public static class Builder { private IterableDataRegion dataRegion = IterableDataRegion.US; private boolean useInMemoryStorageForInApps = false; private boolean enableEmbeddedMessaging = false; - private boolean disableKeychainEncryption = false; + private boolean keychainEncryption = true; private IterableDecryptionFailureHandler decryptionFailureHandler; private IterableAPIMobileFrameworkInfo mobileFrameworkInfo; @@ -314,11 +314,11 @@ public Builder setEnableEmbeddedMessaging(boolean enableEmbeddedMessaging) { /** * When set to true, disables encryption for Iterable's keychain storage. * By default, encryption is enabled for storing sensitive user data. - * @param disableKeychainEncryption Whether to disable encryption for keychain + * @param keychainEncryption Whether to disable encryption for keychain */ @NonNull - public Builder setDisableKeychainEncryption(boolean disableKeychainEncryption) { - this.disableKeychainEncryption = disableKeychainEncryption; + public Builder setKeychainEncryption(boolean keychainEncryption) { + this.keychainEncryption = keychainEncryption; return this; } diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableKeychain.kt b/iterableapi/src/main/java/com/iterable/iterableapi/IterableKeychain.kt index 201e9dfbe..139bc68e1 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableKeychain.kt +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableKeychain.kt @@ -14,7 +14,7 @@ class IterableKeychain { const val KEY_AUTH_TOKEN = "iterable-auth-token" private const val PLAINTEXT_SUFFIX = "_plaintext" private const val CRYPTO_OPERATION_TIMEOUT_MS = 500L - private const val KEY_ENCRYPTION_DISABLED = "iterable-encryption-disabled" + private const val KEY_ENCRYPTION_ENABLED = "iterable-encryption-enabled" private val cryptoExecutor = Executors.newSingleThreadExecutor() } @@ -22,23 +22,23 @@ class IterableKeychain { private var sharedPrefs: SharedPreferences internal var encryptor: IterableDataEncryptor? = null private val decryptionFailureHandler: IterableDecryptionFailureHandler? - private var encryptionDisabled: Boolean + private var encryption: Boolean @JvmOverloads constructor( context: Context, decryptionFailureHandler: IterableDecryptionFailureHandler? = null, migrator: IterableKeychainEncryptedDataMigrator? = null, - encryptionDisabled: Boolean = false + encryption: Boolean = true ) { sharedPrefs = context.getSharedPreferences( IterableConstants.SHARED_PREFS_FILE, Context.MODE_PRIVATE ) this.decryptionFailureHandler = decryptionFailureHandler - this.encryptionDisabled = encryptionDisabled || sharedPrefs.getBoolean(KEY_ENCRYPTION_DISABLED, false) + this.encryption = encryption && sharedPrefs.getBoolean(KEY_ENCRYPTION_ENABLED, true) - if (encryptionDisabled) { + if (!encryption) { IterableLogger.v(TAG, "SharedPreferences being used without encryption") } else { encryptor = IterableDataEncryptor() @@ -75,10 +75,10 @@ class IterableKeychain { .remove(KEY_EMAIL) .remove(KEY_USER_ID) .remove(KEY_AUTH_TOKEN) - .putBoolean(KEY_ENCRYPTION_DISABLED, true) + .putBoolean(KEY_ENCRYPTION_ENABLED, false) .apply() - encryptionDisabled = true + encryption = false decryptionFailureHandler?.let { handler -> val exception = e ?: Exception("Unknown decryption error") @@ -99,7 +99,7 @@ class IterableKeychain { private fun secureGet(key: String): String? { val hasPlainText = sharedPrefs.getBoolean(key + PLAINTEXT_SUFFIX, false) - if (encryptionDisabled) { + if (!encryption) { if (hasPlainText) { return sharedPrefs.getString(key, null) } else { @@ -125,7 +125,7 @@ class IterableKeychain { return } - if (encryptionDisabled) { + if (!encryption) { editor.putString(key, value).putBoolean(key + PLAINTEXT_SUFFIX, true).apply() return } diff --git a/iterableapi/src/test/java/com/iterable/iterableapi/IterableConfigTest.kt b/iterableapi/src/test/java/com/iterable/iterableapi/IterableConfigTest.kt index 0781f11b7..c64476107 100644 --- a/iterableapi/src/test/java/com/iterable/iterableapi/IterableConfigTest.kt +++ b/iterableapi/src/test/java/com/iterable/iterableapi/IterableConfigTest.kt @@ -25,14 +25,14 @@ class IterableConfigTest { fun defaultDisableKeychainEncryption() { val configBuilder: IterableConfig.Builder = IterableConfig.Builder() val config: IterableConfig = configBuilder.build() - assertFalse(config.disableKeychainEncryption) + assertTrue(config.keychainEncryption) } @Test fun setDisableKeychainEncryption() { val configBuilder: IterableConfig.Builder = IterableConfig.Builder() - .setDisableKeychainEncryption(true) + .setKeychainEncryption(false) val config: IterableConfig = configBuilder.build() - assertTrue(config.disableKeychainEncryption) + assertFalse(config.keychainEncryption) } } \ No newline at end of file diff --git a/iterableapi/src/test/java/com/iterable/iterableapi/IterableKeychainTest.kt b/iterableapi/src/test/java/com/iterable/iterableapi/IterableKeychainTest.kt index 152cc3ab7..08fb042ff 100644 --- a/iterableapi/src/test/java/com/iterable/iterableapi/IterableKeychainTest.kt +++ b/iterableapi/src/test/java/com/iterable/iterableapi/IterableKeychainTest.kt @@ -62,12 +62,14 @@ class IterableKeychainTest { // Mock migration-related SharedPreferences calls `when`(mockSharedPrefs.contains(any())).thenReturn(false) - `when`(mockSharedPrefs.getBoolean(any(), anyBoolean())).thenReturn(false) + // Mock encryption flag to be true by default + `when`(mockSharedPrefs.getBoolean(eq("iterable-encryption-enabled"), anyBoolean())).thenReturn(true) `when`(mockSharedPrefs.getString(any(), any())).thenReturn(null) // Mock editor.apply() to do nothing Mockito.doNothing().`when`(mockEditor).apply() + // Create keychain with encryption enabled (default) keychain = IterableKeychain( mockContext, mockDecryptionFailureHandler @@ -328,7 +330,7 @@ class IterableKeychainTest { mockContext, mockDecryptionFailureHandler, null, - true + false // encryption = false means encryption is disabled ) val testEmail = "test@example.com"