Sqldelight: SQLDelight Encryption

Created on 3 Jun 2019  路  2Comments  路  Source: cashapp/sqldelight

I am using SQLDelight for my Kotlin Multi Platform application development.

Queries :

  1. What is the best way to encrypt my application database?
  2. Does SQLDelight support using libraries like SQLCipher?

In the KotlinConf 2018 - A Multiplatform Delight video, there was a mention of sqlcipher being used with sqldelight but I haven't came across anything useful online which shows how to do that exactly.
Is there any example that you can point me to in this regard?

Thanks.

Most helpful comment

SQL Delight's Android driver is built on the AndroidX SQLite abstraction which means you can use any implementation underneath the library.

When creating the Android driver, you can supply a SupportSQLiteOpenHelper.Factory:

https://github.com/square/sqldelight/blob/d04b16a6921f1e89b4f58447fa65eb8ddf739ac0/drivers/android-driver/src/main/java/com/squareup/sqldelight/android/AndroidSqliteDriver.kt#L41

This defaults to the framework one (i.e., using the built-in SQLite in Android), but any should work. A quick Google yields https://github.com/commonsguy/cwac-saferoom which talks about Room but has nothing to do with Room. It's a SQLCipher implementation of SupportSQLiteOpenHelper that you can use.

All 2 comments

SQL Delight's Android driver is built on the AndroidX SQLite abstraction which means you can use any implementation underneath the library.

When creating the Android driver, you can supply a SupportSQLiteOpenHelper.Factory:

https://github.com/square/sqldelight/blob/d04b16a6921f1e89b4f58447fa65eb8ddf739ac0/drivers/android-driver/src/main/java/com/squareup/sqldelight/android/AndroidSqliteDriver.kt#L41

This defaults to the framework one (i.e., using the built-in SQLite in Android), but any should work. A quick Google yields https://github.com/commonsguy/cwac-saferoom which talks about Room but has nothing to do with Room. It's a SQLCipher implementation of SupportSQLiteOpenHelper that you can use.

Seems like cursor close is needed for SQLCipher

2019-06-12 08:03:46.251 26280-26289/com.nibras.mobile.debug E/System: Uncaught exception thrown by finalizer 2019-06-12 08:03:46.252 26280-26289/com.nibras.mobile.debug E/System: net.sqlcipher.database.SQLiteException: unable to close due to unfinalized statements or unfinished backups: sqlite3_close() failed at net.sqlcipher.database.SQLiteDatabase.dbclose(Native Method) at net.sqlcipher.database.SQLiteDatabase.onAllReferencesReleased(SQLiteDatabase.java:513) at net.sqlcipher.database.SQLiteDatabase.finalize(SQLiteDatabase.java:2491) at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:250) at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:237) at java.lang.Daemons$Daemon.run(Daemons.java:103) at java.lang.Thread.run(Thread.java:764) 2019-06-12 08:03:46.270 2032-2522/system_process I/GnssLocationProvider: WakeLock acquired by sendMessage(REPORT_SV_STATUS, 0, com.android.server.location.GnssLocationProvider$SvStatusInfo@3ce80cb) 2019-06-12 08:03:46.272 2032-2051/system_process I/GnssLocationProvider: WakeLock released by handleMessage(REPORT_SV_STATUS, 0, com.android.server.location.GnssLocationProvider$SvStatusInfo@3ce80cb) 2019-06-12 08:03:46.303 26280-26289/com.nibras.mobile.debug W/SQLiteCompiledSql: Releasing statement in a finalizer. Please ensure that you explicitly call close() on your cursor: CREATE TABLE LOGS_TBL ( -- ROW_ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , CLIENT_ID INTEGER net.sqlcipher.database.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here at net.sqlcipher.database.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:62) at net.sqlcipher.database.SQLiteProgram.<init>(SQLiteProgram.java:79) at net.sqlcipher.database.SQLiteStatement.<init>(SQLiteStatement.java:39) at net.sqlcipher.database.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1702) at com.commonsware.cwac.saferoom.Database.compileStatement(Database.java:54) at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:125) at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:19) at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:110) at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:125) at com.squareup.sqldelight.db.SqlDriver$DefaultImpls.execute$default(SqlDriver.kt:56) at com.nibras.mobile.app.nibrasmobiledbImpl$Schema.create(nibrasmobiledbImpl.kt:35) at com.squareup.sqldelight.android.AndroidSqliteDriver$Callback.onCreate(AndroidSqliteDriver.kt:146) at com.commonsware.cwac.saferoom.Helper$OpenHelper.onCreate(Helper.java:168) at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:177) at com.commonsware.cwac.saferoom.Helper$OpenHelper.getWritableSupportDatabase(Helper.java:142) at com.commonsware.cwac.saferoom.Helper.getWritableDatabase(Helper.java:77) at com.squareup.sqldelight.android.AndroidSqliteDriver$database$2.invoke(AndroidSqliteDriver.kt:26) at com.squareup.sqldelight.android.AndroidSqliteDriver$database$2.invoke(AndroidSqliteDriver.kt:19) at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) at com.squareup.sqldelight.android.AndroidSqliteDriver.getDatabase(Unknown Source:7) at com.squareup.sqldelight.android.AndroidSqliteDriver.access$getDatabase$p(AndroidSqliteDriver.kt:19) at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:125) at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:19) at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:110) at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:125) at com.nibras.mobile.app.LogsQueriesImpl.insert(nibrasmobiledbImpl.kt:79) at nibrasCommon.core.platform.Utils$Companion.saveLogsInDB(Utils.kt:14) at nibrasCommon.features.login.AuthenticateViewModel.loginClick(AuthenticateViewModel.kt:161) at com.nibras.mobile.features.LoginActivity$onCreate$1.onClick(LoginActivity.kt:161) at android.view.View.performClick(View.java:6597) at android.view.View.performClickInternal(View.java:6574) at android.view.View.access$3100(View.java:778) at android.view.View$PerformClick.run(View.java:25885) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 2019-06-12 08:03:46.304 26280-26289/com.nibras.mobile.debug W/SQLiteCompiledSql: Releasing statement in a finalizer. Please ensure that you explicitly call close() on your cursor: CREATE TABLE UserElement_TBL ( -- ROW_ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , User_ID IN net.sqlcipher.database.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here at net.sqlcipher.database.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:62) at net.sqlcipher.database.SQLiteProgram.<init>(SQLiteProgram.java:79) at net.sqlcipher.database.SQLiteStatement.<init>(SQLiteStatement.java:39) at net.sqlcipher.database.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1702) at com.commonsware.cwac.saferoom.Database.compileStatement(Database.java:54) at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:125) at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:19) at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:110) at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:125) at com.squareup.sqldelight.db.SqlDriver$DefaultImpls.execute$default(SqlDriver.kt:56) at com.nibras.mobile.app.nibrasmobiledbImpl$Schema.create(nibrasmobiledbImpl.kt:47) at com.squareup.sqldelight.android.AndroidSqliteDriver$Callback.onCreate(AndroidSqliteDriver.kt:146) at com.commonsware.cwac.saferoom.Helper$OpenHelper.onCreate(Helper.java:168) at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:177) at com.commonsware.cwac.saferoom.Helper$OpenHelper.getWritableSupportDatabase(Helper.java:142) at com.commonsware.cwac.saferoom.Helper.getWritableDatabase(Helper.java:77) at com.squareup.sqldelight.android.AndroidSqliteDriver$database$2.invoke(AndroidSqliteDriver.kt:26) at com.squareup.sqldelight.android.AndroidSqliteDriver$database$2.invoke(AndroidSqliteDriver.kt:19) at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) at com.squareup.sqldelight.android.AndroidSqliteDriver.getDatabase(Unknown Source:7) at com.squareup.sqldelight.android.AndroidSqliteDriver.access$getDatabase$p(AndroidSqliteDriver.kt:19) at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:125) at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:19) at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:110) at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:125) at com.nibras.mobile.app.LogsQueriesImpl.insert(nibrasmobiledbImpl.kt:79) at nibrasCommon.core.platform.Utils$Companion.saveLogsInDB(Utils.kt:14) at nibrasCommon.features.login.AuthenticateViewModel.loginClick(AuthenticateViewModel.kt:161) at com.nibras.mobile.features.LoginActivity$onCreate$1.onClick(LoginActivity.kt:161) at android.view.View.performClick(View.java:6597) at android.view.View.performClickInternal(View.java:6574) at android.view.View.access$3100(View.java:778) at android.view.View$PerformClick.run(View.java:25885) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mhernand40 picture mhernand40  路  5Comments

jrodbx picture jrodbx  路  4Comments

davidbilik picture davidbilik  路  3Comments

LouisCAD picture LouisCAD  路  5Comments

treelzebub picture treelzebub  路  3Comments