mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 12:07:28 +00:00
Avoid SQLCipher key derivation (#6774)
* Avoid SQLCipher key derivation by manually providing the generated as a raw key: this needs a series of DB re-key operations, performed as part of a 'dummy' DB migration * Set key generation length to 32 bytes in `RandomSecretPassphraseProvider`. * Use `ClientSecret` for handling the keys for SQLCipher. Move `ClientSecret` to `:libraries:androidutils` so it's shared.
This commit is contained in:
committed by
GitHub
parent
4cafdae22d
commit
1e00353f29
-66
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl
|
||||
|
||||
import okio.ByteString.Companion.decodeHex
|
||||
|
||||
/**
|
||||
* Represents a client secret used to encrypt/decrypt data from databases, which can be either a passphrase or a raw key.
|
||||
*/
|
||||
sealed interface ClientSecret {
|
||||
/**
|
||||
* A passphrase that can be used to derive a key for encryption/decryption.
|
||||
*/
|
||||
data class Passphrase(val value: String) : ClientSecret {
|
||||
override fun formattedAsString(): String = toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* A raw key that can be directly used for encryption/decryption. The key is represented as a byte array, and is formatted as a string in the form of
|
||||
* `x'...'` where the bytes are encoded as hex characters.
|
||||
*/
|
||||
data class RawKey(val bytes: ByteArray) : ClientSecret {
|
||||
override fun formattedAsString() = "x'${bytes.toHexString()}'"
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
return bytes.contentEquals((other as RawKey).bytes)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return bytes.contentHashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return formattedAsString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the client secret as a string that can be parsed back with [fromString].
|
||||
* For a passphrase, this is just the passphrase value. For a raw key, this is the hex-encoded representation of the key formatted as `x'...'`.
|
||||
*/
|
||||
fun formattedAsString(): String
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Parse a string representation of a client secret, which can be either a passphrase or a raw key formatted as `x'...'`.
|
||||
*/
|
||||
fun fromString(secret: String): ClientSecret {
|
||||
val regex = Regex("^x'([0-9a-fA-F]+)'$")
|
||||
val rawKeyMatch = regex.matchEntire(secret)
|
||||
return if (rawKeyMatch != null) {
|
||||
RawKey(rawKeyMatch.groupValues[1].decodeHex().toByteArray())
|
||||
} else {
|
||||
Passphrase(secret)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -9,6 +9,7 @@
|
||||
package io.element.android.libraries.matrix.impl
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.libraries.androidutils.crypto.ClientSecret
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.data.ByteUnit
|
||||
import io.element.android.libraries.core.data.megaBytes
|
||||
|
||||
+1
-1
@@ -12,6 +12,7 @@ import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import io.element.android.features.enterprise.api.EnterpriseService
|
||||
import io.element.android.libraries.androidutils.crypto.ClientSecret
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.extensions.mapFailure
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
@@ -30,7 +31,6 @@ import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||
import io.element.android.libraries.matrix.impl.ClientBuilderSlidingSync
|
||||
import io.element.android.libraries.matrix.impl.ClientSecret
|
||||
import io.element.android.libraries.matrix.impl.RustMatrixClientFactory
|
||||
import io.element.android.libraries.matrix.impl.auth.qrlogin.QrErrorMapper
|
||||
import io.element.android.libraries.matrix.impl.auth.qrlogin.SdkQrCodeLoginData
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ package io.element.android.libraries.matrix.impl.keys
|
||||
import android.util.Base64
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.libraries.matrix.impl.ClientSecret
|
||||
import io.element.android.libraries.androidutils.crypto.ClientSecret
|
||||
import java.security.SecureRandom
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
package io.element.android.libraries.matrix.impl.keys
|
||||
|
||||
import io.element.android.libraries.matrix.impl.ClientSecret
|
||||
import io.element.android.libraries.androidutils.crypto.ClientSecret
|
||||
|
||||
private const val PASSPHRASE_SIZE = 256
|
||||
private const val KEY_SIZE = 32
|
||||
|
||||
+1
-1
@@ -7,9 +7,9 @@
|
||||
|
||||
package io.element.android.libraries.matrix.impl.storage
|
||||
|
||||
import io.element.android.libraries.androidutils.crypto.ClientSecret
|
||||
import io.element.android.libraries.core.data.ByteUnit
|
||||
import io.element.android.libraries.core.data.megaBytes
|
||||
import io.element.android.libraries.matrix.impl.ClientSecret
|
||||
import io.element.android.libraries.matrix.impl.paths.SessionPaths
|
||||
import org.matrix.rustcomponents.sdk.ClientBuilder
|
||||
import org.matrix.rustcomponents.sdk.SqliteStoreBuilder as SdkSqliteStoreBuilder
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
package io.element.android.libraries.matrix.impl.auth
|
||||
|
||||
import io.element.android.libraries.matrix.impl.ClientSecret
|
||||
import io.element.android.libraries.androidutils.crypto.ClientSecret
|
||||
import io.element.android.libraries.matrix.impl.keys.SecretGenerator
|
||||
import io.element.android.libraries.matrix.test.A_PASSPHRASE
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
package io.element.android.libraries.matrix.impl.keys
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.impl.ClientSecret
|
||||
import io.element.android.libraries.androidutils.crypto.ClientSecret
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
|
||||
package io.element.android.libraries.matrix.impl.storage
|
||||
|
||||
import io.element.android.libraries.matrix.impl.ClientSecret
|
||||
import io.element.android.libraries.androidutils.crypto.ClientSecret
|
||||
import org.matrix.rustcomponents.sdk.ClientBuilder
|
||||
|
||||
class FakeSqliteStoreBuilder : SqliteStoreBuilder {
|
||||
|
||||
Reference in New Issue
Block a user