Update SDK to 2.0.0-4254-6c954013 (#6218)

Co-authored-by: bw-ghapp[bot] <178206702+bw-ghapp[bot]@users.noreply.github.com>
Co-authored-by: Carlos Gonçalves <cgoncalves@bitwarden.com>
This commit is contained in:
bw-ghapp[bot] 2025-12-30 18:12:39 +00:00 committed by GitHub
parent 3bc538c1f8
commit 2d228b8496
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 1402 additions and 518 deletions

View File

@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.repository
import com.bitwarden.core.AuthRequestMethod
import com.bitwarden.core.InitUserCryptoMethod
import com.bitwarden.core.WrappedAccountCryptographicState
import com.bitwarden.core.data.manager.dispatcher.DispatcherManager
import com.bitwarden.core.data.repository.error.MissingPropertyException
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
@ -113,6 +114,7 @@ import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockError
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
import com.x8bit.bitwarden.data.vault.repository.util.createWrappedAccountCryptographicState
import com.x8bit.bitwarden.data.vault.repository.util.toSdkMasterPasswordUnlock
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -517,6 +519,7 @@ class AuthRepositoryImpl(
)
val signingKey = accountKeys?.signatureKeyPair?.wrappedSigningKey
val securityState = accountKeys?.securityState?.securityState
val signedPublicKey = accountKeys?.publicKeyEncryptionKeyPair?.signedPublicKey
checkForVaultUnlockError(
onVaultUnlockError = { error ->
@ -524,10 +527,13 @@ class AuthRepositoryImpl(
},
) {
unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = securityState,
signingKey = signingKey,
signedPublicKey = signedPublicKey,
),
accountProfile = profile,
privateKey = privateKey,
signingKey = signingKey,
securityState = securityState,
initUserCryptoMethod = InitUserCryptoMethod.AuthRequest(
requestPrivateKey = requestPrivateKey,
method = AuthRequestMethod.UserKey(protectedUserKey = asymmetricalKey),
@ -1809,14 +1815,23 @@ class AuthRepositoryImpl(
)
.map {
unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = loginResponse.accountKeys
?.securityState
?.securityState,
signingKey = loginResponse.accountKeys
?.signatureKeyPair
?.wrappedSigningKey,
signedPublicKey = loginResponse.accountKeys
?.publicKeyEncryptionKeyPair
?.signedPublicKey,
),
accountProfile = profile,
privateKey = privateKey,
initUserCryptoMethod = InitUserCryptoMethod.KeyConnector(
masterKey = it.masterKey,
userKey = key,
),
securityState = loginResponse.accountKeys?.securityState?.securityState,
signingKey = loginResponse.accountKeys?.signatureKeyPair?.wrappedSigningKey,
)
}
.fold(
@ -1837,11 +1852,21 @@ class AuthRepositoryImpl(
organizationIdentifier = orgIdentifier,
)
.map { keyConnectorResponse ->
val accountKeys = loginResponse.accountKeys
val result = unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = keyConnectorResponse.keys.private,
securityState = accountKeys
?.securityState
?.securityState,
signingKey = accountKeys
?.signatureKeyPair
?.wrappedSigningKey,
signedPublicKey = accountKeys
?.publicKeyEncryptionKeyPair
?.signedPublicKey,
),
accountProfile = profile,
privateKey = keyConnectorResponse.keys.private,
securityState = loginResponse.accountKeys?.securityState?.securityState,
signingKey = loginResponse.accountKeys?.signatureKeyPair?.wrappedSigningKey,
initUserCryptoMethod = InitUserCryptoMethod.KeyConnector(
masterKey = keyConnectorResponse.masterKey,
userKey = keyConnectorResponse.encryptedUserKey,
@ -1897,10 +1922,19 @@ class AuthRepositoryImpl(
)
return unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = loginResponse.accountKeys
?.securityState
?.securityState,
signingKey = loginResponse.accountKeys
?.signatureKeyPair
?.wrappedSigningKey,
signedPublicKey = loginResponse.accountKeys
?.publicKeyEncryptionKeyPair
?.signedPublicKey,
),
accountProfile = profile,
privateKey = privateKey,
securityState = loginResponse.accountKeys?.securityState?.securityState,
signingKey = loginResponse.accountKeys?.signatureKeyPair?.wrappedSigningKey,
initUserCryptoMethod = initUserCryptoMethod,
)
}
@ -1908,6 +1942,7 @@ class AuthRepositoryImpl(
/**
* Attempt to unlock the current user's vault with trusted device specific data.
*/
@Suppress("LongMethod")
private suspend fun unlockVaultWithTdeOnLoginSuccess(
loginResponse: GetTokenResponseJson.Success,
profile: AccountJson.Profile,
@ -1920,10 +1955,19 @@ class AuthRepositoryImpl(
if (privateKey != null && key != null) {
deviceData?.let { model ->
return unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = loginResponse.accountKeys
?.securityState
?.securityState,
signingKey = loginResponse.accountKeys
?.signatureKeyPair
?.wrappedSigningKey,
signedPublicKey = loginResponse.accountKeys
?.publicKeyEncryptionKeyPair
?.signedPublicKey,
),
accountProfile = profile,
privateKey = privateKey,
securityState = loginResponse.accountKeys?.securityState?.securityState,
signingKey = loginResponse.accountKeys?.signatureKeyPair?.wrappedSigningKey,
initUserCryptoMethod = InitUserCryptoMethod.AuthRequest(
requestPrivateKey = model.privateKey,
method = model
@ -1953,9 +1997,18 @@ class AuthRepositoryImpl(
unlockVaultWithTrustedDeviceUserDecryptionOptionsAndStoreKeys(
options = options,
profile = profile,
privateKey = accountKeys.publicKeyEncryptionKeyPair.wrappedPrivateKey,
securityState = accountKeys.securityState?.securityState,
signingKey = accountKeys.signatureKeyPair?.wrappedSigningKey,
privateKey = accountKeys
.publicKeyEncryptionKeyPair
.wrappedPrivateKey,
securityState = accountKeys
.securityState
?.securityState,
signedPublicKey = accountKeys
.publicKeyEncryptionKeyPair
.signedPublicKey,
signingKey = accountKeys
.signatureKeyPair
?.wrappedSigningKey,
)
}
?: loginResponse.privateKey
@ -1965,6 +2018,7 @@ class AuthRepositoryImpl(
profile = profile,
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
)
}
@ -1980,6 +2034,7 @@ class AuthRepositoryImpl(
profile: AccountJson.Profile,
privateKey: String,
securityState: String?,
signedPublicKey: String?,
signingKey: String?,
): VaultUnlockResult? {
var vaultUnlockResult: VaultUnlockResult? = null
@ -1997,10 +2052,13 @@ class AuthRepositoryImpl(
// For approved requests the key will always be present.
val userKey = requireNotNull(request.key)
vaultUnlockResult = unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = securityState,
signingKey = signingKey,
signedPublicKey = signedPublicKey,
),
accountProfile = profile,
privateKey = privateKey,
signingKey = signingKey,
securityState = securityState,
initUserCryptoMethod = InitUserCryptoMethod.AuthRequest(
requestPrivateKey = pendingRequest.requestPrivateKey,
method = AuthRequestMethod.UserKey(protectedUserKey = userKey),
@ -2026,10 +2084,13 @@ class AuthRepositoryImpl(
}
vaultUnlockResult = unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = securityState,
signingKey = signingKey,
signedPublicKey = signedPublicKey,
),
accountProfile = profile,
privateKey = privateKey,
securityState = securityState,
signingKey = signingKey,
initUserCryptoMethod = InitUserCryptoMethod.DeviceKey(
deviceKey = deviceKey,
protectedDevicePrivateKey = encryptedPrivateKey,
@ -2047,20 +2108,16 @@ class AuthRepositoryImpl(
* A helper function to unlock the vault for the user associated with the [accountProfile].
*/
private suspend fun unlockVault(
accountCryptographicState: WrappedAccountCryptographicState,
accountProfile: AccountJson.Profile,
privateKey: String,
securityState: String?,
signingKey: String?,
initUserCryptoMethod: InitUserCryptoMethod,
): VaultUnlockResult {
val userId = accountProfile.userId
return vaultRepository.unlockVault(
accountCryptographicState = accountCryptographicState,
userId = userId,
email = accountProfile.email,
kdf = accountProfile.toSdkParams(),
privateKey = privateKey,
signingKey = signingKey,
securityState = securityState,
initUserCryptoMethod = initUserCryptoMethod,
// The value for the organization keys here will typically be null. We can separately
// unlock the vault for organization data after receiving the sync response if this

View File

@ -258,6 +258,7 @@ class BitwardenCredentialManagerImpl(
userId = userId,
fido2CredentialStore = fido2CredentialStore,
relyingPartyId = relyingPartyId,
userHandle = null,
)
.fold(
onSuccess = { it },

View File

@ -16,6 +16,7 @@ import com.x8bit.bitwarden.data.vault.datasource.disk.VaultDiskSource
import com.x8bit.bitwarden.data.vault.datasource.sdk.ScopedVaultSdkSource
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.InitializeCryptoResult
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
import com.x8bit.bitwarden.data.vault.repository.util.createWrappedAccountCryptographicState
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkCipher
import com.x8bit.bitwarden.data.vault.repository.util.toVaultUnlockResult
@ -137,17 +138,21 @@ class AuthenticatorBridgeRepositoryImpl(
?.securityState
?.securityState
val signingKey = accountKeys?.signatureKeyPair?.wrappedSigningKey
val signedPublicKey = accountKeys?.publicKeyEncryptionKeyPair?.signedPublicKey
return scopedVaultSdkSource
.initializeCrypto(
userId = userId,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = securityState,
signingKey = signingKey,
signedPublicKey = signedPublicKey,
),
userId = userId,
kdfParams = account.profile.toSdkParams(),
email = account.profile.email,
privateKey = privateKey,
securityState = securityState,
signingKey = signingKey,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = decryptedUserKey,
),

View File

@ -487,6 +487,7 @@ interface VaultSdkSource {
userId: String,
fido2CredentialStore: Fido2CredentialStore,
relyingPartyId: String,
userHandle: String?,
): Result<List<Fido2CredentialAutofillView>>
/**

View File

@ -599,6 +599,7 @@ class VaultSdkSourceImpl(
userId: String,
fido2CredentialStore: Fido2CredentialStore,
relyingPartyId: String,
userHandle: String?,
): Result<List<Fido2CredentialAutofillView>> = runCatchingWithLogs {
getClient(userId)
.platform()
@ -607,7 +608,7 @@ class VaultSdkSourceImpl(
userInterface = Fido2CredentialSearchUserInterfaceImpl(),
credentialStore = fido2CredentialStore,
)
.silentlyDiscoverCredentials(relyingPartyId)
.silentlyDiscoverCredentials(relyingPartyId, userHandle?.toByteArray())
}
override suspend fun makeUpdateKdf(

View File

@ -28,7 +28,7 @@ class Fido2CredentialAuthenticationUserInterfaceImpl(
newCredential: Fido2CredentialNewView,
): CheckUserAndPickCredentialForCreationResult = throw IllegalStateException()
override suspend fun isVerificationEnabled(): Boolean = isVerificationSupported
override fun isVerificationEnabled(): Boolean = isVerificationSupported
override suspend fun pickCredentialForAuthentication(
availableCredentials: List<CipherView>,

View File

@ -32,7 +32,7 @@ class Fido2CredentialRegistrationUserInterfaceImpl(
checkUserResult = CheckUserResult(userPresent = true, userVerified = true),
)
override suspend fun isVerificationEnabled(): Boolean = isVerificationSupported
override fun isVerificationEnabled(): Boolean = isVerificationSupported
override suspend fun pickCredentialForAuthentication(
availableCredentials: List<CipherView>,

View File

@ -29,7 +29,7 @@ class Fido2CredentialSearchUserInterfaceImpl : Fido2UserInterface {
// Always return true for this property because any problems with verification should
// be handled downstream where the app can actually offer verification methods.
override suspend fun isVerificationEnabled(): Boolean = true
override fun isVerificationEnabled(): Boolean = true
override suspend fun pickCredentialForAuthentication(
availableCredentials: List<CipherView>,

View File

@ -42,7 +42,11 @@ class Fido2CredentialStoreImpl(
* @param ids Optional list of FIDO 2 credential ID's to find.
* @param ripId Relying Party ID to find.
*/
override suspend fun findCredentials(ids: List<ByteArray>?, ripId: String): List<CipherView> =
override suspend fun findCredentials(
ids: List<ByteArray>?,
ripId: String,
userHandle: ByteArray?,
): List<CipherView> =
vaultRepository
.decryptCipherListResultStateFlow
.value

View File

@ -1,6 +1,7 @@
package com.x8bit.bitwarden.data.vault.manager
import com.bitwarden.core.InitUserCryptoMethod
import com.bitwarden.core.WrappedAccountCryptographicState
import com.bitwarden.crypto.Kdf
import com.bitwarden.sdk.AuthClient
import com.x8bit.bitwarden.data.vault.manager.model.VaultStateEvent
@ -61,12 +62,10 @@ interface VaultLockManager {
*/
@Suppress("LongParameterList")
suspend fun unlockVault(
accountCryptographicState: WrappedAccountCryptographicState,
userId: String,
email: String,
kdf: Kdf,
privateKey: String,
signingKey: String?,
securityState: String?,
initUserCryptoMethod: InitUserCryptoMethod,
organizationKeys: Map<String, String>?,
): VaultUnlockResult

View File

@ -7,6 +7,7 @@ import android.content.IntentFilter
import com.bitwarden.core.InitOrgCryptoRequest
import com.bitwarden.core.InitUserCryptoMethod
import com.bitwarden.core.InitUserCryptoRequest
import com.bitwarden.core.WrappedAccountCryptographicState
import com.bitwarden.core.data.manager.dispatcher.DispatcherManager
import com.bitwarden.core.data.manager.realtime.RealtimeManager
import com.bitwarden.core.data.repository.error.MissingPropertyException
@ -39,6 +40,7 @@ import com.x8bit.bitwarden.data.vault.datasource.sdk.model.InitializeCryptoResul
import com.x8bit.bitwarden.data.vault.manager.model.VaultStateEvent
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockData
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
import com.x8bit.bitwarden.data.vault.repository.util.createWrappedAccountCryptographicState
import com.x8bit.bitwarden.data.vault.repository.util.logTag
import com.x8bit.bitwarden.data.vault.repository.util.statusFor
import com.x8bit.bitwarden.data.vault.repository.util.toVaultUnlockResult
@ -171,12 +173,10 @@ class VaultLockManagerImpl(
@Suppress("LongMethod")
override suspend fun unlockVault(
accountCryptographicState: WrappedAccountCryptographicState,
userId: String,
email: String,
kdf: Kdf,
privateKey: String,
signingKey: String?,
securityState: String?,
initUserCryptoMethod: InitUserCryptoMethod,
organizationKeys: Map<String, String>?,
): VaultUnlockResult = withContext(context = NonCancellable) {
@ -187,13 +187,11 @@ class VaultLockManagerImpl(
.initializeCrypto(
userId = userId,
request = InitUserCryptoRequest(
accountCryptographicState = accountCryptographicState,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = initUserCryptoMethod,
userId = userId,
signingKey = signingKey,
securityState = securityState,
),
)
.flatMap { result ->
@ -683,14 +681,18 @@ class VaultLockManagerImpl(
)
val signingKey = accountKeys?.signatureKeyPair?.wrappedSigningKey
val securityState = accountKeys?.securityState?.securityState
val signedPublicKey = accountKeys?.publicKeyEncryptionKeyPair?.signedPublicKey
val organizationKeys = authDiskSource.getOrganizationKeys(userId = userId)
return unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = securityState,
signingKey = signingKey,
signedPublicKey = signedPublicKey,
),
userId = userId,
email = account.profile.email,
kdf = account.profile.toSdkParams(),
privateKey = privateKey,
signingKey = signingKey,
securityState = securityState,
initUserCryptoMethod = initUserCryptoMethod,
organizationKeys = organizationKeys,
)

View File

@ -92,6 +92,7 @@ interface VaultRepository :
userId: String,
fido2CredentialStore: Fido2CredentialStore,
relyingPartyId: String,
userHandle: String?,
): Result<List<Fido2CredentialAutofillView>>
/**

View File

@ -41,6 +41,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.GenerateTotpResult
import com.x8bit.bitwarden.data.vault.repository.model.ImportCredentialsResult
import com.x8bit.bitwarden.data.vault.repository.model.TotpCodeResult
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
import com.x8bit.bitwarden.data.vault.repository.util.createWrappedAccountCryptographicState
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkCipher
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkFolder
import com.x8bit.bitwarden.data.vault.repository.util.toSdkAccount
@ -253,12 +254,14 @@ class VaultRepositoryImpl(
userId: String,
fido2CredentialStore: Fido2CredentialStore,
relyingPartyId: String,
userHandle: String?,
): Result<List<Fido2CredentialAutofillView>> =
vaultSdkSource
.silentlyDiscoverCredentials(
userId = userId,
fido2CredentialStore = fido2CredentialStore,
relyingPartyId = relyingPartyId,
userHandle = userHandle,
)
override fun emitTotpCodeResult(totpCodeResult: TotpCodeResult) {
@ -537,15 +540,19 @@ class VaultRepositoryImpl(
)
val signingKey = accountKeys?.signatureKeyPair?.wrappedSigningKey
val securityState = accountKeys?.securityState?.securityState
val signedPublicKey = accountKeys?.publicKeyEncryptionKeyPair?.signedPublicKey
val organizationKeys = authDiskSource
.getOrganizationKeys(userId = userId)
return vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = securityState,
signingKey = signingKey,
signedPublicKey = signedPublicKey,
),
userId = userId,
email = account.profile.email,
kdf = account.profile.toSdkParams(),
privateKey = privateKey,
signingKey = signingKey,
securityState = securityState,
initUserCryptoMethod = initUserCryptoMethod,
organizationKeys = organizationKeys,
)

View File

@ -0,0 +1,34 @@
package com.x8bit.bitwarden.data.vault.repository.util
import com.bitwarden.core.WrappedAccountCryptographicState
/**
* Creates a [WrappedAccountCryptographicState] based on the available cryptographic parameters.
*
* Returns [WrappedAccountCryptographicState.V2] if signing key, signed public key, and security
* state are all present, otherwise returns [WrappedAccountCryptographicState.V1].
*
* @param privateKey The user's wrapped private key.
* @param securityState The user's signed security state (V2 only).
* @param signingKey The user's wrapped signing key (V2 only).
* @param signedPublicKey The user's signed public key (V2 only).
*/
fun createWrappedAccountCryptographicState(
privateKey: String,
securityState: String?,
signingKey: String?,
signedPublicKey: String?,
): WrappedAccountCryptographicState {
return if (signingKey != null && securityState != null && signedPublicKey != null) {
WrappedAccountCryptographicState.V2(
privateKey = privateKey,
securityState = securityState,
signingKey = signingKey,
signedPublicKey = signedPublicKey,
)
} else {
WrappedAccountCryptographicState.V1(
privateKey = privateKey,
)
}
}

View File

@ -1165,6 +1165,7 @@ class BitwardenCredentialManagerTest {
userId = "mockUserId",
fido2CredentialStore = any(),
relyingPartyId = "mockRpId-1",
userHandle = null,
)
} returns fido2CredentialAutofillViews.asSuccess()
every {
@ -1304,6 +1305,7 @@ class BitwardenCredentialManagerTest {
userId = "mockUserId",
fido2CredentialStore = any(),
relyingPartyId = "mockRpId-1",
userHandle = null,
)
} returns fido2CredentialAutofillViews.asSuccess()
every {
@ -1425,6 +1427,7 @@ class BitwardenCredentialManagerTest {
userId = "mockUserId",
fido2CredentialStore = any(),
relyingPartyId = "mockRpId-1",
userHandle = null,
)
} returns fido2CredentialAutofillViews.asSuccess()
every {

View File

@ -23,6 +23,7 @@ import com.x8bit.bitwarden.data.platform.repository.util.sanitizeTotpUri
import com.x8bit.bitwarden.data.vault.datasource.disk.VaultDiskSource
import com.x8bit.bitwarden.data.vault.datasource.sdk.ScopedVaultSdkSource
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.InitializeCryptoResult
import com.x8bit.bitwarden.data.vault.repository.util.createWrappedAccountCryptographicState
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkCipher
import io.mockk.coEvery
import io.mockk.coVerify
@ -86,15 +87,18 @@ class AuthenticatorBridgeRepositoryTest {
scopedVaultSdkSource.initializeCrypto(
userId = USER_1_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = USER_1_PRIVATE_KEY,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_1_ID,
kdfParams = Kdf.Argon2id(iterations = 0U, memory = 0U, parallelism = 0U),
email = USER_1_EMAIL,
privateKey = USER_1_PRIVATE_KEY,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = USER_1_UNLOCK_KEY,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -102,15 +106,18 @@ class AuthenticatorBridgeRepositoryTest {
scopedVaultSdkSource.initializeCrypto(
userId = USER_2_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = USER_2_PRIVATE_KEY,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_2_ID,
kdfParams = Kdf.Argon2id(iterations = 0U, memory = 0U, parallelism = 0U),
email = USER_2_EMAIL,
privateKey = USER_2_PRIVATE_KEY,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = USER_2_UNLOCK_KEY,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -200,15 +207,18 @@ class AuthenticatorBridgeRepositoryTest {
scopedVaultSdkSource.initializeCrypto(
userId = USER_2_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = USER_2_PRIVATE_KEY,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_2_ID,
kdfParams = Kdf.Argon2id(iterations = 0U, memory = 0U, parallelism = 0U),
email = USER_2_EMAIL,
privateKey = USER_2_PRIVATE_KEY,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = USER_2_UNLOCK_KEY,
),
signingKey = null,
securityState = null,
),
)
scopedVaultSdkSource.initializeOrganizationCrypto(
@ -239,15 +249,18 @@ class AuthenticatorBridgeRepositoryTest {
scopedVaultSdkSource.initializeCrypto(
userId = USER_1_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = USER_1_PRIVATE_KEY,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_1_ID,
kdfParams = Kdf.Argon2id(iterations = 0U, memory = 0U, parallelism = 0U),
email = USER_1_EMAIL,
privateKey = USER_1_PRIVATE_KEY,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = USER_1_UNLOCK_KEY,
),
signingKey = null,
securityState = null,
),
)
scopedVaultSdkSource.initializeOrganizationCrypto(
@ -262,15 +275,18 @@ class AuthenticatorBridgeRepositoryTest {
scopedVaultSdkSource.initializeCrypto(
userId = USER_2_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = USER_2_PRIVATE_KEY,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_2_ID,
kdfParams = Kdf.Argon2id(iterations = 0U, memory = 0U, parallelism = 0U),
email = USER_2_EMAIL,
privateKey = USER_2_PRIVATE_KEY,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = USER_2_UNLOCK_KEY,
),
signingKey = null,
securityState = null,
),
)
scopedVaultSdkSource.initializeOrganizationCrypto(
@ -297,15 +313,18 @@ class AuthenticatorBridgeRepositoryTest {
scopedVaultSdkSource.initializeCrypto(
userId = USER_1_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = USER_1_PRIVATE_KEY,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_1_ID,
kdfParams = Kdf.Argon2id(iterations = 0U, memory = 0U, parallelism = 0U),
email = USER_1_EMAIL,
privateKey = USER_1_PRIVATE_KEY,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = USER_1_UNLOCK_KEY,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.AuthenticationError(error = Throwable()).asSuccess()
@ -319,29 +338,35 @@ class AuthenticatorBridgeRepositoryTest {
scopedVaultSdkSource.initializeCrypto(
userId = USER_1_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = USER_1_PRIVATE_KEY,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_1_ID,
kdfParams = Kdf.Argon2id(iterations = 0U, memory = 0U, parallelism = 0U),
email = USER_1_EMAIL,
privateKey = USER_1_PRIVATE_KEY,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = USER_1_UNLOCK_KEY,
),
signingKey = null,
securityState = null,
),
)
scopedVaultSdkSource.initializeCrypto(
userId = USER_2_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = USER_2_PRIVATE_KEY,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_2_ID,
kdfParams = Kdf.Argon2id(iterations = 0U, memory = 0U, parallelism = 0U),
email = USER_2_EMAIL,
privateKey = USER_2_PRIVATE_KEY,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = USER_2_UNLOCK_KEY,
),
signingKey = null,
securityState = null,
),
)
scopedVaultSdkSource.initializeOrganizationCrypto(

View File

@ -1394,18 +1394,24 @@ class VaultSdkSourceTest {
val userId = "userId"
val fido2CredentialStore: Fido2CredentialStore = mockk()
val relyingPartyId = "relyingPartyId"
val userHandle = "mockUserHandle"
val mockAutofillView = Fido2CredentialAutofillView(
credentialId = byteArrayOf(0),
cipherId = "mockCipherId",
rpId = "mockRpId",
userNameForUi = "mockUserNameForUi",
userHandle = "mockUserHandle".toByteArray(),
userHandle = userHandle.toByteArray(),
hasCounter = false,
)
val autofillViews = listOf(mockAutofillView)
val authenticator: ClientFido2Authenticator = mockk {
coEvery { silentlyDiscoverCredentials(relyingPartyId) } returns autofillViews
coEvery {
silentlyDiscoverCredentials(
relyingPartyId,
userHandle.toByteArray(),
)
} returns autofillViews
}
every {
clientFido2.authenticator(
@ -1418,6 +1424,7 @@ class VaultSdkSourceTest {
userId = userId,
fido2CredentialStore = fido2CredentialStore,
relyingPartyId = relyingPartyId,
userHandle = userHandle,
)
assertEquals(
@ -1432,6 +1439,7 @@ class VaultSdkSourceTest {
val userId = "userId"
val fido2CredentialStore: Fido2CredentialStore = mockk()
val relyingPartyId = "relyingPartyId"
val userHandle = "mockUserHandle"
coEvery {
clientFido2
@ -1439,7 +1447,10 @@ class VaultSdkSourceTest {
userInterface = Fido2CredentialSearchUserInterfaceImpl(),
credentialStore = fido2CredentialStore,
)
.silentlyDiscoverCredentials(relyingPartyId)
.silentlyDiscoverCredentials(
relyingPartyId,
userHandle.toByteArray(),
)
} throws BitwardenException.SilentlyDiscoverCredentials(
mockk<SilentlyDiscoverCredentialsException>("mockException"),
)
@ -1448,6 +1459,7 @@ class VaultSdkSourceTest {
userId = userId,
fido2CredentialStore = fido2CredentialStore,
relyingPartyId = relyingPartyId,
userHandle = userHandle,
)
assertTrue(result.isFailure)

View File

@ -18,7 +18,6 @@ fun createMockPublicKeyAssertionResponse(number: Int) =
clientExtensionResults = ClientExtensionResults(
credProps = CredPropsResult(
rk = true,
authenticatorDisplayName = "mockAuthenticatorDisplayName-$number",
),
),
response = AuthenticatorAssertionResponse(

View File

@ -18,7 +18,6 @@ fun createMockPublicKeyAttestationResponse(number: Int) =
clientExtensionResults = ClientExtensionResults(
credProps = CredPropsResult(
rk = true,
authenticatorDisplayName = "mockDisplayName",
),
),
response = AuthenticatorAttestationResponse(

View File

@ -61,7 +61,6 @@ class PublicKeyCredentialAuthenticatorAssertionResponseExtensionsTest {
number = 1,
credProps = CredPropsResult(
rk = true,
authenticatorDisplayName = null,
),
)
val result = mockSdkResponse.toAndroidFido2PublicKeyCredential()
@ -74,7 +73,6 @@ class PublicKeyCredentialAuthenticatorAssertionResponseExtensionsTest {
number = 1,
credProps = CredPropsResult(
rk = null,
authenticatorDisplayName = null,
),
)
val result = mockSdkResponse.toAndroidFido2PublicKeyCredential()

View File

@ -60,7 +60,6 @@ class PublicKeyCredentialAuthenticatorAttestationResponseExtensionsTest {
number = 1,
credProps = CredPropsResult(
rk = true,
authenticatorDisplayName = null,
),
)
val result = mockSdkResponse.toAndroidAttestationResponse(callingPackageName = "")

View File

@ -37,6 +37,7 @@ import com.x8bit.bitwarden.data.vault.datasource.sdk.model.InitializeCryptoResul
import com.x8bit.bitwarden.data.vault.manager.model.VaultStateEvent
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockData
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
import com.x8bit.bitwarden.data.vault.repository.util.createWrappedAccountCryptographicState
import io.mockk.clearMocks
import io.mockk.coEvery
import io.mockk.coVerify
@ -760,15 +761,18 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = MOCK_PROFILE.toSdkParams(),
email = MOCK_PROFILE.email,
privateKey = privateKey,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = userAutoUnlockKey,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -786,15 +790,18 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = MOCK_PROFILE.toSdkParams(),
email = MOCK_PROFILE.email,
privateKey = privateKey,
method = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = userAutoUnlockKey,
),
signingKey = null,
securityState = null,
),
)
trustedDeviceManager.trustThisDeviceIfNecessary(userId = USER_ID)
@ -918,16 +925,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -951,12 +961,15 @@ class VaultLockManagerTest {
)
val result = vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
@ -987,16 +1000,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
vaultSdkSource.initializeOrganizationCrypto(
@ -1022,16 +1038,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -1064,12 +1083,15 @@ class VaultLockManagerTest {
}
val result = vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
@ -1102,16 +1124,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
vaultSdkSource.initializeOrganizationCrypto(
@ -1137,16 +1162,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.AuthenticationError(error = error).asSuccess()
@ -1161,12 +1189,15 @@ class VaultLockManagerTest {
)
val result = vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
@ -1187,16 +1218,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
}
@ -1215,16 +1249,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -1246,12 +1283,15 @@ class VaultLockManagerTest {
)
val result = vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
@ -1272,16 +1312,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
}
@ -1307,16 +1350,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
} returns error.asFailure()
@ -1330,12 +1376,15 @@ class VaultLockManagerTest {
)
val result = vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
@ -1356,16 +1405,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
}
@ -1384,16 +1436,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -1414,12 +1469,15 @@ class VaultLockManagerTest {
)
val result = vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
@ -1440,16 +1498,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
}
@ -1474,16 +1535,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -1504,12 +1568,15 @@ class VaultLockManagerTest {
)
val result = vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
@ -1537,16 +1604,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
}
@ -1646,16 +1716,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -1675,12 +1748,15 @@ class VaultLockManagerTest {
mutableVaultTimeoutStateFlow.value = VaultTimeout.ThirtyMinutes
val result = vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
@ -1703,16 +1779,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
vaultSdkSource.initializeOrganizationCrypto(
@ -1741,13 +1820,16 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = initUserCryptoMethod,
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -1771,12 +1853,15 @@ class VaultLockManagerTest {
)
val result = vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = initUserCryptoMethod,
organizationKeys = organizationKeys,
)
@ -1804,13 +1889,16 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = USER_ID,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = USER_ID,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = initUserCryptoMethod,
signingKey = null,
securityState = null,
),
)
vaultSdkSource.initializeOrganizationCrypto(
@ -1852,16 +1940,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = userId,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
} coAnswers {
@ -1870,12 +1961,15 @@ class VaultLockManagerTest {
}
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MasterPasswordUnlockData(
@ -1905,16 +1999,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = userId,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
} returns InitializeCryptoResult.Success.asSuccess()
@ -1926,12 +2023,15 @@ class VaultLockManagerTest {
} returns true.asSuccess()
val result = vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = email,
kdf = kdf,
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
@ -1944,16 +2044,19 @@ class VaultLockManagerTest {
vaultSdkSource.initializeCrypto(
userId = userId,
request = InitUserCryptoRequest(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
kdfParams = kdf,
email = email,
privateKey = privateKey,
method = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = MOCK_MASTER_PASSWORD_UNLOCK_DATA,
),
signingKey = null,
securityState = null,
),
)
}

View File

@ -56,6 +56,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.ImportCredentialsResult
import com.x8bit.bitwarden.data.vault.repository.model.SendData
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
import com.x8bit.bitwarden.data.vault.repository.util.createWrappedAccountCryptographicState
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkCipher
import com.x8bit.bitwarden.data.vault.repository.util.toSdkMasterPasswordUnlock
import com.x8bit.bitwarden.ui.vault.feature.verificationcode.util.createVerificationCodeItem
@ -258,12 +259,15 @@ class VaultRepositoryTest {
}
coEvery {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = encryptedBytes.toString(Charsets.ISO_8859_1),
),
@ -281,12 +285,15 @@ class VaultRepositoryTest {
assertEquals(VaultUnlockResult.Success, result)
coVerify(exactly = 1) {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = encryptedBytes.toString(Charsets.ISO_8859_1),
),
@ -311,12 +318,15 @@ class VaultRepositoryTest {
}
coEvery {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = biometricsKey,
),
@ -334,12 +344,15 @@ class VaultRepositoryTest {
assertEquals(VaultUnlockResult.Success, result)
coVerify {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = biometricsKey,
),
@ -368,12 +381,15 @@ class VaultRepositoryTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
coEvery {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = authenticatorSyncUnlockKey,
),
@ -395,12 +411,15 @@ class VaultRepositoryTest {
assertEquals(VaultUnlockResult.Success, result)
coVerify {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = authenticatorSyncUnlockKey,
),
@ -420,12 +439,15 @@ class VaultRepositoryTest {
val error = Throwable("Fail")
coEvery {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = privateKey,
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = privateKey,
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = authenticatorSyncUnlockKey,
),
@ -447,12 +469,15 @@ class VaultRepositoryTest {
assertEquals(VaultUnlockResult.InvalidStateError(error = error), result)
coVerify {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
decryptedUserKey = authenticatorSyncUnlockKey,
),
@ -531,12 +556,15 @@ class VaultRepositoryTest {
)
coVerify {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = "mockPassword-1",
masterPasswordUnlock = MasterPasswordUnlockData(
@ -585,12 +613,15 @@ class VaultRepositoryTest {
coEvery {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = masterPasswordUnlockData,
@ -606,12 +637,15 @@ class VaultRepositoryTest {
assertEquals(VaultUnlockResult.Success, result)
coVerify {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = masterPassword,
masterPasswordUnlock = masterPasswordUnlockData,
@ -647,7 +681,7 @@ class VaultRepositoryTest {
assertTrue(result is VaultUnlockResult.InvalidStateError)
coVerify(exactly = 0) {
vaultLockManager.unlockVault(any(), any(), any(), any(), any(), any(), any(), any())
vaultLockManager.unlockVault(any(), any(), any(), any(), any(), any())
}
}
@ -669,12 +703,15 @@ class VaultRepositoryTest {
)
coVerify {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = "mockPassword-1",
masterPasswordUnlock = MasterPasswordUnlockData(
@ -762,12 +799,15 @@ class VaultRepositoryTest {
)
coVerify {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.PinEnvelope(
pin = "1234",
pinProtectedUserKeyEnvelope = "mockKey-1",
@ -797,12 +837,15 @@ class VaultRepositoryTest {
)
coVerify {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.Pin(
pin = "1234",
pinProtectedUserKey = "mockKey-1",
@ -828,12 +871,15 @@ class VaultRepositoryTest {
)
coVerify {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.PinEnvelope(
pin = "1234",
pinProtectedUserKeyEnvelope = "mockKey-1",
@ -1364,12 +1410,14 @@ class VaultRepositoryTest {
val userId = "userId"
val fido2CredentialStore: Fido2CredentialStore = mockk()
val relyingPartyId = "relyingPartyId"
val userHandle = "mockUserHandle"
val expected: List<Fido2CredentialAutofillView> = mockk()
coEvery {
vaultSdkSource.silentlyDiscoverCredentials(
userId = userId,
fido2CredentialStore = fido2CredentialStore,
relyingPartyId = relyingPartyId,
userHandle = userHandle,
)
} returns expected.asSuccess()
@ -1377,6 +1425,7 @@ class VaultRepositoryTest {
userId = userId,
fido2CredentialStore = fido2CredentialStore,
relyingPartyId = relyingPartyId,
userHandle = userHandle,
)
assertEquals(expected.asSuccess(), result)
@ -1386,6 +1435,7 @@ class VaultRepositoryTest {
userId = userId,
fido2CredentialStore = fido2CredentialStore,
relyingPartyId = relyingPartyId,
userHandle = userHandle,
)
}
}
@ -1529,12 +1579,15 @@ class VaultRepositoryTest {
// Master password unlock
coEvery {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.MasterPasswordUnlock(
password = mockMasterPassword,
masterPasswordUnlock = MasterPasswordUnlockData(
@ -1550,12 +1603,15 @@ class VaultRepositoryTest {
// PIN unlock
coEvery {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.Pin(
pin = mockPin,
pinProtectedUserKey = "mockKey-1",
@ -1567,12 +1623,15 @@ class VaultRepositoryTest {
// PIN ENVELOPE unlock
coEvery {
vaultLockManager.unlockVault(
accountCryptographicState = createWrappedAccountCryptographicState(
privateKey = "mockPrivateKey-1",
securityState = null,
signedPublicKey = null,
signingKey = null,
),
userId = userId,
email = "email",
kdf = MOCK_PROFILE.toSdkParams(),
privateKey = "mockPrivateKey-1",
signingKey = null,
securityState = null,
initUserCryptoMethod = InitUserCryptoMethod.PinEnvelope(
pin = mockPin,
pinProtectedUserKeyEnvelope = "mockKey-1",

View File

@ -0,0 +1,111 @@
package com.x8bit.bitwarden.data.vault.repository.util
import com.bitwarden.core.WrappedAccountCryptographicState
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
private const val PRIVATE_KEY = "test-private-key"
private const val SECURITY_STATE = "test-security-state"
private const val SIGNING_KEY = "test-signing-key"
private const val SIGNED_PUBLIC_KEY = "test-signed-public-key"
class WrappedAccountCryptographicStateExtensionsTest {
@Suppress("MaxLineLength")
@Test
fun `createWrappedAccountCryptographicState returns V2 when securityState, signedPublicKey and signingKey are non-null`() {
val result = createWrappedAccountCryptographicState(
privateKey = PRIVATE_KEY,
securityState = SECURITY_STATE,
signedPublicKey = SIGNED_PUBLIC_KEY,
signingKey = SIGNING_KEY,
)
val v2State = result as WrappedAccountCryptographicState.V2
assertEquals(PRIVATE_KEY, v2State.privateKey)
assertEquals(SECURITY_STATE, v2State.securityState)
assertEquals(SIGNED_PUBLIC_KEY, v2State.signedPublicKey)
assertEquals(SIGNING_KEY, v2State.signingKey)
}
@Test
fun `createWrappedAccountCryptographicState returns V1 when securityState is null`() {
val result = createWrappedAccountCryptographicState(
privateKey = PRIVATE_KEY,
securityState = null,
signedPublicKey = SIGNED_PUBLIC_KEY,
signingKey = SIGNING_KEY,
)
val v1State = result as WrappedAccountCryptographicState.V1
assertEquals(PRIVATE_KEY, v1State.privateKey)
}
@Test
fun `createWrappedAccountCryptographicState returns V1 when signedPublicKey is null`() {
val result = createWrappedAccountCryptographicState(
privateKey = PRIVATE_KEY,
securityState = SECURITY_STATE,
signedPublicKey = null,
signingKey = SIGNING_KEY,
)
val v1State = result as WrappedAccountCryptographicState.V1
assertEquals(PRIVATE_KEY, v1State.privateKey)
}
@Test
fun `createWrappedAccountCryptographicState returns V1 when signingKey is null`() {
val result = createWrappedAccountCryptographicState(
privateKey = PRIVATE_KEY,
securityState = SECURITY_STATE,
signedPublicKey = SIGNED_PUBLIC_KEY,
signingKey = null,
)
val v1State = result as WrappedAccountCryptographicState.V1
assertEquals(PRIVATE_KEY, v1State.privateKey)
}
@Suppress("MaxLineLength")
@Test
fun `createWrappedAccountCryptographicState returns V1 when both securityState and signedPublicKey are null`() {
val result = createWrappedAccountCryptographicState(
privateKey = PRIVATE_KEY,
securityState = null,
signedPublicKey = null,
signingKey = SIGNING_KEY,
)
val v1State = result as WrappedAccountCryptographicState.V1
assertEquals(PRIVATE_KEY, v1State.privateKey)
}
@Suppress("MaxLineLength")
@Test
fun `createWrappedAccountCryptographicState returns V1 when both securityState and signingKey are null`() {
val result = createWrappedAccountCryptographicState(
privateKey = PRIVATE_KEY,
securityState = null,
signedPublicKey = SIGNED_PUBLIC_KEY,
signingKey = null,
)
val v1State = result as WrappedAccountCryptographicState.V1
assertEquals(PRIVATE_KEY, v1State.privateKey)
}
@Suppress("MaxLineLength")
@Test
fun `createWrappedAccountCryptographicState returns V1 when both signedPublicKey and signingKey are null`() {
val result = createWrappedAccountCryptographicState(
privateKey = PRIVATE_KEY,
securityState = SECURITY_STATE,
signedPublicKey = null,
signingKey = null,
)
val v1State = result as WrappedAccountCryptographicState.V1
assertEquals(PRIVATE_KEY, v1State.privateKey)
}
}

View File

@ -30,7 +30,7 @@ androidxRoom = "2.8.4"
androidxSecurityCrypto = "1.1.0"
androidxSplash = "1.2.0"
androidxWork = "2.11.0"
bitwardenSdk = "1.0.0-4328-km-fix-cherry-pick"
bitwardenSdk = "2.0.0-4254-6c954013"
crashlytics = "3.0.6"
detekt = "1.23.8"
firebaseBom = "34.5.0"
@ -97,7 +97,7 @@ androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "
androidx-security-crypto = { module = "androidx.security:security-crypto", version.ref = "androidxSecurityCrypto" }
androidx-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "androidxSplash" }
androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "androidxWork" }
bitwarden-sdk = { module = "com.bitwarden:sdk-android.dev", version.ref = "bitwardenSdk" }
bitwarden-sdk = { module = "com.bitwarden:sdk-android", version.ref = "bitwardenSdk" }
bumptech-glide = { module = "com.github.bumptech.glide:compose", version.ref = "glide" }
detekt-detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
detekt-detekt-rules = { module = "io.gitlab.arturbosch.detekt:detekt-rules-libraries", version.ref = "detekt" }

View File

@ -7,9 +7,9 @@ fun createMockAccountKeysJson(
number: Int,
): AccountKeysJson =
AccountKeysJson(
signatureKeyPair = createMockSignatureKeyPair(number = number),
publicKeyEncryptionKeyPair = createMockPublicKeyEncryptionKeyPair(number = number),
securityState = createMockSecurityState(number = number),
signatureKeyPair = createMockSignatureKeyPair(number = number),
)
/**
@ -53,3 +53,18 @@ fun createMockSignatureKeyPair(
wrappedSigningKey = wrappedSigningKey,
verifyingKey = verifyingKey,
)
/**
* Create a mock set of account keys with null nested fields for testing null-safety.
*/
fun createMockAccountKeysJsonWithNullFields(
number: Int,
): AccountKeysJson =
AccountKeysJson(
publicKeyEncryptionKeyPair = createMockPublicKeyEncryptionKeyPair(
number = number,
signedPublicKey = null,
),
securityState = null,
signatureKeyPair = null,
)