【问题标题】:Using SQLCipher with Android [duplicate]在 Android 中使用 SQLCipher [重复]
【发布时间】:2015-04-25 04:04:20
【问题描述】:

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

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

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

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

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

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

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

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

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

【问题讨论】:

  • 您可以(很快)为您的其他问题添加赏金。再次问“相同”的问题是不受欢迎的。
  • @ArtjomB。这个问题在很多方面与可能的重复问题不同。这个问题更详细,涵盖了广泛的场景。
  • 在那种情况下,它太宽泛了。每个帖子坚持一个问题,而不是 8 个(原文如此!)。

标签: android encryption android-sqlite sqlcipher


【解决方案1】:

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

你没有。除其他事项外,您必须调整您的 UI 以要求用户输入密码,并确保您可以根据需要要求输入该密码(例如,用户从某些“内部”活动恢复任务,而不仅仅是在用户运行您的应用程序通过启动器图标)。

我想要一个简短的教程

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

其次,对适用于 Android 的 SQLCipher 的体面覆盖需要很多,而不是单个 Stack Overflow 答案。例如,我有an 18-page chapter on the subject in my book。这个答案已经比绝大多数 Android 问题都要长,我不会责怪人们结束这个问题过于宽泛。

我应该如何检查数据库是否未加密

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

如何加密?

基本做法是:

  • 打开未加密的数据库

  • 使用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);
    }
  }

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

我应该只做一次吗?

只有你能回答这个问题,因为这里没有人会对你的应用了解太多。

当我加密我现有的未加密数据库时,SQLCipher 是否会创建一个新数据库?

是的。

如果是,我应该如何管理这个新的?

只有你能回答这个问题,因为这里没有人会对你的应用了解太多。

那我的未加密的旧数据库呢?它还在那里吗?

是的,不过如果您完成了它,欢迎您删除它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-28
    • 2017-01-22
    • 2013-07-14
    • 2012-10-01
    • 2014-02-01
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    相关资源
    最近更新 更多