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());
}
}
}
}
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.
SQLCipher is an open source library that provides transparent, secure 256-bit AES encryption of SQLite database files.
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.
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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With