Merge pull request #588 from PhilKes/fix/backup-on-save-decrypt

Fix decrypting database on auto-save backup if biometric lock is enabled
This commit is contained in:
Phil 2025-05-10 16:43:25 +02:00 committed by GitHub
commit 402baf8056
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 32 additions and 13 deletions

View file

@ -89,7 +89,7 @@ import net.lingala.zip4j.model.enums.EncryptionMethod
private const val TAG = "ExportExtensions" private const val TAG = "ExportExtensions"
private const val NOTIFICATION_CHANNEL_ID = "AutoBackups" private const val NOTIFICATION_CHANNEL_ID = "AutoBackups"
private const val NOTIFICATION_ID = 123412 private const val NOTIFICATION_ID = 123412
private const val NOTALLYX_BACKUP_LOGS_FILE = "notallyx-backup-logs" private const val NOTALLYX_BACKUP_LOGS_FILE = "notallyx-backup-logs.txt"
private const val OUTPUT_DATA_BACKUP_URI = "backupUri" private const val OUTPUT_DATA_BACKUP_URI = "backupUri"
const val AUTO_BACKUP_WORK_NAME = "com.philkes.notallyx.AutoBackupWork" const val AUTO_BACKUP_WORK_NAME = "com.philkes.notallyx.AutoBackupWork"
@ -174,7 +174,7 @@ fun ContextWrapper.autoBackupOnSave(backupPath: String, password: String, savedN
backupFile = folder.createFile(MIME_TYPE_ZIP, ON_SAVE_BACKUP_FILE) backupFile = folder.createFile(MIME_TYPE_ZIP, ON_SAVE_BACKUP_FILE)
exportAsZip(backupFile!!.uri, password = password) exportAsZip(backupFile!!.uri, password = password)
} else { } else {
NotallyDatabase.getDatabase(this, observePreferences = false).value.checkpoint() val (_, file) = copyDatabase()
val files = val files =
with(savedNote) { with(savedNote) {
images.map { images.map {
@ -192,10 +192,7 @@ fun ContextWrapper.autoBackupOnSave(backupPath: String, password: String, savedN
audios.map { audios.map {
BackupFile(SUBFOLDER_AUDIOS, File(getExternalAudioDirectory(), it.name)) BackupFile(SUBFOLDER_AUDIOS, File(getExternalAudioDirectory(), it.name))
} + } +
BackupFile( BackupFile(null, file)
null,
NotallyDatabase.getCurrentDatabaseFile(this@autoBackupOnSave),
)
} }
try { try {
exportToZip(backupFile.uri, files, password) exportToZip(backupFile.uri, files, password)
@ -417,7 +414,7 @@ fun ContextWrapper.copyDatabase(): Pair<NotallyDatabase, File> {
val cipher = getInitializedCipherForDecryption(iv = preferences.iv.value!!) val cipher = getInitializedCipherForDecryption(iv = preferences.iv.value!!)
val passphrase = cipher.doFinal(preferences.databaseEncryptionKey.value) val passphrase = cipher.doFinal(preferences.databaseEncryptionKey.value)
val decryptedFile = File(cacheDir, DATABASE_NAME) val decryptedFile = File(cacheDir, DATABASE_NAME)
decryptDatabase(this, passphrase, decryptedFile, databaseFile) decryptDatabase(this, passphrase, databaseFile, decryptedFile)
Pair(database, decryptedFile) Pair(database, decryptedFile)
} else { } else {
val dbFile = File(cacheDir, DATABASE_NAME) val dbFile = File(cacheDir, DATABASE_NAME)

View file

@ -28,6 +28,7 @@ import com.philkes.notallyx.data.model.parseToColorString
import com.philkes.notallyx.presentation.getQuantityString import com.philkes.notallyx.presentation.getQuantityString
import com.philkes.notallyx.presentation.showToast import com.philkes.notallyx.presentation.showToast
import com.philkes.notallyx.presentation.viewmodel.NotallyModel.FileType import com.philkes.notallyx.presentation.viewmodel.NotallyModel.FileType
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
import com.philkes.notallyx.utils.FileError import com.philkes.notallyx.utils.FileError
import com.philkes.notallyx.utils.SUBFOLDER_AUDIOS import com.philkes.notallyx.utils.SUBFOLDER_AUDIOS
import com.philkes.notallyx.utils.SUBFOLDER_FILES import com.philkes.notallyx.utils.SUBFOLDER_FILES
@ -44,6 +45,8 @@ import com.philkes.notallyx.utils.log
import com.philkes.notallyx.utils.mimeTypeToFileExtension import com.philkes.notallyx.utils.mimeTypeToFileExtension
import com.philkes.notallyx.utils.rename import com.philkes.notallyx.utils.rename
import com.philkes.notallyx.utils.scheduleNoteReminders import com.philkes.notallyx.utils.scheduleNoteReminders
import com.philkes.notallyx.utils.security.SQLCipherUtils
import com.philkes.notallyx.utils.security.decryptDatabase
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.InputStream import java.io.InputStream
@ -86,12 +89,31 @@ suspend fun ContextWrapper.importZip(
NotallyDatabase.DATABASE_NAME, NotallyDatabase.DATABASE_NAME,
) )
val database = var dbFile = File(databaseFolder, NotallyDatabase.DATABASE_NAME)
SQLiteDatabase.openDatabase( val state = SQLCipherUtils.getDatabaseState(dbFile)
File(databaseFolder, NotallyDatabase.DATABASE_NAME).path, if (state == SQLCipherUtils.State.ENCRYPTED) {
null, val fallbackEncryptionKey =
SQLiteDatabase.OPEN_READONLY, NotallyXPreferences.getInstance(this@importZip)
.fallbackDatabaseEncryptionKey
.value
if (fallbackEncryptionKey != null) {
val dbFileDecrypted =
File(databaseFolder, "${NotallyDatabase.DATABASE_NAME}-decrypted")
decryptDatabase(
this@importZip,
fallbackEncryptionKey,
dbFile,
dbFileDecrypted,
) )
dbFile = dbFileDecrypted
} else {
throw IllegalArgumentException(
"Backup contains encrypted database and 'fallbackDatabaseEncryptionKey' has no value!"
)
}
}
val database =
SQLiteDatabase.openDatabase(dbFile.path, null, SQLiteDatabase.OPEN_READONLY)
val labelCursor = database.query("Label", null, null, null, null, null, null) val labelCursor = database.query("Label", null, null, null, null, null, null)
val baseNoteCursor = database.query("BaseNote", null, null, null, null, null, null) val baseNoteCursor = database.query("BaseNote", null, null, null, null, null, null)

View file

@ -37,8 +37,8 @@ fun decryptDatabase(context: ContextWrapper, passphrase: ByteArray) {
fun decryptDatabase( fun decryptDatabase(
context: Context, context: Context,
passphrase: ByteArray, passphrase: ByteArray,
decryptedFile: File,
databaseFile: File, databaseFile: File,
decryptedFile: File,
) { ) {
val state = SQLCipherUtils.getDatabaseState(databaseFile) val state = SQLCipherUtils.getDatabaseState(databaseFile)
if (state == SQLCipherUtils.State.ENCRYPTED) { if (state == SQLCipherUtils.State.ENCRYPTED) {