使用Android中的SQLCipher加密/解密现有数据库

时间:2014-01-07 07:07:38

标签: android database sqlite sqlcipher

我正在使用下面的代码来加密和解密我能够加密的数据库但是当我尝试解密时我得到了以下异常。我引用了这个documentation和{ {3}}仍然面临同样的问题。

例外:

sqlite returned: error code = 26, msg = file is encrypted or is not a database
CREATE TABLE android_metadata failed
Failed to setLocale() when constructing, closing the database
net.sqlcipher.database.SQLiteException: file is encrypted or is not a database

加密

private static void ConvertNormalToSQLCipheredDB(Context context,
 String startingFileName, String endingFileName, String filePassword)
 throws IOException {
  File mStartingFile = context.getDatabasePath(startingFileName);
  if (!mStartingFile.exists()) {
   return;
  }
  File mEndingFile = context.getDatabasePath(endingFileName);
  mEndingFile.delete();
  SQLiteDatabase database = null;
  try {
   database = SQLiteDatabase.openOrCreateDatabase(MainApp.mainDBPath,
   "", null);
   database.rawExecSQL(String.format(
   "ATTACH DATABASE '%s' AS encrypted KEY '%s'",
   mEndingFile.getAbsolutePath(), filePassword));
   database.rawExecSQL("select sqlcipher_export('encrypted')");
   database.rawExecSQL("DETACH DATABASE encrypted");
   database.close();
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   if (database.isOpen())
    database.close();
   mStartingFile.delete();
  }
 }

解密:

private void decryptDatabase() {
  File unencryptedFile = getDatabasePath(PhoneNumbersDatabase.DATABASE_NAME);
  unencryptedFile.delete();
  File databaseFile = getDatabasePath("encrypt.db");
  SQLiteDatabaseHook hook = new SQLiteDatabaseHook() {
   public void preKey(SQLiteDatabase sqLiteDatabase) {
    sqLiteDatabase
      .rawExecSQL("PRAGMA cipher_default_use_hmac = off;");
   }

   public void postKey(SQLiteDatabase sqLiteDatabase) {
   }
  };
  SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(
    databaseFile, "test123", null, hook); // Exception 
  if (database.isOpen()) {
   database.rawExecSQL(String.format(
     "ATTACH DATABASE '%s' as plaintext KEY '';",
     unencryptedFile.getAbsolutePath()));
   database.rawExecSQL("SELECT sqlcipher_export('plaintext');");
   database.rawExecSQL("DETACH DATABASE plaintext;");
   android.database.sqlite.SQLiteDatabase sqlDB = android.database.sqlite.SQLiteDatabase
     .openOrCreateDatabase(unencryptedFile, null);
   sqlDB.close();
   database.close();
  }

  databaseFile.delete();
 }

1 个答案:

答案 0 :(得分:4)

当您尝试解密数据库时,无需在cipher_default_use_hmac事件中将off设置为preKey。加密数据库时不会禁用它,因此数据库的每个页面都包含HMAC。尝试从解密功能中删除SQLiteDatabaseHook。另外,请考虑加入SQLCipher Mailing List进行这类讨论。

相关问题