Fatal Exception: net.sqlcipher.database.SQLiteException file is not a database: , while compiling: select count(*) from sqlite_master;

Hi,
I have a plain room db in my application, i used “net.zetetic:android-database-sqlcipher:4.4.0” to encrypt the database it working fine in development phase, but after application released into the market getting random crashes as saying “Fatal Exception: net.sqlcipher.database.SQLiteException file is not a database: , while compiling: select count(*) from sqlite_master;”, and we are not able reproduce the same in our end. i checked that Passphrase also correct, no where it is getting changed. Any help you can give would be greatly appreciated.

I used the below code to encrypt the data base

@Throws(IOException::class)
private fun encrypt(context: Context, databaseName: String, passphrase: ByteArray) {
val originalFile = getCurrentDBPath(context, databaseName)
if (originalFile.exists()) {
val newFile = File.createTempFile(“xyz_room_db”, “tmp”,
context.cacheDir)
var db = SQLiteDatabase.openDatabase(originalFile.absolutePath,
“”, null, SQLiteDatabase.OPEN_READWRITE)
val version = db.version
SlLog.i(“SL_DATABASE”, “DB version ${version}”)
db.close()
db = SQLiteDatabase.openDatabase(newFile.absolutePath, passphrase, null, SQLiteDatabase.OPEN_READWRITE, null, null)
val st: SQLiteStatement = db.compileStatement(“ATTACH DATABASE ? AS plaintext KEY ‘’”)
st.bindString(1, originalFile.absolutePath)
st.execute()
db.rawExecSQL(“SELECT sqlcipher_export(‘main’, ‘plaintext’)”)
db.rawExecSQL(“DETACH DATABASE plaintext”)
db.version = version
st.close()
db.close()
originalFile.delete()
newFile.renameTo(originalFile)
SlLog.i(“SL_DATABASE”, “DB encrypted successfully”)
} else {
throw FileNotFoundException(originalFile.absolutePath + " not found")
}
}

Fatal Exception: net.sqlcipher.database.SQLiteException

file is not a database: , while compiling: select count(*) from sqlite_master;

net.sqlcipher.database.SQLiteCompiledSql.native_compile (SQLiteCompiledSql.java)

net.sqlcipher.database.SQLiteCompiledSql.compile (SQLiteCompiledSql.java:89)

net.sqlcipher.database.SQLiteCompiledSql. (SQLiteCompiledSql.java:62)

net.sqlcipher.database.SQLiteProgram. (SQLiteProgram.java:91)

net.sqlcipher.database.SQLiteQuery. (SQLiteQuery.java:48)

net.sqlcipher.database.SQLiteDirectCursorDriver.query (SQLiteDirectCursorDriver.java:60)

net.sqlcipher.database.SQLiteDatabase.rawQueryWithFactory (SQLiteDatabase.java:2016)

net.sqlcipher.database.SQLiteDatabase.rawQuery (SQLiteDatabase.java:1902)

net.sqlcipher.database.SQLiteDatabase.keyDatabase (SQLiteDatabase.java:2669)

net.sqlcipher.database.SQLiteDatabase.openDatabaseInternal (SQLiteDatabase.java:2612)

net.sqlcipher.database.SQLiteDatabase.openDatabase (SQLiteDatabase.java:1247)

net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase (SQLiteDatabase.java:1322)

net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase (SQLiteOpenHelper.java:166)

net.sqlcipher.database.SupportHelper.getWritableDatabase (SupportHelper.java:83)

androidx.room.RoomDatabase.inTransaction (RoomDatabase.java:476)

arrow_drop_down

androidx.room.RoomDatabase.assertNotSuspendingTransaction (RoomDatabase.java:281)

com.mobile.newArch.room.dao.NotificationListDao_Impl.insert (NotificationListDao_Impl.java:189)

com.mobile.newArch.room.dao.NotificationListDao_Impl.insert (NotificationListDao_Impl.java:24)

com.mobile.newArch.utils.NotificationDbOperationsUtil.saveNotificationData (NotificationDbOperationsUtil.java:38)

com.mobile.newArch.utils.PushNotifications.onPushNotificationShown (PushNotifications.java:29)

com.webengage.sdk.android.i$5.run (i.java:10)

Hi @Jayakrishna

This code appears to be exporting to a plaintext database file, not encrypting it; note the blank key you are using in the ATTACH statement. Example # 1 for encrypting a plaintext database file shows the proper usage here.

One additional consideration you might make in your application is to capture the return value of your call to the following:

newFile.renameTo(originalFile)

If for some reason renameTo returns false, your code currently ignores that, leaving the originalFile deleted.

But, after executing this statements, i exported the DB and tried to open in sqlite broswer. while opening the DB in sqlite broswer it asked me to enter the “passphrase” that i have used to encrypt the DB file. You can see in the below code i m creating the db object with “passphrase” and after that i m attaching the the plaintext database.

db = SQLiteDatabase.openDatabase(newFile.absolutePath, passphrase, null, SQLiteDatabase.OPEN_READWRITE, null, null)
val st: SQLiteStatement = db.compileStatement(“ATTACH DATABASE ? AS plaintext KEY ‘’”)
st.bindString(1, originalFile.absolutePath)
st.execute()

Hi @Jayakrishna

Sorry, I saw you were opening without a password above and didn’t see the reuse of the variable name to open a different connection with passphrase. I would still recommend checking the result of your call to renameTo. Additionally, you might consider adjusting your application logic to catch that exception, and when it occurs, attempt to open the database without a passphrase.