gpt4 book ai didi

android - SQLCipher for Android getReadableDatabase() Overherad

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:48:29 30 4
gpt4 key购买 nike

我修改了我的 DatabaseHelper 类以使用 SQLCipher 库。

为此,我:

  • 将 Assets 复制到我的 Assets 文件夹中,将库(armeabi、x86、commons-codec、guava-r09、sqlcipher)复制到我的 libs 文件夹中。

  • 更改了我的 DatabaseHelper 中的导入类,以便它们指向 import net.sqlcipher.database.*相反。

  • 调用 SQLiteDatabase.loadLibs(getApplicationContext());当应用程序启动时。

  • 修改了我调用 getReadableDatabase() 的行和 getWriteableDatabase()以便他们将密码短语作为参数;

一切似乎都正常,因为数据已正确读取/写入。我的问题与性能有关,因为我的应用程序可能会以某种频率执行数据库操作,导致它变慢(在迁移到 SQLCipher 之后)。

对于我的 DatabaseHelper 方法,我相信我遵循的是标准方法,例如:

/*
* Getting all MyObjects
*/
public List<MyObject> getMyObjects() {

List<MyObject> objects = new ArrayList<MyObject>();

String selectQuery = "SELECT * FROM " + TABLE_NAME;
Log.v(LOG, selectQuery);

// Open
SQLiteDatabase db = this.getReadableDatabase("...the password...");
// I know this passphrase can be figured out by decompiling.

// Cursor with query
Cursor c = db.rawQuery(selectQuery, null);

// looping through all rows and adding to list
if (c.moveToFirst()) {
do {
MyObject object = createMyObjectFromCursor(c); // Method that builds MyObject from Cursor data
// adding to list
objects.add(object);
} while (c.moveToNext());
}

c.close();
db.close();
return objects;
}

我并不完全熟悉 SQLCipher 的内部机制(例如,当我调用 getReadableDatabase() 时它会解密整个数据库文件吗?)但是,在调试时,开销似乎在 getReadableDatabase(password) 中和 getWritableDatabase(password) ,如果我上面的假设是真的,这是有道理的。

将这些调用移至 DatabaseHelper.open() 和 DatabaseHelper.close() 方法(只要 Activity 实例化 DatabaseHelper 时就会调用它们),而不是在每个单独的方法上调用它们,这是一种不好的做法吗?请分享您关于如何解决此问题的知识。

编辑:

我已经使用 DDMS 跟踪其中一种方法,我可以看到开销确实在 SQLiteOpenHelper.getReadableDatabase() 处。 (每次约 4 秒)。查询似乎工作得很快,我认为我不需要担心它们。

如果我向下钻取通话,每次都跟随持续时间最长的通话,我最终会得到:

SQLiteDatabase.OpenOrCreateDatabase --> SqLiteDatabase.openDatabase --> SQLiteDatabase.openDatabase --> SQLiteDatabase.setLocale

所以 SQLiteDatabase.setLocale(java.util.Locale)似乎是罪魁祸首,因为每次调用 getReadableDatabase() 都需要大约 4 秒。我查看了 SQLiteDatabase 的源代码,它只是锁定了数据库,调用 native_setLocale(locale.toString(), mFlags) (4 秒的开销发生在这里)并解锁数据库。

知道为什么会这样吗?

最佳答案

您看到的性能问题很可能是由于 SQLCipher key 派生引起的。 SQLCipher 打开数据库的性能故意很慢,使用 PBKDF2 执行 key 推导(即数千次 SHA1 操作)以抵御暴力和字典攻击(您可以在 http://sqlcipher.net/design 阅读更多相关信息)。此 Activity 被推迟到第一次使用数据库时,这恰好发生在 setLocale 中,这就是为什么您在分析时会在那里看到性能问题。

最好的选择是缓存数据库连接,这样它就可以多次使用,而不必重复打开和键入数据库。如果可能,最好在启动期间打开一次数据库。对同一数据库句柄的后续访问不会触发 key 派生,因此性能会快得多。

如果这不可能,另一个选项是禁用或削弱 key 派生。这将导致 SQLCipher 在派生 key 时使用较少轮次的 PBKDF2。虽然这将使数据库打开得更快,但从安全角度来看,它明显较弱。因此,除非特殊情况,否则不推荐使用。也就是说,这里是关于如何减少 KDF 迭代的信息:

http://sqlcipher.net/sqlcipher-api/#kdf_iter

关于android - SQLCipher for Android getReadableDatabase() Overherad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22176445/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com