Run detekt on authenticatorbridge module (#4940)

This commit is contained in:
Patrick Honkonen
2025-03-31 10:22:18 -04:00
committed by GitHub
parent 2e11c81f45
commit 6369b20f18
9 changed files with 42 additions and 46 deletions

View File

@@ -1,7 +1,5 @@
package com.bitwarden.authenticatorbridge.manager
import android.content.Intent
import android.net.Uri
import com.bitwarden.authenticatorbridge.IAuthenticatorBridgeService
import com.bitwarden.authenticatorbridge.manager.model.AccountSyncState
import kotlinx.coroutines.flow.StateFlow

View File

@@ -7,7 +7,6 @@ import android.content.ServiceConnection
import android.content.pm.PackageManager.NameNotFoundException
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
@@ -46,7 +45,8 @@ private const val AUTHENTICATOR_BRIDGE_SERVICE_CLASS =
internal class AuthenticatorBridgeManagerImpl(
private val connectionType: AuthenticatorBridgeConnectionType,
private val symmetricKeyStorageProvider: SymmetricKeyStorageProvider,
callbackProvider: AuthenticatorBridgeCallbackProvider = StubAuthenticatorBridgeCallbackProvider(),
callbackProvider: AuthenticatorBridgeCallbackProvider =
StubAuthenticatorBridgeCallbackProvider(),
context: Context,
processLifecycleOwner: LifecycleOwner = ProcessLifecycleOwner.get(),
) : AuthenticatorBridgeManager {
@@ -67,7 +67,7 @@ internal class AuthenticatorBridgeManagerImpl(
isBuildVersionBelow(Build.VERSION_CODES.S) -> AccountSyncState.OsVersionNotSupported
!isBitwardenAppInstalled() -> AccountSyncState.AppNotInstalled
else -> AccountSyncState.Loading
}
},
)
/**
@@ -117,7 +117,7 @@ internal class AuthenticatorBridgeManagerImpl(
}
?.fold(
onFailure = { false },
onSuccess = { true }
onSuccess = { true },
)
?: false
@@ -201,7 +201,6 @@ internal class AuthenticatorBridgeManagerImpl(
return
},
)
}
if (symmetricKeyStorageProvider.symmetricKey == null) {

View File

@@ -30,7 +30,7 @@ sealed class AccountSyncState {
/**
* OS version can't support account syncing.
*/
data object OsVersionNotSupported: AccountSyncState()
data object OsVersionNotSupported : AccountSyncState()
/**
* Accounts successfully synced.

View File

@@ -1,7 +1,5 @@
package com.bitwarden.authenticatorbridge.model
import java.time.Instant
/**
* Domain level model representing shared account data.
*

View File

@@ -1,9 +1,7 @@
package com.bitwarden.authenticatorbridge.model
import kotlinx.serialization.Contextual
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.time.Instant
/**
* Models a serializable list of shared accounts to be shared with other applications.
@@ -46,5 +44,3 @@ internal data class SharedAccountDataJson(
val totpUris: List<String>,
)
}

View File

@@ -1,3 +1,5 @@
@file:Suppress("TooManyFunctions")
package com.bitwarden.authenticatorbridge.util
import android.security.keystore.KeyProperties
@@ -11,7 +13,6 @@ import com.bitwarden.authenticatorbridge.model.SharedAccountDataJson
import com.bitwarden.authenticatorbridge.model.SymmetricEncryptionKeyData
import com.bitwarden.authenticatorbridge.model.SymmetricEncryptionKeyFingerprintData
import com.bitwarden.authenticatorbridge.model.toByteArrayContainer
import kotlinx.serialization.encodeToString
import java.security.MessageDigest
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
@@ -25,6 +26,7 @@ import javax.crypto.spec.SecretKeySpec
* This is intended to be used for implementing
* [IAuthenticatorBridgeService.getSymmetricEncryptionKeyData].
*/
@Suppress("MagicNumber")
fun generateSecretKey(): Result<SecretKey> = runCatching {
val keygen = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES)
keygen.init(256)
@@ -35,8 +37,9 @@ fun generateSecretKey(): Result<SecretKey> = runCatching {
* Generate a fingerprint for the given symmetric key.
*
* This is intended to be used for implementing
* [IAuthenticatorBridgeService.checkSymmetricEncryptionKeyFingerprint], which allows callers of the service
* to verify that they have the correct symmetric key without actually having to send the key.
* [IAuthenticatorBridgeService.checkSymmetricEncryptionKeyFingerprint], which allows callers of the
* service to verify that they have the correct symmetric key without actually having to send the
* key.
*/
fun SymmetricEncryptionKeyData.toFingerprint(): Result<SymmetricEncryptionKeyFingerprintData> =
runCatching {
@@ -87,7 +90,7 @@ internal fun EncryptedSharedAccountData.decrypt(
val cipher = generateCipher()
cipher.init(Cipher.DECRYPT_MODE, key, iv)
val decryptedModel = JSON.decodeFromString<SharedAccountDataJson>(
cipher.doFinal(this.encryptedAccountsJson.byteArray).decodeToString()
cipher.doFinal(this.encryptedAccountsJson.byteArray).decodeToString(),
)
decryptedModel.toDomainModel()
}
@@ -130,7 +133,7 @@ fun EncryptedAddTotpLoginItemData.decrypt(
val cipher = generateCipher()
cipher.init(Cipher.DECRYPT_MODE, key, iv)
val decryptedModel = JSON.decodeFromString<AddTotpLoginItemDataJson>(
cipher.doFinal(this.encryptedTotpUriJson.byteArray).decodeToString()
cipher.doFinal(this.encryptedTotpUriJson.byteArray).decodeToString(),
)
decryptedModel.toDomainModel()
}
@@ -158,7 +161,7 @@ private fun generateCipher(): Cipher =
Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/" +
KeyProperties.BLOCK_MODE_CBC + "/" +
"PKCS5PADDING"
"PKCS5PADDING",
)
/**
@@ -173,7 +176,7 @@ private fun SharedAccountData.toJsonModel() = SharedAccountDataJson(
email = account.email,
totpUris = account.totpUris,
)
}
},
)
/**
@@ -188,7 +191,7 @@ private fun SharedAccountDataJson.toDomainModel() = SharedAccountData(
email = account.email,
totpUris = account.totpUris,
)
}
},
)
/**
@@ -199,7 +202,8 @@ private fun AddTotpLoginItemDataJson.toDomainModel() = AddTotpLoginItemData(
)
/**
* Helper function for converting [AddTotpLoginItemData] to a serializable [AddTotpLoginItemDataJson].
* Helper function for converting [AddTotpLoginItemData] to a serializable
* [AddTotpLoginItemDataJson].
*/
private fun AddTotpLoginItemData.toJsonModel() = AddTotpLoginItemDataJson(
totpUri = totpUri,

View File

@@ -164,6 +164,7 @@ class AuthenticatorBridgeManagerTest {
verify { context.bindService(any(), any(), Context.BIND_AUTO_CREATE) }
}
@Suppress("MaxLineLength")
@Test
fun `onStart when Bitwarden app is present and bindService succeeds should set state to Loading before service calls back`() {
val mockIntent: Intent = mockk()
@@ -195,7 +196,7 @@ class AuthenticatorBridgeManagerTest {
context.bindService(
any(),
capture(serviceConnection),
Context.BIND_AUTO_CREATE
Context.BIND_AUTO_CREATE,
)
} returns true
@@ -224,7 +225,7 @@ class AuthenticatorBridgeManagerTest {
context.bindService(
any(),
capture(serviceConnection),
Context.BIND_AUTO_CREATE
Context.BIND_AUTO_CREATE,
)
} returns true
@@ -243,7 +244,7 @@ class AuthenticatorBridgeManagerTest {
fakeSymmetricKeyStorageProvider.symmetricKey = SYMMETRIC_KEY
every {
mockBridgeService.checkSymmetricEncryptionKeyFingerprint(
SYMMETRIC_KEY.toFingerprint().getOrNull()
SYMMETRIC_KEY.toFingerprint().getOrNull(),
)
} returns true
val serviceConnection = slot<ServiceConnection>()
@@ -257,7 +258,7 @@ class AuthenticatorBridgeManagerTest {
context.bindService(
any(),
capture(serviceConnection),
Context.BIND_AUTO_CREATE
Context.BIND_AUTO_CREATE,
)
} returns true
@@ -278,7 +279,7 @@ class AuthenticatorBridgeManagerTest {
fakeSymmetricKeyStorageProvider.symmetricKey = SYMMETRIC_KEY
every {
mockBridgeService.checkSymmetricEncryptionKeyFingerprint(
SYMMETRIC_KEY.toFingerprint().getOrNull()
SYMMETRIC_KEY.toFingerprint().getOrNull(),
)
} returns false
every {
@@ -295,7 +296,7 @@ class AuthenticatorBridgeManagerTest {
context.bindService(
any(),
capture(serviceConnection),
Context.BIND_AUTO_CREATE
Context.BIND_AUTO_CREATE,
)
} returns true
@@ -313,7 +314,7 @@ class AuthenticatorBridgeManagerTest {
@Suppress("MaxLineLength")
fun `onAccountsSync should set AccountSyncState to decrypted response`() {
val expectedAccounts = listOf<SharedAccountData.Account>(
mockk()
mockk(),
)
val encryptedAccounts: EncryptedSharedAccountData = mockk()
val decryptedAccounts: SharedAccountData = mockk {
@@ -323,7 +324,7 @@ class AuthenticatorBridgeManagerTest {
every { encryptedAccounts.decrypt(SYMMETRIC_KEY) } returns Result.success(decryptedAccounts)
every {
mockBridgeService.checkSymmetricEncryptionKeyFingerprint(
SYMMETRIC_KEY.toFingerprint().getOrNull()
SYMMETRIC_KEY.toFingerprint().getOrNull(),
)
} returns true
fakeSymmetricKeyStorageProvider.symmetricKey = SYMMETRIC_KEY
@@ -340,7 +341,7 @@ class AuthenticatorBridgeManagerTest {
context.bindService(
any(),
capture(serviceConnection),
Context.BIND_AUTO_CREATE
Context.BIND_AUTO_CREATE,
)
} returns true
@@ -363,7 +364,7 @@ class AuthenticatorBridgeManagerTest {
val encryptedAccounts: EncryptedSharedAccountData = mockk()
every {
mockBridgeService.checkSymmetricEncryptionKeyFingerprint(
SYMMETRIC_KEY.toFingerprint().getOrNull()
SYMMETRIC_KEY.toFingerprint().getOrNull(),
)
} returns true
fakeSymmetricKeyStorageProvider.symmetricKey = SYMMETRIC_KEY
@@ -380,7 +381,7 @@ class AuthenticatorBridgeManagerTest {
context.bindService(
any(),
capture(serviceConnection),
Context.BIND_AUTO_CREATE
Context.BIND_AUTO_CREATE,
)
} returns true
@@ -406,7 +407,7 @@ class AuthenticatorBridgeManagerTest {
every { encryptedAccounts.decrypt(SYMMETRIC_KEY) } returns Result.failure(RuntimeException())
every {
mockBridgeService.checkSymmetricEncryptionKeyFingerprint(
SYMMETRIC_KEY.toFingerprint().getOrNull()
SYMMETRIC_KEY.toFingerprint().getOrNull(),
)
} returns true
fakeSymmetricKeyStorageProvider.symmetricKey = SYMMETRIC_KEY
@@ -423,7 +424,7 @@ class AuthenticatorBridgeManagerTest {
context.bindService(
any(),
capture(serviceConnection),
Context.BIND_AUTO_CREATE
Context.BIND_AUTO_CREATE,
)
} returns true

View File

@@ -10,7 +10,7 @@ class AuthenticatorBridgeConnectionTypeExtensionsTest {
fun `toPackageName RELEASE should map to correct release package`() {
assertEquals(
"com.x8bit.bitwarden",
AuthenticatorBridgeConnectionType.RELEASE.toPackageName()
AuthenticatorBridgeConnectionType.RELEASE.toPackageName(),
)
}
@@ -18,7 +18,7 @@ class AuthenticatorBridgeConnectionTypeExtensionsTest {
fun `toPackageName DEV should map to correct dev package`() {
assertEquals(
"com.x8bit.bitwarden.dev",
AuthenticatorBridgeConnectionType.DEV.toPackageName()
AuthenticatorBridgeConnectionType.DEV.toPackageName(),
)
}
}

View File

@@ -38,7 +38,7 @@ class EncryptionUtilTest {
@Test
fun `toFingerprint should return success when there are no internal exceptions`() {
val keyData = SymmetricEncryptionKeyData(
symmetricEncryptionKey = generateSecretKey().getOrThrow().encoded.toByteArrayContainer()
symmetricEncryptionKey = generateSecretKey().getOrThrow().encoded.toByteArrayContainer(),
)
val result = keyData.toFingerprint()
assertTrue(result.isSuccess)
@@ -49,7 +49,7 @@ class EncryptionUtilTest {
mockkStatic(MessageDigest::class)
every { MessageDigest.getInstance("SHA-256") } throws NoSuchAlgorithmException()
val keyData = SymmetricEncryptionKeyData(
symmetricEncryptionKey = generateSecretKey().getOrThrow().encoded.toByteArrayContainer()
symmetricEncryptionKey = generateSecretKey().getOrThrow().encoded.toByteArrayContainer(),
)
val result = keyData.toFingerprint()
assertTrue(result.isFailure)
@@ -100,7 +100,7 @@ class EncryptionUtilTest {
.decrypt(SYMMETRIC_KEY)
assertEquals(
SHARED_ACCOUNT_DATA,
result.getOrThrow()
result.getOrThrow(),
)
}
@@ -148,7 +148,7 @@ class EncryptionUtilTest {
.decrypt(SYMMETRIC_KEY)
assertEquals(
ADD_TOTP_ITEM,
result.getOrThrow()
result.getOrThrow(),
)
}
@@ -168,16 +168,16 @@ private val SHARED_ACCOUNT_DATA = SharedAccountData(
email = "johnyapples@test.com",
environmentLabel = "bitwarden.com",
totpUris = listOf("test.com"),
)
)
),
),
)
private val ADD_TOTP_ITEM = AddTotpLoginItemData(
totpUri = "test.com"
totpUri = "test.com",
)
private val SYMMETRIC_KEY = SymmetricEncryptionKeyData(
symmetricEncryptionKey = generateSecretKey().getOrThrow().encoded.toByteArrayContainer()
symmetricEncryptionKey = generateSecretKey().getOrThrow().encoded.toByteArrayContainer(),
)
private val ENCRYPTED_SHARED_ACCOUNT_DATA =