我有一个Android应用程序,它使用SQLCipher进行数据库加密。该应用程序已经上线并拥有许多活跃用户。我正在寻找一种解决方案,可以从应用程序的现有数据库中删除SQLCipher加密,而不会丢失用户的数据。
我尝试与this帖子中提到的相反,但无法打开我的加密数据库文件。
public static void decrypt(Context ctxt, String dbName, String passphrase)
throws IOException {
try {
File originalFile = ctxt.getDatabasePath(dbName);
int version = 0;
if (originalFile.exists()) {
File newFile = File.createTempFile("sqlite", "tmp", ctxt.getCacheDir());
net.sqlcipher.database.SQLiteDatabase dbCipher = net.sqlcipher.database.SQLiteDatabase.openDatabase(
originalFile.getAbsolutePath(), passphrase, null,
net.sqlcipher.database.SQLiteDatabase.OPEN_READWRITE);
if (dbCipher.isOpen()) {
dbCipher.rawExecSQL(String.format(
"ATTACH DATABASE '%s' AS plaintext KEY '%s';",
newFile.getAbsolutePath(), passphrase));
dbCipher.rawExecSQL("SELECT sqlcipher_export('plaintext')");
dbCipher.rawExecSQL("DETACH DATABASE plaintext;");
version = dbCipher.getVersion();
dbCipher.close();
}
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(newFile, null);
db.setVersion(version);
db.close();
originalFile.delete();
newFile.renameTo(originalFile);
}
} catch (Exception e) {
e.printStackTrace();
}
}
而且,这是我得到的错误日志......
06-04 11:33:54.929: E/SQLiteLog(12309): (26) file is encrypted or is not a database
06-04 11:33:54.929: E/DefaultDatabaseErrorHandler(12309): Corruption reported by sqlite on database: /data/data/ril.jio.protrak/cache/sqlite1817652413tmp
答案 0 :(得分:1)
以下是将SQLCipher加密数据库文件导出为纯文本数据库文件的示例。
恢复
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
而不是
import net.sqlcipher.Cursor;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteOpenHelper;
现在使用此类将加密的数据库文件导出为普通纯文本
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
public class ExportSQLCipherEncryptedDBIntoPlainText extends
AsyncTask<Void, Integer, Boolean> {
private Context context;
private String dbName, password, filePath;
public ExportSQLCipherEncryptedDBIntoPlainText(Context context,
String dbName, String password, String filePath) {
this.context = context;
this.dbName = dbName;
this.password = password;
this.filePath = filePath;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(Void... arg0) {
try {
File originalFile = context.getDatabasePath(dbName);
int version = 0;
if (originalFile.exists()) {
// create new file
File newFile = new File(filePath + "/plaintext.db");
File newAdditionalFile = new File(filePath + "/plaintext.db-journal");
if (!newFile.exists()) {
net.sqlcipher.database.SQLiteDatabase.loadLibs(context);
net.sqlcipher.database.SQLiteDatabase dbCipher = net.sqlcipher.database.SQLiteDatabase
.openDatabase(
originalFile.getAbsolutePath(),
password,
null,
net.sqlcipher.database.SQLiteDatabase.OPEN_READWRITE);
if (dbCipher.isOpen()) {
dbCipher.rawExecSQL("ATTACH DATABASE '" + filePath
+ "/plaintext.db' AS plaintext KEY ''");
dbCipher.rawExecSQL("SELECT sqlcipher_export('plaintext')");
dbCipher.rawExecSQL("DETACH DATABASE plaintext");
version = dbCipher.getVersion();
dbCipher.close();
}
if (newFile.exists()) {
android.database.sqlite.SQLiteDatabase db = android.database.sqlite.SQLiteDatabase
.openOrCreateDatabase(newFile, null);
db.setVersion(version);
db.close();
originalFile.delete();
// newFile.renameTo(originalFile);
}
Log.i("AndroidLib",
"Copying database from external directory to application Started");
byte[] buffer = new byte[1024];
OutputStream myOutput = null;
int length;
// Open your local db as the input stream
InputStream myInput = null;
myInput = new FileInputStream(newFile);
// transfer bytes from the inputfile to the
// outputfile
myOutput = new FileOutputStream(originalFile);
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
if (originalFile.exists()) {
android.database.sqlite.SQLiteDatabase db = android.database.sqlite.SQLiteDatabase
.openOrCreateDatabase(originalFile, null);
newFile.delete();
if (newAdditionalFile.exists()) {
newAdditionalFile.delete();
}
Log.i("AndroidLib",
"Copying database from external directory to application Completed successfully");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}