2015-06-03 37 views
0

我有一个使用SQLCipher进行数据库加密的Android应用程序。该应用程序已上线,并有许多活跃的用户。我正在寻找一种解决方案,它可以从应用程序的现有数据库中删除SQLCipher加密,而不会丢失用户的数据。从我现有的应用程序数据库中删除SQLCipher加密

我试着做与this后提到的相反,但无法打开我的加密数据库文件。

public static void decrypt(Context ctxt, String dbName, String passphrase) 
     throws IOException { 
    try { 

     File originalFile = ctxt.getDatabasePath(dbName); 

     int version = 0; 
     if (originalFile.exists()) { 
      File newFile = File.createTempFile("sqlite", "tmp", ctxt.getCacheDir()); 

      net.sqlcipher.database.SQLiteDatabase dbCipher = net.sqlcipher.database.SQLiteDatabase.openDatabase(
        originalFile.getAbsolutePath(), passphrase, null, 
        net.sqlcipher.database.SQLiteDatabase.OPEN_READWRITE); 

      if (dbCipher.isOpen()) { 
       dbCipher.rawExecSQL(String.format(
         "ATTACH DATABASE '%s' AS plaintext KEY '%s';", 
         newFile.getAbsolutePath(), passphrase)); 
       dbCipher.rawExecSQL("SELECT sqlcipher_export('plaintext')"); 
       dbCipher.rawExecSQL("DETACH DATABASE plaintext;"); 

       version = dbCipher.getVersion(); 

       dbCipher.close(); 
      } 


      SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(newFile, null); 
      db.setVersion(version); 
      db.close(); 

      originalFile.delete(); 
      newFile.renameTo(originalFile); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

} 

而且,这里是错误提示我...

06-04 11:33:54.929: E/SQLiteLog(12309): (26) file is encrypted or is not a database 
06-04 11:33:54.929: E/DefaultDatabaseErrorHandler(12309): Corruption reported by sqlite on database: /data/data/ril.jio.protrak/cache/sqlite1817652413tmp 
+3

创建一个常规的SQLite数据库,打开SQLCipher数据库,并将数据从SQLCipher数据库复制到SQLite数据库。这将是我显示[在此堆栈溢出答案](https://stackoverflow.com/a/29867682/115145)中的'encrypt()'方法的反函数。 – CommonsWare

+0

如果你只是想解密数据库,并继续使用sqlcipher lib,我认为你可以'重新键入'空数据库的新密码,但如果你想移动到android集成的sqlite你必须采取将数据从旧数据库迁移到新数据库。 – Yazan

回答

1

这里是样品SQLCipher加密数据库文件导出成纯文本的数据库文件。

恢复到

import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 

而不是

import net.sqlcipher.Cursor; 
import net.sqlcipher.database.SQLiteDatabase; 
import net.sqlcipher.database.SQLiteOpenHelper; 

现在使用这个类来加密数据库文件导出到正常的纯文本

import java.io.File; 
     import java.io.FileInputStream; 
     import java.io.FileOutputStream; 
     import java.io.InputStream; 
     import java.io.OutputStream; 
     import android.content.Context; 
     import android.os.AsyncTask; 
     import android.util.Log; 

    public class ExportSQLCipherEncryptedDBIntoPlainText extends 
      AsyncTask<Void, Integer, Boolean> { 

     private Context context; 
     private String dbName, password, filePath; 

     public ExportSQLCipherEncryptedDBIntoPlainText(Context context, 
       String dbName, String password, String filePath) { 

      this.context = context; 
      this.dbName = dbName; 
      this.password = password; 
      this.filePath = filePath; 

     } 

     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 
     } 

     @Override 
     protected Boolean doInBackground(Void... arg0) { 

      try { 

       File originalFile = context.getDatabasePath(dbName); 

       int version = 0; 
       if (originalFile.exists()) { 

        // create new file 
        File newFile = new File(filePath + "/plaintext.db"); 
        File newAdditionalFile = new File(filePath + "/plaintext.db-journal"); 
        if (!newFile.exists()) { 

         net.sqlcipher.database.SQLiteDatabase.loadLibs(context); 
         net.sqlcipher.database.SQLiteDatabase dbCipher = net.sqlcipher.database.SQLiteDatabase 
           .openDatabase(
             originalFile.getAbsolutePath(), 
             password, 
             null, 
             net.sqlcipher.database.SQLiteDatabase.OPEN_READWRITE); 

         if (dbCipher.isOpen()) { 
          dbCipher.rawExecSQL("ATTACH DATABASE '" + filePath 
            + "/plaintext.db' AS plaintext KEY ''"); 
          dbCipher.rawExecSQL("SELECT sqlcipher_export('plaintext')"); 
          dbCipher.rawExecSQL("DETACH DATABASE plaintext"); 
          version = dbCipher.getVersion(); 
          dbCipher.close(); 
         } 

         if (newFile.exists()) { 
          android.database.sqlite.SQLiteDatabase db = android.database.sqlite.SQLiteDatabase 
            .openOrCreateDatabase(newFile, null); 
          db.setVersion(version); 
          db.close(); 
          originalFile.delete(); 
          // newFile.renameTo(originalFile); 
         } 

         Log.i("AndroidLib", 
           "Copying database from external directory to application Started"); 
         byte[] buffer = new byte[1024]; 
         OutputStream myOutput = null; 
         int length; 
         // Open your local db as the input stream 
         InputStream myInput = null; 
         myInput = new FileInputStream(newFile); 
         // transfer bytes from the inputfile to the 
         // outputfile 
         myOutput = new FileOutputStream(originalFile); 
         while ((length = myInput.read(buffer)) > 0) { 
          myOutput.write(buffer, 0, length); 
         } 

         myOutput.flush(); 
         myOutput.close(); 
         myInput.close(); 

         if (originalFile.exists()) { 

          android.database.sqlite.SQLiteDatabase db = android.database.sqlite.SQLiteDatabase 
            .openOrCreateDatabase(originalFile, null); 

          newFile.delete(); 

          if (newAdditionalFile.exists()) { 
           newAdditionalFile.delete(); 
          } 

          Log.i("AndroidLib", 
            "Copying database from external directory to application Completed successfully"); 
         } 



        } 

       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      return true; 
     } 

     @Override 
     protected void onPostExecute(Boolean result) { 
      // TODO Auto-generated method stub 
      super.onPostExecute(result); 
     } 

    } 
相关问题