Skip to content

Commit 56d9316

Browse files
siddh1004sagarwal
andauthored
Replace android-database-sqlcipher library with sqlcipher-android (#5464)
https://app.shortcut.com/simpledotorg/story/16100/migrate-deprecated-sqlcipher-library?team_id=1&iteration_ids=15786&iteration_ids=16015 --------- Co-authored-by: sagarwal <[email protected]>
1 parent 8258abb commit 56d9316

File tree

5 files changed

+59
-14
lines changed

5 files changed

+59
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- Migrate patient status view to Jetpack Compose
2020
- Migrate clinical decision support alert to Jetpack Compose
2121
- Bump sqlite-android version to 3.49.0
22+
- Replace `android-database-sqlcipher` library with `sqlcipher-android`
2223

2324
## 2025.05.20
2425

app/src/androidTest/java/org/simple/clinic/storage/DatabaseEncryptorTest.kt

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import android.app.Application
44
import androidx.room.Room
55
import com.google.common.truth.Truth.assertThat
66
import com.squareup.moshi.Moshi
7-
import net.sqlcipher.database.SupportFactory
7+
import net.zetetic.database.sqlcipher.SupportOpenHelperFactory
88
import org.junit.After
99
import org.junit.Before
1010
import org.junit.Test
1111
import org.simple.clinic.AppDatabase
1212
import org.simple.clinic.FakeMinimumMemoryChecker
1313
import org.simple.clinic.TestClinicApp
14+
import org.simple.clinic.TestData
1415
import org.simple.clinic.questionnaire.component.BaseComponentData
1516
import org.simple.clinic.storage.DatabaseEncryptor.State.DOES_NOT_EXIST
1617
import org.simple.clinic.storage.DatabaseEncryptor.State.ENCRYPTED
@@ -19,7 +20,6 @@ import org.simple.clinic.storage.DatabaseEncryptor.State.UNENCRYPTED
1920
import org.simple.clinic.user.User
2021
import org.simple.clinic.user.UserStatus
2122
import org.simple.clinic.util.MinimumMemoryChecker
22-
import org.simple.clinic.TestData
2323
import java.time.Instant
2424
import java.util.UUID
2525
import javax.inject.Inject
@@ -94,7 +94,7 @@ class DatabaseEncryptorTest {
9494
val encryptedDatabase = Room.databaseBuilder(appContext, AppDatabase::class.java, DB_NAME)
9595
.allowMainThreadQueries()
9696
.addTypeConverter(BaseComponentData.RoomTypeConverter(moshi))
97-
.openHelperFactory(SupportFactory(passphrase, null, false))
97+
.openHelperFactory(SupportOpenHelperFactory(passphrase))
9898
.build()
9999

100100
val encryptedUser = encryptedDatabase.userDao().userImmediate()
@@ -104,7 +104,7 @@ class DatabaseEncryptorTest {
104104
}
105105

106106
@Test
107-
fun if_device_doesnt_have_min_req_memory_then_skip_database_encryption() {
107+
fun if_device_does_not_have_min_req_memory_then_skip_database_encryption() {
108108
// given
109109
(minimumMemoryChecker as FakeMinimumMemoryChecker).hasMinMemory = false
110110

@@ -114,4 +114,49 @@ class DatabaseEncryptorTest {
114114
// then
115115
assertThat(databaseEncryptor.databaseState(DB_NAME)).isEqualTo(SKIPPED)
116116
}
117+
118+
@Test
119+
fun when_database_is_already_encrypted_it_should_do_nothing() {
120+
// given
121+
val passphrase = databaseEncryptor.passphrase
122+
val encryptedDatabase = Room.databaseBuilder(appContext, AppDatabase::class.java, DB_NAME)
123+
.allowMainThreadQueries()
124+
.addTypeConverter(BaseComponentData.RoomTypeConverter(moshi))
125+
.openHelperFactory(SupportOpenHelperFactory(passphrase))
126+
.build()
127+
128+
val expectedUser = TestData.loggedInUser(uuid = UUID.randomUUID())
129+
encryptedDatabase.userDao().createOrUpdate(expectedUser)
130+
encryptedDatabase.close()
131+
132+
assertThat(databaseEncryptor.databaseState(DB_NAME)).isEqualTo(ENCRYPTED)
133+
134+
// when
135+
databaseEncryptor.execute(databaseName = DB_NAME)
136+
137+
// then
138+
assertThat(databaseEncryptor.databaseState(DB_NAME)).isEqualTo(ENCRYPTED)
139+
140+
val reOpenedEncryptedDb = Room.databaseBuilder(appContext, AppDatabase::class.java, DB_NAME)
141+
.allowMainThreadQueries()
142+
.addTypeConverter(BaseComponentData.RoomTypeConverter(moshi))
143+
.openHelperFactory(SupportOpenHelperFactory(passphrase))
144+
.build()
145+
146+
val actualUser = reOpenedEncryptedDb.userDao().userImmediate()
147+
assertThat(actualUser).isEqualTo(expectedUser)
148+
reOpenedEncryptedDb.close()
149+
}
150+
151+
@Test
152+
fun when_database_does_not_exist_it_should_do_nothing() {
153+
// given
154+
assertThat(databaseEncryptor.databaseState(DB_NAME)).isEqualTo(DOES_NOT_EXIST)
155+
156+
// when
157+
databaseEncryptor.execute(databaseName = DB_NAME)
158+
159+
// then
160+
assertThat(databaseEncryptor.databaseState(DB_NAME)).isEqualTo(DOES_NOT_EXIST)
161+
}
117162
}

app/src/main/java/org/simple/clinic/storage/DatabaseEncryptor.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import androidx.annotation.VisibleForTesting
66
import androidx.core.content.edit
77
import io.reactivex.Observable
88
import io.reactivex.subjects.BehaviorSubject
9-
import net.sqlcipher.database.SQLiteDatabase
10-
import net.sqlcipher.database.SQLiteStatement
9+
import net.zetetic.database.sqlcipher.SQLiteDatabase
10+
import net.zetetic.database.sqlcipher.SQLiteStatement
1111
import org.simple.clinic.di.AppScope
1212
import org.simple.clinic.storage.DatabaseEncryptor.State.ENCRYPTED
1313
import org.simple.clinic.storage.DatabaseEncryptor.State.SKIPPED
@@ -45,7 +45,7 @@ class DatabaseEncryptor @Inject constructor(
4545
.distinctUntilChanged()
4646

4747
init {
48-
SQLiteDatabase.loadLibs(appContext)
48+
System.loadLibrary("sqlcipher");
4949
}
5050

5151
fun execute(databaseName: String) {
@@ -79,7 +79,7 @@ class DatabaseEncryptor @Inject constructor(
7979
val databasePath = appContext.getDatabasePath(databaseName)
8080
if (databasePath.exists()) {
8181
val newFile = File.createTempFile("simple_database_encryption", "tmp", appContext.cacheDir)
82-
var db = SQLiteDatabase.openDatabase(databasePath.absolutePath, "", null, SQLiteDatabase.OPEN_READWRITE)
82+
var db = SQLiteDatabase.openDatabase(databasePath.absolutePath, null, SQLiteDatabase.OPEN_READWRITE)
8383
val version = db.version
8484

8585
db.close()
@@ -123,8 +123,7 @@ class DatabaseEncryptor @Inject constructor(
123123
if (databasePath.exists()) {
124124
var db: SQLiteDatabase? = null
125125
return try {
126-
db = SQLiteDatabase.openDatabase(databasePath.absolutePath, "",
127-
null, SQLiteDatabase.OPEN_READONLY)
126+
db = SQLiteDatabase.openDatabase(databasePath.absolutePath, null, SQLiteDatabase.OPEN_READONLY)
128127
db.version
129128
State.UNENCRYPTED
130129
} catch (e: Exception) {

app/src/main/java/org/simple/clinic/storage/StorageModule.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import com.squareup.moshi.Moshi
88
import dagger.Module
99
import dagger.Provides
1010
import io.requery.android.database.sqlite.SQLiteGlobal
11-
import net.sqlcipher.database.SupportFactory
11+
import net.zetetic.database.sqlcipher.SupportOpenHelperFactory
1212
import org.simple.clinic.AppDatabase
1313
import org.simple.clinic.DATABASE_NAME
1414
import org.simple.clinic.di.AppScope
@@ -51,7 +51,7 @@ class StorageModule {
5151

5252
val helperFactory = if (minimumMemoryChecker.hasMinimumRequiredMemory()) {
5353
val passphrase = databaseEncryptor.passphrase
54-
SupportFactory(passphrase)
54+
SupportOpenHelperFactory(passphrase)
5555
} else {
5656
factory
5757
}

gradle/libs.versions.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ composeThemeAdapter = "0.36.0"
4343

4444
ksp = "2.1.20-1.0.31"
4545

46-
sqlCipher = "4.5.4"
46+
sqlCipher = "4.9.0"
4747

4848
[libraries]
4949
android-desugaring = "com.android.tools:desugar_jdk_libs:2.1.5"
@@ -220,7 +220,7 @@ androidx-compose-livedata = { module = "androidx.compose.runtime:runtime-livedat
220220
androidx-compose-test-junit = { module = "androidx.compose.ui:ui-test-junit4" }
221221
androidx-compose-test-manifest = { module = "androidx.compose.ui:ui-test-manifest" }
222222

223-
sqlCipher = { module = "net.zetetic:android-database-sqlcipher", version.ref = "sqlCipher" }
223+
sqlCipher = { module = "net.zetetic:sqlcipher-android", version.ref = "sqlCipher" }
224224

225225
[plugins]
226226
android-application = { id = "com.android.application", version.ref = "agp" }

0 commit comments

Comments
 (0)