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