我正在构建一个使用房间数据库的应用程序,并使用 SQLCipher 对其进行加密。我如何检查数据是否真的加密,因为这是我第一次使用加密,我不知道我是否正确使用。
问问题
133 次
1 回答
0
假设您要检查数据库是否在应用程序中加密,那么您必须小心一点。
建议通过房间打开数据库而不使用密钥进行检查,如果数据库被加密,将导致数据丢失。
这是因为当房间在加密时尝试打开数据库时,它将被视为损坏的数据库,因为整个文件都已加密,因此不是有效的数据库文件(标题字符串不是必需的标题字符串“SQLite 格式 3\ 000”)。Room 然后将删除损坏的数据库,然后调用 onCreate 方法来提供一个没有数据的有效新数据库。
我建议您考虑打开文件,而不是作为数据库,而是作为文件并检查前 16 个字节是否为“SQLite 格式 3\000”。
如果是“SQLite format 3\000”那么数据库没有被加密,如果不是“SQLite format 3\000”那么数据库(如果文件实际上是一个/数据库文件)可能被加密了。
也许考虑以下内容:-
/**
* Check to see if the database is encrypted
*
* NOTE assumes encrypted if the database header string is not the required SQLite header string
* WARNING any invalid file would be considered encrypted
*/
fun isEncryptedDatabase(context: Context, databaseName: String): Boolean {
var rv = false
// SQlite header String 16 bytes as SQLite format 3\000
// hex representation is 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00
val requiredSQLiteFileHeaderString: ByteArray
= byteArrayOf(0x53,0x51,0x4c,0x69,0x74,0x65,0x20,0x66,0x6F,0x72,0x6D,0x72,0x61,0x74,0x20,0x33,0x0)
var dbFileHeader = ByteArray(requiredSQLiteFileHeaderString.size)
var i: InputStream
try {
i = FileInputStream(context.getDatabasePath(databaseName))
i.read(dbFileHeader)
if(!dbFileHeader.equals(requiredSQLiteFileHeaderString)) {
rv = true
}
i.close()
} catch (e: IOException) {
rv = true;
}
return rv
}
}
您可以在 Room 之外和 Room 打开数据库之前使用它。考虑到上面使用了 Context 的 getDatabasePath 方法,那么真实结果(数据库被加密)很可能是由于数据库被加密而不是另一种类型的文件。
这是使用嵌入在 @Database 类中的上述代码的示例(基于使用用于上述链接答案的代码)。活动代码是:-
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: AllDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (!TheDatabase.isEncryptedDatabase(this,TheDatabase.DATABASENAME)) {
//.... handle un-encrypted database here
}
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
....
}
}
- 注意为了方便和简洁,上面使用了主线程(
.allowMainThreadQueries()
即已在 databaseBuilder 中编码)
于 2021-10-29T01:20:37.293 回答