Question

I'm using the below piece of code to encrypt and decrypt the database i'm able to encrypt but when i'm trying to decrypt i'm getting the below exception.I referred this documentation and TestCases too still facing the same problem.

Exception:

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

Encrypt:

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

Decrypt:

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();
 }
Was it helpful?

Solution

You do not need to set cipher_default_use_hmac to off in the preKey event when you attempt to decrypt the database. It is not being disabled when you encrypt the database so an HMAC is being included for every page of the database. Try removing your SQLiteDatabaseHook from the decryption function. Also, consider joining the SQLCipher Mailing List for these type of discussions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top