私は何年間も生産されているアプリを持っています。標準のSqlite DBが付属しています。アプリの最新バージョンにはSqlCipher 3.5.6ライブラリが統合されています。ファイルが暗号化されているかデータベースではありません:コンパイル中に:select count(*)from sqlite_master;
新しいDBにいくつかの余分なテーブルがあるので、それらをonUpgradeメソッドで作成しました。
私はアプリケーションオブジェクトで次のメソッドを呼び出しました。
SQLiteDatabase.loadLibs(this);
古いAPKでDB_VERSIONは56で、ONUPGRADEを呼び出さなければなりませんので、私は、新しいAPKで57に設定しています。
私はonUpgradeの中からencryptメソッドを呼び出します。
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.e(TAG, "++++++++++++++++++++++++++SQLiteOpenHelper onUpgrade old version = " + oldVersion + " new version = " + newVersion);
if(oldVersion == 56){
String sqlToCreateWeeklySummary = String
.format("create table %s (%s INTEGER primary key, %s TEXT, %s TEXT, %s TEXT, %s TEXT, %s TEXT, %s TEXT, %s TEXT)",
TABLEWEEKLYSUMMARY, C_ID_WEEKLY_SUMMARY, C_WEEKLY_SUMMARY_STARTDATE,
C_WEEKLY_SUMMARY_PLANNEDCALLS, C_WEEKLY_SUMMARY_NCR, C_WEEKLY_SUMMARY_QA, C_WEEKLY_SUMMARY_PLANNEDHOURS,
C_WEEKLY_SUMMARY_ACTUALCALLS, C_WEEKLY_SUMMARY_ACTUALHOURS);
db.execSQL(sqlToCreateWeeklySummary);
Log.e(TAG, "onUpgrade " + sqlToCreateWeeklySummary);
more table upgrades................
NfcScannerApplication.setJustUpgradedDBTrue();
NfcScannerApplication.setDownloadingCompOptsAfterUpgradeTrue();
try {
encrypt(context, "carefreemobiledb.db", "");
}catch(Exception e){}
}
}//end of onUpgrade
。
public void encrypt(Context ctxt, String dbName, String passphrase) throws IOException {
Log.e(TAG, "inside encrypt");
File originalFile=ctxt.getDatabasePath(dbName);
if (originalFile.exists()) {
Log.e(TAG, "originalFile exists1");
File newFile= File.createTempFile("sqlcipherutils", "tmp", ctxt.getCacheDir());
Log.e(TAG, "created newFile2");
SQLiteDatabase db= SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(),
"", null, SQLiteDatabase.OPEN_READWRITE);
Log.e(TAG, "opened DB using originalFile3");
db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
newFile.getAbsolutePath(), passphrase));
Log.e(TAG, "Attached DB4");
db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
Log.e(TAG, "export5");
db.rawExecSQL("DETACH DATABASE encrypted;");
Log.e(TAG, "detached DB6");
int version=db.getVersion();
db.close();
Log.e(TAG, "closed DB7");
db= SQLiteDatabase.openDatabase(newFile.getAbsolutePath(),
passphrase, null,
SQLiteDatabase.OPEN_READWRITE);
Log.e(TAG, "opened DB with newFile8");
db.setVersion(version);
Log.e(TAG, "set version for db using newFile9");
db.close();
Log.e(TAG, "closed db10");
originalFile.delete();
Log.e(TAG, "deleted orignial file11");
newFile.renameTo(originalFile);
Log.e(TAG, "renamed newFile to orginalFile12");
}
}
古いアプリがインストールされているデバイスに新しいapkを読み込むと、次のエラーが表示されます。
file is encrypted or is not a database: , while compiling: select count(*) from sqlite_master;
net.sqlcipher.database.SQLiteException: file is encrypted or is not a database: , while compiling: select count(*) from sqlite_master;
at net.sqlcipher.database.SQLiteCompiledSql.native_compile(Native Method)
at net.sqlcipher.database.SQLiteCompiledSql.compile(Unknown Source)
at net.sqlcipher.database.SQLiteCompiledSql.<init>(Unknown Source)
at net.sqlcipher.database.SQLiteProgram.<init>(Unknown Source)
at net.sqlcipher.database.SQLiteQuery.<init>(Unknown Source)
at net.sqlcipher.database.SQLiteDirectCursorDriver.query(Unknown Source)
at net.sqlcipher.database.SQLiteDatabase.rawQueryWithFactory(Unknown Source)
at net.sqlcipher.database.SQLiteDatabase.rawQuery(Unknown Source)
at net.sqlcipher.database.SQLiteDatabase.keyDatabase(Unknown Source)
at net.sqlcipher.database.SQLiteDatabase.openDatabaseInternal(Unknown Source)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(Unknown Source)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(Unknown Source)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(Unknown Source)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(Unknown Source)
at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(Unknown Source)
at com.carefreegroup.rr3.g.c(Unknown Source)
at com.carefreegroup.rr3.EntryActivity.onCreate(Unknown Source)
at android.app.Activity.performCreate(Activity.java:6912)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2900)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3008)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1650)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6688)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
04-26 10:40:53.332 9417-9417/? E/SQLiteOpenHelper: Couldn't open carefreemobiledb.db for writing (will try read-only):
は私がしようとしているもの:SO上
他の記事は、暗号化方式のパスワードがSqlCipherは暗号化されていないDBを開くことができるように、空の文字列にする必要があると言います。
encryptメソッドでパスワードを「」に設定しましたが、ログにDBを開くことができませんでした。
誰でもDBが開かれていない理由を教えていただけますか? onUpgradeメソッドまでは到達していません。
NB。それは私がアプリのデータをクリアすると、それはうまく動作することに注意する価値があるかもしれません。
[更新1]
私は、暗号化メソッドをApplicationクラスに移動しました。 ApplicationクラスのonCreateでは、
を呼び出します。
パスフレーズの暗号化メソッドに空のStringパラメータがありますが、以下の実際の暗号化メソッドでコメントアウトしているので、何もしません。
public static void encrypt(Context ctxt, String dbName, String passphrase) throws IOException {
File originalFile=ctxt.getDatabasePath(dbName);
if (originalFile.exists()) {
Log.e(TAG, "originalFile exists1");
File newFile= File.createTempFile("sqlcipherutils", "tmp", ctxt.getCacheDir());
Log.e(TAG, "created newFile2");
SQLiteDatabase db= SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(),
"", null, SQLiteDatabase.OPEN_READWRITE);
Log.e(TAG, "opened DB using originalFile3");
// db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
// newFile.getAbsolutePath(), passphrase));
db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
newFile.getAbsolutePath()));
Log.e(TAG, "Attached DB4");
db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
Log.e(TAG, "export5");
db.rawExecSQL("DETACH DATABASE encrypted;");
Log.e(TAG, "detached DB6");
int version=db.getVersion();
db.close();
Log.e(TAG, "closed DB7");
db= SQLiteDatabase.openDatabase(newFile.getAbsolutePath(),
passphrase, null,
SQLiteDatabase.OPEN_READWRITE);
Log.e(TAG, "opened DB with newFile8");
db.setVersion(version);
Log.e(TAG, "set version for db using newFile9");
db.close();
Log.e(TAG, "closed db10");
originalFile.delete();
Log.e(TAG, "deleted orignial file11");
newFile.renameTo(originalFile);
Log.e(TAG, "renamed newFile to orginalFile12");
}
}
。
04-26 13:56:02.793 15460-15460/? E/NfcScannerApplication: just called SQLiteDatabase.loadLibs(this)
04-26 13:56:02.793 15460-15460/? E/NfcScannerApplication: originalFile exists1
04-26 13:56:02.794 15460-15460/? E/NfcScannerApplication: created newFile2
04-26 13:56:02.798 15460-15460/? E/NfcScannerApplication: opened DB using originalFile3
04-26 13:56:02.806 3247-3247/? E/audit: type=1320 audit(1493211362.789:23690):
04-26 13:56:02.817 3247-3247/? E/audit: type=1320 audit(1493211362.799:23691):
04-26 13:56:02.828 3247-3247/? E/audit: type=1320 audit(1493211362.809:23692):
04-26 13:56:02.886 15460-15469/? E/Database: close() was never explicitly called on database '/data/user/0/com.carefreegroup.rr3/databases/carefreemobiledb.db'
net.sqlcipher.database.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
at net.sqlcipher.database.SQLiteDatabase.<init>(Unknown Source)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(Unknown Source)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(Unknown Source)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(Unknown Source)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(Unknown Source)
at com.carefreegroup.rr3.NfcScannerApplication.a(Unknown Source)
at com.carefreegroup.rr3.NfcScannerApplication.onCreate(Unknown Source)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1032)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5881)
at android.app.ActivityThread.-wrap3(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1718)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6688)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
:
は、私は今、次のエラーを取得します。
それは、次のとクラッシュ限り取得します。
Log.e(TAG, "opened DB using originalFile3");
。
[更新2]
データベースを正しく閉じるかどうかわかりません。 LoginValidateはDBオブジェクトを返すメソッドが公開されている私のDBクラスです。
SQLiteDatabase.loadLibs(this);
Log.e(TAG, "just called SQLiteDatabase.loadLibs(this)");
loginValidate.getDB().close();
try {
encrypt(mContext, "carefreemobiledb.db", "");
}catch(Exception e){}
。
また、私はencryptメソッドのパスフレーズについてはわかりません。あなたはパスフレーズを使わないと言っていますが、それは意味のある空文字列かパスフレーズをまったく通過しません。私は次の例を挙げます。最初はオリジナル、もう1つは私が試したものです。
Log.e(TAG, "opened DB using originalFile3");
db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
newFile.getAbsolutePath(), passphrase));
Log.e(TAG, "opened DB using originalFile3");
db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
newFile.getAbsolutePath(), ""));
Log.e(TAG, "opened DB using originalFile3");
db.rawExecSQL(String.format("ATTACH DATABASE '%s';",
newFile.getAbsolutePath()));
私が正しく読んでいれば、 '... AS暗号化されたKEY ...'呼び出しの置換バージョンは明示的に '、' '' '.getAbsolutePath()'の後ろに置かれなければなりません。 'String.format()'の 's'はランダムな文字列をスタックから引き出します。 – TripeHound
@TripeHoundありがとうございますが、私はまだパスフレーズを使用しないことが何を意味するのか分かりません。私は更新2の下の投稿を編集しました – turtleboy
どちらも私はいません。ちょうどその少しのコードはおそらくうまくいかなかったでしょう。 – TripeHound