I've just learned how to use SQLCipher here and I want to be able to save it to an SQLite file and I stumbled upon this approach where the file is saved via FileOutputStream. However, the FileOutputStream approach only worked when the database file isn't encrypted. Is there a workaround that you can recommend?
If not, my ultimate objective is actually the following:
- Create an encrypted database using Room
- Create an encrypted backup for this database
- Give the user the ability send this file either via Google Drive, email, or some other means so that I can also view the database's contents if they need me to look over it
- Make this process as seamless and as invisible, but also as elegant as possible
Thanks a lot!
Here's what I tried to do and it is pretty much a copy-paste of those two links I referred above:
For the database:
public abstract class MyDatabase extends RoomDatabase {
public static MyDatabase myDatabase;
// based on https://github.com/sqlcipher/android-database-sqlcipher
public static synchronized MyDatabase getInstance(Context context) {
if (MyDatabase == null) {
final byte[] passphrase = SQLiteDatabase.getBytes("userEnteredPassphrase".toCharArray());
final SupportFactory factory = new SupportFactory(passphrase);
MyDatabase = Room.databaseBuilder(context.getApplicationContext(),
MyDatabase.class,
"my_database")
.addCallback(roomCallback)
.openHelperFactory(factory) // WHEN I REMOVE THIS LINE, THE ENTIRE DATABASE GETS SAVED AS A FILE INCLUDING THE TABLES, BUT WHEN THIS LINE IS ACTIVE, THE FILE IS REDUCED TO ABOUT 4kb WITH NOTHING IN IT
.build();
}
return MyDatabase;
}
}
How I tried to save the database using FileOutputStream:
public void saveDatabaseToFileOutputStream() {
File dbfile = this.getDatabasePath("my_database");
File sdir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),"DBsaves");
String sfpath = sdir.getPath() + File.separator + "DBsave" + String.valueOf(System.currentTimeMillis());
if (!sdir.exists()) {
sdir.mkdirs();
}
File savefile = new File(sfpath);
try {
savefile.createNewFile();
int buffersize = 8 * 1024;
byte[] buffer = new byte[buffersize];
int bytes_read = buffersize;
OutputStream savedb = new FileOutputStream(sfpath);
InputStream indb = new FileInputStream(dbfile);
while ((bytes_read = indb.read(buffer,0,buffersize)) > 0) {
savedb.write(buffer,0,bytes_read);
}
savedb.flush();
indb.close();
savedb.close();
} catch (Exception e) {
e.printStackTrace();
}
}
The difference in saved file when the database is ciphered and not ciphered