mirror of
https://github.com/bitwarden/android.git
synced 2026-06-08 16:17:05 -05:00
BIT-329 Implement parsing and usage of kdf params (#112)
This commit is contained in:
committed by
Álison Fernandes
parent
57561d0ccd
commit
5ecb8fbb2c
@@ -0,0 +1,21 @@
|
||||
package com.x8bit.bitwarden.data.auth.datasource.network.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Response body for pre login. This internal model is only used for as a surrogate serializer.
|
||||
*
|
||||
* See [PreLoginResponseJson] for exposed model.
|
||||
*/
|
||||
@Serializable
|
||||
data class InternalPreLoginResponseJson(
|
||||
@SerialName("kdf")
|
||||
val kdfType: Int,
|
||||
@SerialName("kdfIterations")
|
||||
val kdfIterations: UInt,
|
||||
@SerialName("kdfMemory")
|
||||
val kdfMemory: UInt? = null,
|
||||
@SerialName("kdfParallelism")
|
||||
val kdfParallelism: UInt? = null,
|
||||
)
|
||||
@@ -1,20 +1,96 @@
|
||||
package com.x8bit.bitwarden.data.auth.datasource.network.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
private const val KDF_TYPE_ARGON2_ID = 1
|
||||
private const val KDF_TYPE_PBKDF2_SHA256 = 0
|
||||
|
||||
/**
|
||||
* Response body for pre login.
|
||||
*/
|
||||
@Serializable
|
||||
@Serializable(PreLoginResponseSerializer::class)
|
||||
data class PreLoginResponseJson(
|
||||
// TODO parse this property as an enum (BIT-329)
|
||||
@SerialName("kdf")
|
||||
val kdf: Int,
|
||||
@SerialName("kdfIterations")
|
||||
val kdfIterations: UInt,
|
||||
@SerialName("kdfMemory")
|
||||
val kdfMemory: Int? = null,
|
||||
@SerialName("kdfParallelism")
|
||||
val kdfParallelism: Int? = null,
|
||||
)
|
||||
val kdfParams: KdfParams,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Models different kdf types.
|
||||
*
|
||||
* See https://bitwarden.com/help/kdf-algorithms/.
|
||||
*/
|
||||
sealed class KdfParams {
|
||||
|
||||
/**
|
||||
* Models params for the Argon2id algorithm.
|
||||
*/
|
||||
data class Argon2ID(
|
||||
val iterations: UInt,
|
||||
val memory: UInt,
|
||||
val parallelism: UInt,
|
||||
) : KdfParams()
|
||||
|
||||
/**
|
||||
* Models params for the PBKDF2 algorithm.
|
||||
*/
|
||||
data class Pbkdf2(val iterations: UInt) : KdfParams()
|
||||
}
|
||||
}
|
||||
|
||||
private class PreLoginResponseSerializer : KSerializer<PreLoginResponseJson> {
|
||||
|
||||
private val surrogateSerializer = InternalPreLoginResponseJson.serializer()
|
||||
|
||||
override val descriptor: SerialDescriptor = surrogateSerializer.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): PreLoginResponseJson {
|
||||
val surrogate = decoder.decodeSerializableValue(surrogateSerializer)
|
||||
val kdfParams = when (surrogate.kdfType) {
|
||||
KDF_TYPE_PBKDF2_SHA256 -> {
|
||||
PreLoginResponseJson.KdfParams.Pbkdf2(
|
||||
iterations = surrogate.kdfIterations,
|
||||
)
|
||||
}
|
||||
|
||||
KDF_TYPE_ARGON2_ID -> {
|
||||
PreLoginResponseJson.KdfParams.Argon2ID(
|
||||
iterations = surrogate.kdfIterations,
|
||||
memory = surrogate.kdfMemory!!,
|
||||
parallelism = surrogate.kdfParallelism!!,
|
||||
)
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException(
|
||||
"Unable to parse KDF params for unknown kdfType: ${surrogate.kdfType}",
|
||||
)
|
||||
}
|
||||
return PreLoginResponseJson(kdfParams = kdfParams)
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: PreLoginResponseJson) {
|
||||
val surrogate = when (val params = value.kdfParams) {
|
||||
is PreLoginResponseJson.KdfParams.Argon2ID -> {
|
||||
InternalPreLoginResponseJson(
|
||||
kdfType = KDF_TYPE_ARGON2_ID,
|
||||
kdfIterations = params.iterations,
|
||||
kdfMemory = params.memory,
|
||||
kdfParallelism = params.parallelism,
|
||||
)
|
||||
}
|
||||
|
||||
is PreLoginResponseJson.KdfParams.Pbkdf2 -> {
|
||||
InternalPreLoginResponseJson(
|
||||
kdfType = KDF_TYPE_PBKDF2_SHA256,
|
||||
kdfIterations = params.iterations,
|
||||
)
|
||||
}
|
||||
}
|
||||
encoder.encodeSerializableValue(
|
||||
surrogateSerializer,
|
||||
surrogate,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.x8bit.bitwarden.data.auth.repository
|
||||
|
||||
import com.bitwarden.core.Kdf
|
||||
import com.bitwarden.sdk.Client
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthState
|
||||
@@ -11,6 +10,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.LoginResult
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.service.AccountsService
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.service.IdentityService
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.util.CaptchaCallbackTokenResult
|
||||
import com.x8bit.bitwarden.data.auth.util.toSdkParams
|
||||
import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.AuthTokenInterceptor
|
||||
import com.x8bit.bitwarden.data.platform.util.flatMap
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@@ -55,13 +55,12 @@ class AuthRepositoryImpl @Inject constructor(
|
||||
): LoginResult = accountsService
|
||||
.preLogin(email = email)
|
||||
.flatMap {
|
||||
// TODO: Use KDF enum from pre login correctly (BIT-329)
|
||||
val passwordHash = bitwardenSdkClient
|
||||
.auth()
|
||||
.hashPassword(
|
||||
email = email,
|
||||
password = password,
|
||||
kdfParams = Kdf.Pbkdf2(it.kdfIterations),
|
||||
kdfParams = it.kdfParams.toSdkParams(),
|
||||
)
|
||||
identityService.getToken(
|
||||
email = email,
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.x8bit.bitwarden.data.auth.util
|
||||
|
||||
import com.bitwarden.core.Kdf
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.PreLoginResponseJson
|
||||
|
||||
/**
|
||||
* Convert [PreLoginResponseJson.KdfParams] to [Kdf] params for use with Bitwarden SDK.
|
||||
*/
|
||||
fun PreLoginResponseJson.KdfParams.toSdkParams(): Kdf = when (this) {
|
||||
is PreLoginResponseJson.KdfParams.Argon2ID -> {
|
||||
Kdf.Argon2id(
|
||||
iterations = this.iterations,
|
||||
memory = this.memory,
|
||||
parallelism = this.parallelism,
|
||||
)
|
||||
}
|
||||
|
||||
is PreLoginResponseJson.KdfParams.Pbkdf2 -> {
|
||||
Kdf.Pbkdf2(
|
||||
iterations = this.iterations,
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user