简体   繁体   中英

backup and restore of encrypted database (sqlcipher, cacheword)?

I started to develop an android app using a sqlite database. After a while most of my wanted functions were implemented and I decided to insert database encryption. To achieve this I used sqlcipher in combination with cacheword to store and manage the key for encryption.

To backup and restore my database I used in case of unencrypted database simple methods to make a copy of mydb.db file to sdcard and vice versa. With encryption both methods first did their job without an error message, but after restore the app could not use my database.

The backup method:

public static void BackupDatabase() throws IOException {
    boolean success = true;
    File file = null;
    file = new File(Environment.getExternalStorageDirectory() +"/myapp");

    if(file.exists()) {
        success = true;
    }  
    else {
        success = file.mkdir();
    }

    if(success) {
        String inFileName = "/data/data/de.my.app/databases/mydb.db";
        File dbFile = new File(inFileName);
        FileInputStream fis = new FileInputStream(dbFile);

        String outFileName = Environment.getExternalStorageDirectory()+"/myapp/mydb.db.backup";
        // Open the empty db as the output stream
        OutputStream output = new FileOutputStream(outFileName);
        //transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[1024];
        int length;
        while ((length = fis.read(buffer))>0) {
            output.write(buffer, 0, length);
        }

        output.flush();
        output.close();
        fis.close();
    }
}

The restore method:

public static void RestoreDatabase(Context context) throws IOException {
    try {

        // Set the folder on the SDcard
        File directory = new File(Environment.getExternalStorageDirectory()+"/myapp/");
        boolean directoryB = new File(Environment.getExternalStorageDirectory()+"/myapp/", "/mydb.db.backup").exists();

        if (directoryB == true) {

            OutputStream myOutput;   
            myOutput = new FileOutputStream("/data/data/de.my.app/databases/mydb.db");

            // Set the input file stream up:

            InputStream myInputs = new FileInputStream(directory.getPath()+ "/mydb.db.backup");


            // Transfer bytes from the input file to the output file
            byte[] buffer = new byte[1024];
            int length;
            while ((length = myInputs.read(buffer))>0) {
                myOutput.write(buffer, 0, length);
            }


            // Close and clear the streams
            myOutput.flush();

            myOutput.close();

            myInputs.close();   

        }
        else {
            Toast.makeText(context, "Wiederherstellung gescheitert! Datei nicht gefunden! Ordner/Datei existiert nicht?", Toast.LENGTH_SHORT).show();
        }

    } catch (FileNotFoundException e) {
        Toast.makeText(context, "Wiederherstellung gescheitert! Datei nicht gefunden! Ordner/Datei existiert nicht?", Toast.LENGTH_LONG).show();

        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {   
        Toast.makeText(context, "Wiederherstellung gescheitert!", Toast.LENGTH_SHORT).show();


        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

A part of my error messages:

10-01 22:52:58.050: I/Database(4223): sqlite returned: error code = 26, msg = file is encrypted or is not a database
10-01 22:52:58.050: E/Database(4223): CREATE TABLE android_metadata failed
10-01 22:52:58.060: E/Database(4223): Failed to setLocale() when constructing, closing the database
10-01 22:52:58.060: E/Database(4223): net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
10-01 22:52:58.060: E/Database(4223):   at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
10-01 22:52:58.060: E/Database(4223):   at net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2102)
10-01 22:52:58.060: E/Database(4223):   at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1968)
10-01 22:52:58.060: E/Database(4223):   at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:901)
10-01 22:52:58.060: E/Database(4223):   at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:944)
10-01 22:52:58.060: E/Database(4223):   at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:107)
10-01 22:52:58.060: E/Database(4223):   at info.guardianproject.cacheword.SQLCipherOpenHelper.getWritableDatabase(SQLCipherOpenHelper.java:53)

How can I achieve to use a copy of an encrypted database as backup?


The use of sqlcipher_export helped to make a backup of my database. But now I have a new problem with the restore of the database.

I tried the following code:

SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(backupFile, backuppassword, null);
db.execSQL("ATTACH DATABASE '" + dbFile + "' AS encrypted KEY '" + mCacheWord.getEncryptionKey() + "';");
...

Here are the error messages:

10-30 00:56:42.845: I/Database(14407): sqlite returned: error code = 26, msg = statement aborts at 5: [ATTACH DATABASE '/data/data/.../databases/database.db' AS encrypted KEY '[B@42082da0';] file is encrypted or is not a database
10-30 00:56:42.845: E/Database(14407): Failure 26 (file is encrypted or is not a database) on 0x63bdedb0 when executing 'ATTACH DATABASE '/data/data/.../databases/database.db' AS encrypted KEY '[B@42082da0';'

I don't know how to fix this problem. Can you help me?

you should use sql_export function to backup, decrypt and encrypt your database. For the above error the solution is using NO_LOCALIZED_COLLATORS in the flags, but I am not sure exactly where are you getting the above error. You should be getting the above error at the place where you try to connect to the database using SQLiteDatabase class. can u post the code where you connect to your database after restoring

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM