Using SQLCipher with Android [duplicate]

房东的猫 提交于 2020-01-11 07:45:10

问题


I have previously asked this question and have not got any appropriate answer.

I have an app published in the Play Store which makes heavy use of SQLite database.

Now I need to secure the database using SQLCipher. Here are some problems I am facing.

1) 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?

(I would like a short tutorial on this)

2) How should I check if the database is unencrypted and then how can I encrypt it? Should I do this only once? What should be the best practice?

(The possible duplicate doesn't answer this)

3) 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?

(This explanation is also not provided in the duplicate question)


回答1:


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?

You don't. Among other things, you have to adjust your UI to ask the user for a passphrase, and ensure that you can ask for that passphrase as needed (e.g., user resumes a task from some "inner" activity, not just when the user runs your app via a launcher icon).

I would like a short tutorial on this

First, that is not how Stack Overflow works.

Second, decent coverage of SQLCipher for Android takes much more than can fit in a single Stack Overflow answer. I have an 18-page chapter on the subject in my book, for example. This answer is already longer than the vast majority of Android questions, and I would not blame people for closing this question as being too broad.

How should I check if the database is unencrypted

Try opening it using the SQLCipher for Android classes with "" as the passphrase. If it opens successfully, the database is unencrypted. If that fails, either the database is corrupt or encrypted, and without the proper passphrase, you cannot tell the difference.

how can I encrypt it?

The basic approach is:

  • Open the unencrypted database

  • Use the ATTACH SQL statement to attach an empty file to serve as the new encrypted database, supplying your desired passphrase, and naming the attached database encrypted within your database session

  • Run the SELECT sqlcipher_export('encrypted') in the open (unencrypted) database, which will export the data from the unencrypted database into the encrypted one (with the exception of the database schema version, which is handled in later steps)

  • Call getVersion() on the open (unencrypted) database and hold onto that value for a bit

  • Close the unencrypted database

  • Open the encrypted database, using your passphrase

  • Call setVersion() on the encrypted database, supplying the value you cached from getVersion() of the unencrypted database

  • Close the encrypted database

  • If desired, delete the unencrypted database and rename the encrypted one to the name of the now-deleted unencrypted one, so that your conversion appears to happen in place

This utility method implements the above approach:

  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);
    }
  }

In the interests of full disclosure, I have not tried this in a while, and so there may need to be some tweaks.

Should I do this only once?

Only you can answer that, as nobody here is going to know much about your app.

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

Yes.

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

Only you can answer that, as nobody here is going to know much about your app.

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

Yes, though you are welcome to delete it if and when you are done with it.



来源:https://stackoverflow.com/questions/29860873/using-sqlcipher-with-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!