Обновление данных поставщика простого контента (с поддержкой SQLite) до зашифрованного с помощью SQLCipher -Android
Я пытаюсь зашифровать данные, хранящиеся в моем поставщике контента, с помощью обновления приложения. Я следовал по ссылке ниже для этого,
Как реализовать SQLCipher при использовании SQLiteOpenHelper
Хотя это прекрасно работает, если новая установка выполнена, если я иду на обновление, приложение вылетает с ошибкой ниже
net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3009)
at android.app.ActivityThread.access$1800(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1526)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5951)
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:1388)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)
Caused by: net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
Я даже пытался удалить существующие таблицы и создать новую таблицу, просто чтобы посмотреть, решит ли это проблему, но это тоже не помогло. Пожалуйста, предложите, как это исправить, класс My Helper, как показано ниже,
public class MyDBHelper extends SQLiteOpenHelper {
public MyDBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
SQLiteDatabase.loadLibs(context);
}
public static final String DATABASE_NAME = "mydb.db";
private static final int DATABASE_VERSION = 2; // before attempting encryption it was 1
@Override
public void onCreate(SQLiteDatabase db) {
createTables(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + "TEST_TABLE");
createTables(db);
}
private void createTables(SQLiteDatabase db){
db.execSQL(MyDBQueries.CREATE_TEST_TABLE);
}
}
Мой обновленный провайдер просто использует ключ сейчас, чтобы открыть базу данных, как показано ниже,
SQLiteDatabase db = databaseHelper.getWritableDatabase("encryptionKey");
Как я уже упоминал, свежие установки работают хорошо, но при обновлении происходит сбой приложения. Подскажите пожалуйста как это исправить.
1 ответ
База данных изначально не зашифрована, я хочу, чтобы она была зашифрована при обновлении приложения
Это не произойдет автоматически, и это не может произойти как часть SQLiteOpenHelper
И его onUpgrade()
путь (как по времени onUpgrade()
называется, SQLiteOpenHelper
будет уже пытаться открыть незашифрованную базу данных, что приведет к ошибке, за исключением того, что вы показали).
Вам нужно будет отдельно зашифровать эту базу данных. Этот код - то, что я использовал:
public static void encrypt(Context ctxt, String dbName,
String passphrase) throws IOException {
File originalFile=ctxt.getDatabasePath(dbName);
if (originalFile.exists()) {
File newFile=
File.createTempFile("sqlcipherutils", "tmp",
ctxt.getCacheDir());
SQLiteDatabase db=
SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(),
"", null,
SQLiteDatabase.OPEN_READWRITE);
db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
newFile.getAbsolutePath(), passphrase));
db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
db.rawExecSQL("DETACH DATABASE encrypted;");
int version=db.getVersion();
db.close();
db=
SQLiteDatabase.openDatabase(newFile.getAbsolutePath(),
passphrase, null,
SQLiteDatabase.OPEN_READWRITE);
db.setVersion(version);
db.close();
originalFile.delete();
newFile.renameTo(originalFile);
}
}
После encrypt()
возвращается, тогда вы можете пойти дальше и попытаться открыть базу данных.