- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 Android 上使用 SQLCipher 来获取加密数据库。数据库获得一个基于某些硬编码值的默认密码。用户还可以在应用程序上设置密码。当用户这样做时,我还想更改 SQLCipher 使用的数据库密码。我已经在 StackerOverflow 上找到一些帖子说我应该使用 rekey。
目前我正在按照建议的帖子使用此代码
final DatabaseHelper helper = new DatabaseHelper(this);
final SQLiteDatabase db = helper.getWritableDatabase(oldPassword);
final String PRAGMA_KEY = String.format("PRAGMA key = \"%s\";", oldPassword);
final String PRAGMA_REKEY = String.format("PRAGMA rekey = \"%s\";", newPassword);
db.rawExecSQL("BEGIN IMMEDIATE TRANSACTION;");
db.rawExecSQL(PRAGMA_KEY);
db.rawExecSQL(PRAGMA_REKEY);
db.close();
但是当我尝试在密码应该更改后插入数据库时,我得到了这个错误。
sqlite returned: error code = 26, msg = statement aborts at 1: [BEGIN EXCLUSIVE;] file is encrypted or is not a database
Failure 26 (file is encrypted or is not a database) on 0xb90048c0 when executing 'BEGIN EXCLUSIVE;'
FATAL EXCEPTION: IntentService[DBService]
Process: com.example, PID: 26502
net.sqlcipher.database.SQLiteException: file is encrypted or is not a database: BEGIN EXCLUSIVE;
at net.sqlcipher.database.SQLiteDatabase.native_execSQL(Native Method)
at net.sqlcipher.database.SQLiteDatabase.execSQL(SQLiteDatabase.java:1831)
at net.sqlcipher.database.SQLiteDatabase.beginTransactionWithListener(SQLiteDatabase.java:584)
at net.sqlcipher.database.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:538)
at com.example.db.Provider.bulkInsert(OurProvider.java:196)
at android.content.ContentProvider$Transport.bulkInsert(ContentProvider.java:250)
at android.content.ContentResolver.bulkInsert(ContentResolver.java:1268)
at nl.qbusict.cupboard.ProviderCompartment.put(ProviderCompartment.java:158)
at com.example.db.DBUtils.saveObjects(DBUtils.java:32)
at com.example.services.DBService.getDataFromAPI(DBService.java:119)
at com.example.services.DBService.onHandleIntent(DBService.java:48)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
我检查了修改前后的原密码和新密码,都是一样的。我还尝试添加 db.rawExecSQL("END;");
和 db.rawExecSQL("COMMIT;");
但这没有帮助。当我更改密码时,我还看到日志消息来自 error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
。不知道跟这个有没有关系?
public class OurProvider extends ContentProvider {
@Override
public int bulkInsert(Uri uri, ContentValues[] values) {
synchronized (LOCK) {
SQLiteDatabase db = getDatabase().getWritableDatabase(getPassword());
final String table = getTableString(uri);
db.beginTransaction();
int rowsInserted = 0;
try {
for (ContentValues value : values) {
db.insertWithOnConflict(table, null, value, SQLiteDatabase.CONFLICT_REPLACE);
rowsInserted++;
}
db.setTransactionSuccessful();
} catch (Exception e) {
Crashlytics.logException(e);
Log.d(TAG, Log.getStackTraceString(e));
rowsInserted = -1;
} finally {
db.endTransaction();
if (rowsInserted > 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
}
return rowsInserted;
}
}
private String getPassword() {
final String password = Base64.encodeToString(OurApplication.getEncryptionKey().getEncoded(), Base64.DEFAULT);
Log.e("SQLCipher_OurProvider", "SQLCipher password: " + password);
return password;
}
private void initDb() {
SQLiteDatabase.loadLibs(getContext());
mDatabaseHelper = new DatabaseHelper(getContext());
}
public DatabaseHelper getDatabase() {
if (mDatabaseHelper == null) {
initDb();
}
return mDatabaseHelper;
}
}
public class DBService extends IntentService {
private void updatePasscode(Intent intent) {
final SecretKey oldKey = OurApplication.getEncryptionKey();
final String encryptedString = SecurePrefs.getEncryptedString(PrefKeys.ENC_CONFIRM);
if (!TextUtils.isEmpty(encryptedString)) {
String decryptedString = Crypto.decrypt(oldKey, encryptedString);
// check if the oldkey can decrypt the confirmation string.
if (BaseActivity.CONFIRM_STRING.equals(decryptedString)) {
String pin = intent.getStringExtra(KEY_PASSCODE);
if (pin.equals(PasscodeActivity.REMOVE_PIN)) {
pin = null;
}
final SecretKey newKey = SecurityUtil.generateKey(this, pin);
final String accessToken = getUserAccessToken();
final String refreshToken = SecurePrefs.getString(PrefKeys.USER_REFRESH_TOKEN);
final String email = SecurePrefs.getString(PrefKeys.USER_ID);
final String confirmEncrypted = SecurePrefs.getString(PrefKeys.ENC_CONFIRM);
// set the newly generated string in the application.
OurApplication.setEncryptionKey(newKey);
// clear the old encrypted prefs. save the values with the new encryption key.
SecurePrefs.clear();
SecurePrefs.putString(PrefKeys.USER_ACCESS_TOKEN, accessToken);
SecurePrefs.putString(PrefKeys.USER_REFRESH_TOKEN, refreshToken);
SecurePrefs.putString(PrefKeys.USER_ID, email);
SecurePrefs.putString(PrefKeys.ENC_CONFIRM, confirmEncrypted);
// update de encryption key in the database.
final String oldPassword = Base64
.encodeToString(oldKey.getEncoded(), Base64.DEFAULT);
final String newPassword = Base64
.encodeToString(newKey.getEncoded(), Base64.DEFAULT);
final String PRAGMA_KEY = String.format("PRAGMA key = \"%s\";", oldPassword);
final String PRAGMA_REKEY = String.format("PRAGMA rekey = \"%s\";", newPassword);
final DatabaseHelper helper = new DatabaseHelper(this);
final SQLiteDatabase db = helper.getWritableDatabase(oldPassword);
db.rawExecSQL("BEGIN IMMEDIATE TRANSACTION;");
db.rawExecSQL(PRAGMA_KEY);
db.rawExecSQL(PRAGMA_REKEY);
db.close();
sendBroadcast(IntentUtil.createBroadcastPasscodeUpdated());
}
}
}
}
最佳答案
您不应该开始交易(这是处理 internally 并且略有不同),您也不需要执行代码的 PRAGMA key='...';
部分。您可以通过调用 getWritableDatabase(...);
打开数据库,然后执行您的 PRAGMA rekey='...';
命令。
关于android - SQLCipher 使用 rekey 更改数据库密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27400049/
我在 Android 上使用 SQLCipher 来获取加密数据库。数据库获得一个基于某些硬编码值的默认密码。用户还可以在应用程序上设置密码。当用户这样做时,我还想更改 SQLCipher 使用的数据
我想 ReKey 一个 GlobalKTable(可能是在初始化它的时候,因为我相信它们一旦创建就只读)。 这可能吗? 我在 Spring/Java Kafka Streams 应用程序中处理了两个主
我有一个生产数据库,其中偶尔需要“合并”单个表中的冗余行。 假设此表中的两行具有相同的值(ID 除外)。 Table "PrimaryStuff" ID | SomeValue 1 | "I hav
我是一名优秀的程序员,十分优秀!