将 SQLCipher 与 Android 一起使用

Using SQLCipher with Android

我以前问过这个问题,但没有得到任何合适的答案。

我在 Play 商店中发布了一个应用程序,它大量使用了 SQLite 数据库。

现在我需要使用 SQLCipher 来保护数据库。这是我面临的一些问题。

1) 如何将 SQLCipher 与我现有的未加密数据库无缝集成,以便我的应用程序正常运行但现在数据库已加密?

(我想要一个简短的教程)

2) 我应该如何检查数据库是否未加密,然后如何加密?我应该只做一次吗?最佳做法应该是什么?

(可能的重复没有回答这个问题)

3) 当我加密现有的未加密数据库时,SQLCipher 会创建一个新数据库吗?如果是,我应该如何管理这个新的?那我未加密的旧数据库呢?它还留在那里吗?

(重复问题中也没有提供此解释)

How can I seamlessly integrate SQLCipher with my existing unencrypted database, so that my app works as it works normally but now the databases are encrypted?

你不知道。除其他事项外,您必须调整 UI 以向用户询问密码,并确保您可以根据需要询问该密码(例如,用户从某些 "inner" activity,而不仅仅是当用户通过启动器图标运行您的应用程序时)。

I would like a short tutorial on this

首先,Stack Overflow 不是这样工作的。

其次,SQLCipher for Android 的体面覆盖比单个 Stack Overflow 答案中的 。例如,我有 an 18-page chapter on the subject in my book。这个答案已经比绝大多数 Android 问题都长,我不会责怪人们因为太宽泛而关闭这个问题。

How should I check if the database is unencrypted

尝试使用SQLCipher for Android 类打开它,密码为""。如果成功打开,则数据库未加密。如果失败,则数据库已损坏或已加密,如果没有正确的密码,您将无法区分。

how can I encrypt it?

基本方法是:

  • 打开未加密的数据库

  • 使用ATTACH SQL语句附加一个空文件作为新的加密数据库,提供你想要的密码,并命名附加的数据库encrypted 在你的数据库会话中

  • 运行 打开(未加密)数据库中的 SELECT sqlcipher_export('encrypted'),这会将未加密数据库中的数据导出到加密数据库中(数据库模式除外)版本,在后面的步骤中处理)

  • 在打开的(未加密的)数据库上调用 getVersion() 并保留该值一段时间

  • 关闭未加密的数据库

  • 使用您的密码打开加密的数据库

  • 在加密数据库上调用 setVersion(),提供您从未加密数据库的 getVersion() 缓存的值

  • 关闭加密数据库

  • 如果需要,删除未加密的数据库并将加密的数据库重命名为现已删除的未加密数据库的名称,这样您的转换就好像发生了

此实用程序方法实现了上述方法:

  public static void encrypt(Context ctxt, String dbName,
                             String passphrase) throws IOException {
    File originalFile=ctxt.getDatabasePath(dbName);

    if (originalFile.exists()) {
      File newFile=
          File.createTempFile("sqlcipherutils", "tmp",
                              ctxt.getCacheDir());
      SQLiteDatabase db=
          SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(),
                                      "", null,
                                      SQLiteDatabase.OPEN_READWRITE);

      db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
                                  newFile.getAbsolutePath(), passphrase));
      db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
      db.rawExecSQL("DETACH DATABASE encrypted;");

      int version=db.getVersion();

      db.close();

      db=
          SQLiteDatabase.openDatabase(newFile.getAbsolutePath(),
                                      passphrase, null,
                                      SQLiteDatabase.OPEN_READWRITE);
      db.setVersion(version);
      db.close();

      originalFile.delete();
      newFile.renameTo(originalFile);
    }
  }

为了全面披露,我有一段时间没有尝试过,因此可能需要进行一些调整。

Should I do this only once?

只有您可以回答这个问题,因为这里没有人会很了解您的应用程序。

When I encrypt my existing unencrypted database, do SQLCipher create a new database?

是的。

If yes, how should I be managing this new one?

只有您可以回答这个问题,因为这里没有人会很了解您的应用程序。

And what about my old database which is unencrypted? Does it still stay there?

是的,但欢迎您在完成后删除它。