improvement: Bitwarden checksum URI generation #498

This commit is contained in:
Artem Chepurnyi 2024-07-31 13:13:52 +03:00
parent f723997abb
commit 89041d3137
6 changed files with 32 additions and 1 deletions

View File

@ -210,11 +210,15 @@ data class BitwardenCipher(
val version: Long,
)
@optics
@Serializable
data class Uri(
val uri: String? = null,
val uriChecksumBase64: String? = null,
val match: MatchType? = null,
) {
companion object;
@Serializable
enum class MatchType {
Domain,

View File

@ -19,6 +19,8 @@ import com.artemchep.keyguard.core.store.bitwarden.BitwardenProfile
import com.artemchep.keyguard.core.store.bitwarden.BitwardenSend
import com.artemchep.keyguard.core.store.bitwarden.BitwardenService
import com.artemchep.keyguard.core.store.bitwarden.BitwardenToken
import com.artemchep.keyguard.core.store.bitwarden.login
import com.artemchep.keyguard.core.store.bitwarden.uris
import com.artemchep.keyguard.data.Database
import com.artemchep.keyguard.platform.recordException
import com.artemchep.keyguard.provider.bitwarden.api.builder.api
@ -575,7 +577,24 @@ class SyncEngine(
localReEncoder = { model ->
model
},
localDecoder = { local, remote ->
localDecoder = { rawLocal, remote ->
// Inject the URL checksums into the list of URLs before
// processing the entry.
val local = BitwardenCipher.login.uris.modify(rawLocal) { uris ->
uris
.map { uri ->
if (uri.uriChecksumBase64 != null) return@map uri
val uriChecksumBase64 = kotlin.run {
val rawHash =
cryptoGenerator.hashSha256(uri.uri.orEmpty().toByteArray())
base64Service.encodeToString(rawHash)
}
uri.copy(
uriChecksumBase64 = uriChecksumBase64,
)
}
}
val itemKey = local.keyBase64
?.let(base64Service::decode)
val (

View File

@ -85,6 +85,7 @@ fun BitwardenCipher.Login.Uri.transform(
crypto: BitwardenCrCta,
) = copy(
uri = crypto.transformString(uri.orEmpty()),
uriChecksumBase64 = uriChecksumBase64?.let(crypto::transformString),
)
@JvmName("encryptListOfBitwardenCipherLoginFido2Credentials")

View File

@ -80,6 +80,7 @@ fun BitwardenCipher.Companion.encrypted(
val match = it.match?.domain()
BitwardenCipher.Login.Uri(
uri = it.uri,
uriChecksumBase64 = it.uriChecksum,
match = match,
)
},

View File

@ -9,6 +9,9 @@ data class LoginUriEntity(
@JsonNames("uri")
@SerialName("Uri")
val uri: String? = null,
@JsonNames("uriChecksum")
@SerialName("UriChecksum")
val uriChecksum: String? = null,
@JsonNames("match")
@SerialName("Match")
val match: UriMatchTypeEntity? = null,

View File

@ -10,6 +10,8 @@ import kotlinx.serialization.Serializable
data class LoginUriRequest(
@SerialName("uri")
val uri: String,
@SerialName("uriChecksum")
val uriChecksum: String?,
@SerialName("match")
val match: UriMatchTypeEntity?,
) {
@ -21,6 +23,7 @@ fun LoginUriRequest.Companion.of(
) = kotlin.run {
LoginUriRequest(
uri = requireNotNull(model.uri) { "Login URI request must have a non-null URI!" },
uriChecksum = model.uriChecksumBase64,
match = model.match?.let(UriMatchTypeEntity::of),
)
}