Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encrypt Existing Database with SQLCipher in Android

I have a database file in my assets that I copy in the app database folder. After the copy (it works), I want to encrypt the copied database with SQLCipher.

For some reason, I get this error:

Database: sqlite returned: error code = 26, msg = statement aborts at 5: [ATTACH DATABASE '/data/user/0/com.grandeguru.lagmeup/databases/AIRPORTS_DB.db' AS encrypted KEY 'password';] file is encrypted or is not a database

If I look the Database with a root explorer, it is still not encrypted and visible, so I suppose the error is related to the file logic inside the encrypt method.

This is the code of the DatabaseHelper class I created, that manages also the copy from assets:

public class DatabaseHelper extends SQLiteOpenHelper {

private SQLiteDatabase myDB;
private Context context;
public static String DB_NAME = "AIRPORTS_DB.db";
public static String DB_PATH = "/data/data/com.grandeguru.lagmeup/databases/";
public static final int DB_VERSION = 1;


public DatabaseHelper(Context context) {
    super(context, DB_NAME, null, DB_VERSION);
    myDB.loadLibs(context);
    this.context = context;
}

// THE ERROR IS SOMEWHERE INSIDE HERE
public void encryptDataBase(String passphrase) throws IOException {

    File originalFile = context.getDatabasePath(DB_NAME);

    File newFile = File.createTempFile("sqlcipherutils", "tmp", context.getCacheDir());

    openDataBase("");

    myDB.rawExecSQL("ATTACH DATABASE '" + originalFile.getPath() + "' AS encrypted KEY '" + passphrase + "';");
    myDB.rawExecSQL("SELECT sqlcipher_export('encrypted');");
    myDB.rawExecSQL("DETACH DATABASE encrypted;");
    myDB.close();
    myDB = SQLiteDatabase.openDatabase(newFile.getAbsolutePath(), passphrase, null, SQLiteDatabase.OPEN_READWRITE);
    myDB.close();
    newFile.renameTo(originalFile);
    originalFile.delete();
}

private boolean checkDataBase() {
    File databasePath = context.getDatabasePath(DB_NAME);
    return databasePath.exists();
}


public void copyDataBase() throws IOException {
    try {
        File f = context.getDatabasePath(DB_NAME);
        InputStream in = context.getAssets().open(DB_NAME);
        OutputStream out = new FileOutputStream(f.getAbsolutePath());
        byte[] buffer = new byte[1024];
        int length;
        while ((length = in.read(buffer)) > 0) {
            out.write(buffer, 0, length);
        }
        out.flush();
        out.close();
        in.close();
        Log.d("copy database", "finita copia db");

        encryptDataBase("password");
    } catch (Exception e) {
        Log.e("copy database", e.getMessage());
    }

}


public void openDataBase(String passphrase) throws SQLException {
    String myPath = DB_PATH + DB_NAME;
    myDB = SQLiteDatabase.openDatabase(myPath, passphrase, null, SQLiteDatabase.OPEN_READWRITE);
}


public void createDataBase() throws IOException {
    boolean dbExist = checkDataBase();

    if (dbExist) {
    } else {
        this.getReadableDatabase("");
        try {
            copyDataBase();
        } catch (IOException e) {
            Log.e("create database", e.getMessage());
        }
    }
}

}

like image 293
Mr.Sparkle Avatar asked Sep 14 '16 16:09

Mr.Sparkle


People also ask

What encryption does SQLCipher use?

SQLCipher does not implement its own encryption. Instead it uses the widely available encryption libraries like OpenSSL libcrypto, LibTomCrypt, and CommonCrypto for all cryptographic functions.

Is SQLCipher secure?

SQLCipher is an open source library that provides transparent, secure 256-bit AES encryption of SQLite database files.

How do I encrypt a room database?

We first need to create the (SQLCipher) SupportFactory , and we will provide the passphrase we want to use as a MasterKey for the encryption. Then we tell our Room database builder, to use this factory, thanks to openHelperFactory() . From now on, the Room Database is encrypted.

What is DB browser SQLCipher?

DB Browser for SQLite (DB4S) is a high quality, visual, open source tool to create, design, and edit database files compatible with SQLite. DB4S is for users and developers who want to create, search, and edit databases.


1 Answers

I solved, I write my solution as future reference. I was simply getting the wrong path

public void encryptDataBase(String passphrase) throws IOException {

    File originalFile = context.getDatabasePath(DB_NAME);

    File newFile = File.createTempFile("sqlcipherutils", "tmp", context.getCacheDir());

    SQLiteDatabase existing_db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, "", null, SQLiteDatabase.OPEN_READWRITE);

    existing_db.rawExecSQL("ATTACH DATABASE '" + newFile.getPath() + "' AS encrypted KEY '" + passphrase + "';");
    existing_db.rawExecSQL("SELECT sqlcipher_export('encrypted');");
    existing_db.rawExecSQL("DETACH DATABASE encrypted;");

    existing_db.close();

    originalFile.delete();

    newFile.renameTo(originalFile);

}
like image 70
Mr.Sparkle Avatar answered Sep 20 '22 18:09

Mr.Sparkle