从我现有应用程序的数据库

时间:2015-06-03 13:26:53

标签: android encryption android-sqlite sqlcipher-android

我有一个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

1 个答案:

答案 0 :(得分: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);
        }

    }