What I'm trying to do
In the app I'm creating we're saving secret user data that needs to be encrypted. For that we'd like to use SQLCipher. We've implemented as in the documentation.
Now I'm facing following problem. If I create the database for the first time I can read and write the db. If I restart the app I'm unable to read the database again and get tons of errors. What am I doing wrong?
Here's the Code of our SQLiteOpenHeler:
public Database (Context ctx){
super(ctx, DATABASE_NAME, null, DATABASE_VERSION);
try{
mKeySaver = new KeySaver(ctx);
File databaseFile = ctx.getDatabasePath(Database.DATABASE_NAME);
if(databaseFile.exists()){
SQLiteDatabaseHook hook = new SQLiteDatabaseHook(){
public void preKey(SQLiteDatabase database){
database.rawExecSQL("PRAGMA kdf_iter = 5000");
}
public void postKey(SQLiteDatabase database){}
};
mDb = SQLiteDatabase.openOrCreateDatabase(databaseFile, mKeySaver.getKey(), null, hook);
} else {
databaseFile.mkdir();
mDb = SQLiteDatabase.openOrCreateDatabase(databaseFile, mKeySaver.getKey(), null);
mDb.setLocale(Locale.GERMAN);
}
} catch (Exception e){
Log.d("Database", "Exception " + e);
}
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
try{
sqLiteDatabase.execSQL(CREATE_TABLE_ACCOUNT);
sqLiteDatabase.execSQL(CREATE_TABLE_ASSIGNMENT_DETAILS);
sqLiteDatabase.execSQL(CREATE_TABLE_ASSIGNMENT_OVERVIEW);
sqLiteDatabase.execSQL(CREATE_TABLE_ASSIGNMENT_UPLOAD);
sqLiteDatabase.execSQL(CREATE_TABLE_ASSIGNMENT_USER);
sqLiteDatabase.execSQL(CREATE_TABLE_ACCOUNT);
}catch (Exception e){
Log.e("Database", "Exception " + e);
}
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
if (oldVersion >= newVersion) {
return;
}
// Falls ein DB-Update stattfinden sollte Code hier
}
And that's how we instantiate it:
SQLiteDatabase.loadLibs(mContext.getApplicationContext());
mKeySaver = new KeySaver(mContext);
mDb = new Database(mContext.getApplicationContext());
db_password = mKeySaver.getKey();
mDatabase = mDb.getWritableDatabase(db_password);
And the Logcatdump:
04-23 09:00:44.723 2405-2405/ivo E/Database﹕ CREATE TABLE android_metadata failed
04-23 09:00:44.726 2405-2405/ivo E/Database﹕ Failed to setLocale() when constructing, closing the database
net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
at net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2092)
at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1958)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:875)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:907)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:197)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:184)
at ivo.database.adapter.AccountAdapter.checkAccountPassword(AccountAdapter.java:79)
at ivo.activity.LoginActivity.attemptLogin(LoginActivity.java:168)
at ivo.activity.LoginActivity$2.onClick(LoginActivity.java:88)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19748)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
04-23 09:00:44.730 2405-2405/swisscom.ivocore E/SQLiteOpenHelper﹕ Couldn't open ivo.db for writing (will try read-only):
net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
at net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2092)
at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1958)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:875)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:907)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:197)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:184)
at ivo.database.adapter.AccountAdapter.checkAccountPassword(AccountAdapter.java:79)
at ivo.activity.LoginActivity.attemptLogin(LoginActivity.java:168)
at ivo.activity.LoginActivity$2.onClick(LoginActivity.java:88)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19748)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)