fix(Desktop): Use correct SqlCipher parameters to create an encrypted database

This commit is contained in:
Artem Chepurnoy 2024-06-06 11:26:26 +03:00
parent 866da87caf
commit 8b9fc0d3fc
No known key found for this signature in database
GPG Key ID: FAC37D0CF674043E
2 changed files with 56 additions and 11 deletions

View File

@ -167,7 +167,11 @@ kotlin {
implementation(libs.google.zxing.javase) implementation(libs.google.zxing.javase)
implementation(libs.harawata.appdirs) implementation(libs.harawata.appdirs)
implementation(libs.commons.lang3) implementation(libs.commons.lang3)
api(libs.cash.sqldelight.sqlite.driver) val sqldelight = libs.cash.sqldelight.sqlite.driver.get()
.let { "${it.module}:${it.versionConstraint.requiredVersion}" }
api(sqldelight) {
exclude(group = "org.xerial")
}
api(libs.kamel.image) api(libs.kamel.image)
api(libs.mayakapps.window.styler) api(libs.mayakapps.window.styler)
api(libs.wunderbox.nativefiledialog) api(libs.wunderbox.nativefiledialog)

View File

@ -9,9 +9,11 @@ import com.artemchep.keyguard.common.io.bind
import com.artemchep.keyguard.common.io.ioEffect import com.artemchep.keyguard.common.io.ioEffect
import com.artemchep.keyguard.common.model.MasterKey import com.artemchep.keyguard.common.model.MasterKey
import com.artemchep.keyguard.data.Database import com.artemchep.keyguard.data.Database
import io.ktor.util.hex import io.ktor.util.*
import org.sqlite.mc.SQLiteMCSqlCipherConfig
import java.io.File import java.io.File
import java.util.Properties import java.sql.DriverManager
import java.util.*
class SqlManagerFile( class SqlManagerFile(
private val fileIo: IO<File>, private val fileIo: IO<File>,
@ -21,9 +23,40 @@ class SqlManagerFile(
databaseFactory: (SqlDriver) -> Database, databaseFactory: (SqlDriver) -> Database,
vararg callbacks: AfterVersion, vararg callbacks: AfterVersion,
): IO<SqlHelper> = ioEffect { ): IO<SqlHelper> = ioEffect {
val file = fileIo
.bind()
try {
createSqlHelper(
file = file,
masterKey = masterKey,
databaseFactory = databaseFactory,
callbacks = callbacks,
)
} catch (e: Exception) {
e.printStackTrace()
println(e.message)
if ("is not a database" in e.message.orEmpty()) {
file.delete()
}
// Try again
createSqlHelper(
file = file,
masterKey = masterKey,
databaseFactory = databaseFactory,
callbacks = callbacks,
)
}
}
private suspend fun createSqlHelper(
file: File,
masterKey: MasterKey,
databaseFactory: (SqlDriver) -> Database,
vararg callbacks: AfterVersion,
): SqlHelper {
val driver: SqlDriver = createSqlDriver( val driver: SqlDriver = createSqlDriver(
file = fileIo file = file,
.bind(),
key = masterKey.byteArray, key = masterKey.byteArray,
) )
@ -48,7 +81,7 @@ class SqlManagerFile(
} }
val database = databaseFactory(driver) val database = databaseFactory(driver)
object : SqlHelper { return object : SqlHelper {
override val driver: SqlDriver get() = driver override val driver: SqlDriver get() = driver
override val database: Database get() = database override val database: Database get() = database
@ -64,8 +97,7 @@ class SqlManagerFile(
driver.execute( driver.execute(
identifier = null, identifier = null,
sql = """ sql = """
PRAGMA key = "x'$hex"; PRAGMA rekey = "x'$hex'";
PRAGMA rekey = "x'$hex";
""".trimIndent(), """.trimIndent(),
parameters = 0, parameters = 0,
binders = null, binders = null,
@ -78,13 +110,22 @@ class SqlManagerFile(
file: File, file: File,
key: ByteArray, key: ByteArray,
): SqlDriver { ): SqlDriver {
val hex = hex(key) val drivers = DriverManager.getDrivers().toList()
require(drivers.size == 1) {
"There should be only one SQL driver, currently " +
drivers.joinToString { it::class.java.canonicalName } +
" are present."
}
val sqlCipherProps = SQLiteMCSqlCipherConfig.getDefault()
.withRawUnsaltedKey(key)
.build()
.toProperties()
val url = "jdbc:sqlite:file:${file.absolutePath}" val url = "jdbc:sqlite:file:${file.absolutePath}"
return JdbcSqliteDriver( return JdbcSqliteDriver(
url = url, url = url,
properties = Properties().apply { properties = Properties().apply {
put("cipher", "sqlcipher") putAll(sqlCipherProps)
put("hexkey", hex)
put("foreign_keys", "true") put("foreign_keys", "true")
}, },
) )