Add auto unlock key storage (#544)

This commit is contained in:
Brian Yencho 2024-01-08 22:18:40 -06:00 committed by Álison Fernandes
parent 6686d98e34
commit 940979599e
4 changed files with 77 additions and 0 deletions

View file

@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.Flow
/**
* Primary access point for disk information.
*/
@Suppress("TooManyFunctions")
interface AuthDiskSource {
/**
* Retrieves a unique ID for the application that is stored locally. This will generate a new
@ -50,6 +51,16 @@ interface AuthDiskSource {
*/
fun storePrivateKey(userId: String, privateKey: String?)
/**
* Retrieves a user auto-unlock key for the given [userId].
*/
fun getUserAutoUnlockKey(userId: String): String?
/**
* Stores a user auto-unlock key for the given [userId].
*/
fun storeUserAutoUnlockKey(userId: String, userAutoUnlockKey: String?)
/**
* Gets the organization keys for the given [userId] in the form of a mapping from organization
* ID to encrypted organization key.

View file

@ -4,6 +4,8 @@ import android.content.SharedPreferences
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
import com.x8bit.bitwarden.data.platform.datasource.disk.BaseDiskSource.Companion.BASE_KEY
import com.x8bit.bitwarden.data.platform.datasource.disk.BaseEncryptedDiskSource
import com.x8bit.bitwarden.data.platform.datasource.disk.BaseEncryptedDiskSource.Companion.ENCRYPTED_BASE_KEY
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import kotlinx.coroutines.flow.Flow
@ -13,6 +15,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.util.UUID
private const val USER_AUTO_UNLOCK_KEY_KEY = "$ENCRYPTED_BASE_KEY:userKeyAutoUnlock"
private const val UNIQUE_APP_ID_KEY = "$BASE_KEY:appId"
private const val REMEMBERED_EMAIL_ADDRESS_KEY = "$BASE_KEY:rememberedEmail"
private const val STATE_KEY = "$BASE_KEY:state"
@ -85,6 +88,22 @@ class AuthDiskSourceImpl(
)
}
override fun getUserAutoUnlockKey(userId: String): String? =
getEncryptedString(
key = "${USER_AUTO_UNLOCK_KEY_KEY}_$userId",
default = null,
)
override fun storeUserAutoUnlockKey(
userId: String,
userAutoUnlockKey: String?,
) {
putEncryptedString(
key = "${USER_AUTO_UNLOCK_KEY_KEY}_$userId",
value = userAutoUnlockKey,
)
}
override fun getOrganizationKeys(userId: String): Map<String, String>? =
getString(key = "${ORGANIZATION_KEYS_KEY}_$userId")
?.let { json.decodeFromString(it) }

View file

@ -193,6 +193,45 @@ class AuthDiskSourceTest {
)
}
@Test
fun `getUserAutoUnlockKey should pull from SharedPreferences`() {
val userAutoUnlockKeyBaseKey = "bwSecureStorage:userKeyAutoUnlock"
val mockUserId = "mockUserId"
val mockUserAutoUnlockKey = "mockUserAutoUnlockKey"
fakeEncryptedSharedPreferences
.edit()
.putString(
"${userAutoUnlockKeyBaseKey}_$mockUserId",
mockUserAutoUnlockKey,
)
.apply()
val actual = authDiskSource.getUserAutoUnlockKey(userId = mockUserId)
assertEquals(
mockUserAutoUnlockKey,
actual,
)
}
@Test
fun `storeUserAutoUnlockKey should update SharedPreferences`() {
val userAutoUnlockKeyBaseKey = "bwSecureStorage:userKeyAutoUnlock"
val mockUserId = "mockUserId"
val mockUserAutoUnlockKey = "mockUserAutoUnlockKey"
authDiskSource.storeUserAutoUnlockKey(
userId = mockUserId,
userAutoUnlockKey = mockUserAutoUnlockKey,
)
val actual = fakeEncryptedSharedPreferences
.getString(
"${userAutoUnlockKeyBaseKey}_$mockUserId",
null,
)
assertEquals(
mockUserAutoUnlockKey,
actual,
)
}
@Test
fun `getOrganizationKeys should pull from SharedPreferences`() {
val organizationKeysBaseKey = "bwPreferencesStorage:encOrgKeys"

View file

@ -21,6 +21,7 @@ class FakeAuthDiskSource : AuthDiskSource {
private val storedUserKeys = mutableMapOf<String, String?>()
private val storedPrivateKeys = mutableMapOf<String, String?>()
private val storedUserAutoUnlockKeys = mutableMapOf<String, String?>()
private val storedOrganizations =
mutableMapOf<String, List<SyncResponseJson.Profile.Organization>?>()
private val storedOrganizationKeys = mutableMapOf<String, Map<String, String>?>()
@ -46,6 +47,13 @@ class FakeAuthDiskSource : AuthDiskSource {
storedPrivateKeys[userId] = privateKey
}
override fun getUserAutoUnlockKey(userId: String): String? =
storedUserAutoUnlockKeys[userId]
override fun storeUserAutoUnlockKey(userId: String, userAutoUnlockKey: String?) {
storedUserAutoUnlockKeys[userId] = userAutoUnlockKey
}
override fun getOrganizationKeys(
userId: String,
): Map<String, String>? = storedOrganizationKeys[userId]