Comments (10)
首先你需要明白几点:
- ATTACH 操作本身就会打开 DB,因此 ATTACH 之前不需要打开,如果 db2 是你之前已经用 open 等接口打开并得到的 SQLiteDatabase 对象,那这没有必要,直接传路径就行了。
- sqlcipher_export 接受的参数是打开或 ATTACH 的名称,而不是路径,ATTACH上去的,名称就是你自己起的名称(比如你的 unencrypted,或者例子里的 old),如果是主DB(open时传入路径直接打开的),那它有一个固定的名称 'main'。
- sqlcipher_export 的作用是 将第二个参数的 DB 的内容,完整复制到第一个参数的 DB 里面,是导出还是导入,是加密还是解密,完全取决于这两个 DB 的配置。
- WCDB 的 execSQL 函数只能执行 INSERT、UPDATE、DELETE 等命令,不能执行 SELECT,因为 SELECT 一般是返回结果的。你可以换一个调用方式解决这个问题,最简单是例子里的
DatabaseUtils.stringForQuery(db, "SELECT sqlcipher_export('main', 'old');", null);
它的意思是查询并返回一个字符串,实际上 sqlcipher_export 并不会返回字符串,但不需要理会,忽略返回值即可,里面的语句已经执行了。
所以我觉得你可以这么操作:
// 先open了加密DB,得到 "db" 对象
// 将非加密DB挂载到 "db"
String sql = String.format("ATTACH DATABASE %s AS old KEY '';",
DatabaseUtils.sqlEscapeString(oldDbFile.getPath()));
db.execSQL(sql);
// 将数据从 "main"(加密db) 迁移到 "old"(非加密db)
db.beginTransaction();
DatabaseUtils.stringForQuery(db, "SELECT sqlcipher_export('old', 'main');", null);
db.setTransactionSuccessful();
db.endTransaction();
// 将old脱离
db.execSQL("DETACH DATABASE old;");
有没有觉得很像例子?其实就是将sqlcipher_export两个参数调换一下。
from wcdb.
这个跟原来一样的,执行这些SQL语句就能解密
from wcdb.
你好,我尝试解密数据库还是失败,烦请帮忙看一下原因,多谢!
打开wcdb加密数据库代码如下:
db = com.tencent.wcdb.database.SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(),
(isDecode ? password.getBytes() : null/* 无密 */), cipher, null,
SQLiteDatabase.OPEN_READWRITE, new DatabaseErrorHandler() {
@OverRide
public void onCorruption(com.tencent.wcdb.database.SQLiteDatabase dbObj) {
LogUtil.e(TAG, "CipherDB::startDataBaseMigration2::onCorruption1");
}
});
创建临时文件暂存代码:
newFile = File.createTempFile(ENCRYPTED_DATABASE_PREFIX, TEMP_ENCRYPTED_DATABASE_PREFIX,
context.getCacheDir());
数据迁移代码:
try {
// db.rawExecSQL("PRAGMA cipher_default_kdf_iter = 4000;");
db.execSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
newFile.getAbsolutePath(), (isDecode ? ""/* 无密 */ : password)));
db.execSQL("SELECT sqlcipher_export('encrypted')");
db.execSQL("DETACH DATABASE encrypted;");
db.close();
} catch (Exception e) {
LogUtil.e(TAG, "CipherDB::startDataBaseMigration OMG ...DataMigration has exception. "
+ e.getMessage());
throw new StopRequestException(DATA_TRANSFER_DATA_MIGRATION_ERROR, e);
}
异常日志,如下:
06-19 16:17:22.214 7185-7185/com.wlx.debug W/wlx: main:SqliteCipherLogic [LOGIN_READLY]: CipherDB::onItemClick: common_new
06-19 16:17:22.215 7185-7185/com.wlx.debug D/wlx: main:SqliteCipherLogic [LOGIN_READLY]: CipherDB::startDataBaseMigration starting... databaseName: common_new
06-19 16:17:22.215 7185-7185/com.wlx.debug D/wlx: main:SqliteCipherLogic [LOGIN_READLY]: CipherDB::startDataBaseMigration originalFile path: /data/user/0/com.wlx.debug/databases/common_new
06-19 16:17:22.215 7185-7185/com.wlx.debug I/WCDB.SQLiteConnectionPool: Max connection pool size is 1.
06-19 16:17:22.216 7185-7185/com.wlx.debug I/WCDB: Initialize SQLite connection module 'MMFTS'...
06-19 16:17:22.216 7185-7185/com.wlx.debug I/WCDB.SQLiteConnection: Opened connection 0x9b8f6808 with label '/data/user/0/com.wlx.debug/databases/common_new'
06-19 16:17:22.216 7185-7185/com.wlx.debug I/WCDB.SQLiteConnection: sqlite3_key verification passed.
06-19 16:17:22.254 7185-7185/com.wlx.debug W/WCDB.SQLite: [SQLite ErrCode: 5] statement aborts at 1: [PRAGMA journal_mode=PERSIST] database is locked
06-19 16:17:22.255 7185-7185/com.wlx.debug W/WCDB.SQLiteConnectionPool: Connections: 0 active, 0 idle, 0 available.
06-19 16:17:22.257 7185-7185/com.wlx.debug I/WCDB.SQLiteConnection: executeForString took 1ms - failed, sql="PRAGMA journal_mode=PERSIST", exception="database is locked (code 5, errno 0): "
06-19 16:17:22.257 7185-7185/com.wlx.debug W/WCDB.SQLiteConnection: Could not change the database journal mode of '/data/user/0/com.wlx.debug/databases/common_new' from 'wal' to 'PERSIST' because the database is locked. This usually means that there are other open connections to the database which prevents the database from enabling or disabling write-ahead logging mode. Proceeding without changing the journal mode.
06-19 16:17:22.258 7185-7185/com.wlx.debug D/wlx: main:SqliteCipherLogic [LOGIN_READLY]: CipherDB::startDataBaseMigration originalFile version: 65
06-19 16:17:22.266 7185-7185/com.wlx.debug D/wlx: main:SqliteCipherLogic [LOGIN_READLY]: CipherDB::startDataBaseMigration newFile path: /data/user/0/com.wlx.debug/cache/tmp_common
06-19 16:17:23.852 7185-7185/com.wlx.debug I/WCDB.SQLiteConnection: executeForChangedRowCount took 1584ms - failed, sql="SELECT sqlcipher_export('encrypted')", exception="unknown error (code 0, errno -1): Queries can be performed using SQLiteDatabase query or rawQuery methods only.", changedRows=0
06-19 16:17:23.852 7185-7185/com.wlx.debug E/wlx: main:SqliteCipherLogic [LOGIN_READLY]: CipherDB::startDataBaseMigration OMG ...DataMigration has exception. unknown error (code 0, errno -1): Queries can be performed using SQLiteDatabase query or rawQuery methods only.
06-19 16:17:23.852 7185-7185/com.wlx.debug E/wlx: main:SqliteCipherLogic [LOGIN_READLY]: CipherDB::startDataBaseMigration --- > Aborting request for database migration common_new: com.tencent.wcdb.database.SQLiteException: unknown error (code 0, errno -1): Queries can be performed using SQLiteDatabase query or rawQuery methods only.
06-19 16:17:23.853 7185-7185/com.wlx.debug D/wlx: main:SqliteCipherLogic [LOGIN_READLY]: CipherDB::startDataBaseMigration finally --- > 103
from wcdb.
@weilixin 你可以参看以下 sample-encryptdb
,EncryptedDBHelper.onCreate()
里演示了如何迁移数据库,这个对加密和非加密都是一样的,你可以正常打开加密 DB,ATTACH 一个空的非加密 DB,然后用
sqlcipher_export
来迁移。
WCDB的 sqlcipher_export
经过扩展支持两个参数,分别是 导出到哪个DB 和 从哪个DB导出,例子里是从非加密到加密,把参数反过来即可解密。
WCDB接口和限制跟 Android Framework 一致,和 SQLCipher Android 在限制上有一点点不同,但原理是一样的(包括 kdf_iter 等参数),SQL语句不用改,可能要稍微改一下调用代码。
from wcdb.
@John-He-928 感谢帮助,还是有些问题。
String sql = String.format("ATTACH DATABASE %s AS encrypted KEY '%s';",
DatabaseUtils.sqlEscapeString(originalFile.getPath()), password);
db.execSQL(sql);
PS:失败原因应该是密码不对,但实际密码没问题,肯定正确,传入字符串还是byte数组呢?
异常日志,如下: (密码肯定正确,58位数字大小写英文混合)
06-20 10:00:38.310 28755-28755/com.wlx.debug W/WCDB.SQLite: [SQLite ErrCode: 26] statement aborts at 4: [ATTACH DATABASE '/data/user/0/com.wlx.debug/databases/common_new' AS encrypted KEY '733491015b519f491fc2601654c44de8sIO5reWAbAsR1Pbq13ws567612';] file is encrypted or is not a
06-20 10:00:38.311 28755-28755/com.wlx.debug I/WCDB.SQLiteConnection: executeForChangedRowCount took 253ms - failed, sql="ATTACH DATABASE '/data/user/0/com.wlx.debug/databases/common_new' AS encrypted KEY '733491015b519f491fc2601654c44de8sIO5reWAbAsR1Pbq13ws567612';", exception="file is encrypted or is not a database (code 26, errno 0): ", changedRows=0
06-20 10:00:38.316 28755-28755/com.wlx.debug E/wlx: main:SqliteCipherLogic [LOGIN_READLY]: CipherDB::startDataBaseMigration2::onCorruption
from wcdb.
你可以打开加密的,然后attach没加密的,然后export
from wcdb.
@John-He-928 感谢支持!
抱歉,按照你提示的做法尝试还是失败了,麻烦再帮看一下。数据库迁移代码如下:(db2是非加密的数据库,db是加密的数据库)
// 开始数据迁移
try {
db.execSQL(String.format("ATTACH DATABASE '%s' AS unencrypted KEY '%s';",
db2.getPath(), ""));
db.execSQL(String.format("SELECT sqlcipher_export('unencrypted', '%s')",
db.getPath()));
db.execSQL("DETACH DATABASE unencrypted;");
db.close();
} catch (Exception e) {
LogUtil.e(TAG, "CipherDB::startDataBaseMigration OMG ...DataMigration has exception. "
+ e.getMessage());
throw new StopRequestException(DATA_TRANSFER_DATA_MIGRATION_ERROR, e);
}
失败日志如下:
// db-tmp是非加密数据库, common_new是加密的数据库。希望将common_new数据转移到非加密的库db-tmp
06-21 10:19:18.942 21700-21700/com.wlx.debug I/WCDB.SQLiteConnection: Opened connection 0x939aca08 with label '/data/user/0/com.wlx.debug/cache/db-tmp'
06-21 10:19:18.944 21700-21700/com.wlx.debug D/wlx: main:SqliteCipherLogic [CONNECTION_OK]: CipherDB::startDataBaseMigration newFile path: /data/user/0/com.wlx.debug/cache/db-tmp
06-21 10:19:18.947 21700-21700/com.wlx.debug W/WCDB.SQLite: [SQLite ErrCode: 1] near "/": syntax error
06-21 10:19:18.947 21700-21700/com.wlx.debug W/WCDB.SQLite: [SQLite ErrCode: 1] statement aborts at 1: [SELECT sqlcipher_export('unencrypted', '/data/user/0/com.wlx.debug/databases/common_new')] SQL logic error or missing database
06-21 10:19:18.948 21700-21700/com.wlx.debug I/WCDB.SQLiteConnection: executeForChangedRowCount took 1ms - failed, sql="SELECT sqlcipher_export('unencrypted', '/data/user/0/com.wlx.debug/databases/common_new')", exception="SQL logic error or missing database (code 1, errno 0): ", changedRows=0
06-21 10:19:18.948 21700-21700/com.wlx.debug E/wlx: main:SqliteCipherLogic [CONNECTION_OK]: CipherDB::startDataBaseMigration OMG ...DataMigration has exception. SQL logic error or missing database (code 1, errno 0):
from wcdb.
可以了,感谢John细致耐心讲解。赞!!!
from wcdb.
可以通过 sqlcipher_export
来改密码吗?
// 先open了加密DB,得到 "db" 对象
// 将加密DB (old)挂载到 "db"
String sql = String.format("ATTACH DATABASE %s AS old KEY 'I am new password';",
DatabaseUtils.sqlEscapeString(oldDbFile.getPath()));
db.execSQL(sql);
// 将数据从 "main"(加密db) 迁移到 "old"(加密db)
db.beginTransaction();
DatabaseUtils.stringForQuery(db, "SELECT sqlcipher_export('old', 'main');", null);
db.setTransactionSuccessful();
db.endTransaction();
// 将old脱离
db.execSQL("DETACH DATABASE old;");
from wcdb.
你好,我最近也开始使用WCDB,在集成时出现了个问题,所以向您请教下。
我这边有个本地的数据库文件 local.db,通过 WCDB 加密后得出的 encrypted.db,这时用 sample-encryptdb demo 中的 EncryptedDBHelper 来处理没问题。然后把 encrypted.db 从设备导出来,放到项目里面做一个加密的数据库文件,然后进行解密操作并读取由 encrypted.db 解密迁移到的明文数据库 plaintext.db,这时用获取到的 plaintext.db 的 SQLiteDatabase 对象来进行数据库操作会报错,错误信息说没有这样的表(no such table),然后看了下文件大小,发现原来的 local.db 和 encrypted.db 都是3.2M,而这个 plaintext.db 为 4kb,所以想请教下这要如何处理,代码如下:
this.dealTempDB()
USER_DATA_BASE = SQLiteDatabase.openOrCreateDatabase(mContext.getDatabasePath(“plaintext.db”), null, null, null)
private fun dealTempDB() {
// 先 open了加密DB,得到 "db" 对象
val encryptedDB = SQLiteDatabase.openOrCreateDatabase(mContext.getDatabasePath("encrypted.db"),
"password".toByteArray(), null, null)
// 将非加密DB挂载到 "db"
val sql = String.format("ATTACH DATABASE %s AS unencrypted KEY '';",
DatabaseUtils.sqlEscapeString(File(“data/data/com.xxx.xxx” + “plaintext.db”).path))
encryptedDB.execSQL(sql)
// 将数据从 "main"(加密db) 迁移到 "unencrypted"(非加密db)
encryptedDB.beginTransaction()
DatabaseUtils.stringForQuery(encryptedDB, "SELECT sqlcipher_export('unencrypted', 'main');", null)
encryptedDB.setTransactionSuccessful()
encryptedDB.endTransaction()
// 将 unencrypted 脱离
encryptedDB.execSQL("DETACH DATABASE unencrypted;")
encryptedDB.close()
}
from wcdb.
Related Issues (20)
- Auto-increment inserts do not support conflict action! HOT 3
- let crash = Xcode15 + iOS13 HOT 24
- XCode15 ,carthage 报错 HOT 3
- xcode15 WCDB_SYNTHESIZE 崩溃
- YYKit中的YYKVStorage,崩溃在sqlite3_exec调用上,请问如何解决? HOT 3
- Potential memleak in android/jni/com_tencent_wcdb_database_SQLiteConnection.cpp HOT 1
- mac上编译Android的so库报找不到z-lib
- 编译Android的so库后要怎么在Android项目中使用,没有配套的java层的api HOT 3
- CMakeLists.txt 是否可以添加下Apple平台支持
- 错误处理 HOT 6
- Upgrading to WCDB and Issue with Signal Retry Feature removed HOT 1
- 虚拟表中的数据如何更新 HOT 2
- 我这边测试WCDB比FMDB慢了很多,请帮我看下是不是什么优化项没有设置 HOT 3
- 如何查看WCDB依赖的WCDBOptimizedSQLCipher版本对应的tag / 分支 / commit id HOT 2
- 运行在 iOS 17 真机上,Core.cpp 库 Crash HOT 4
- 为什么要设置SQLITE_MAX_VARIABLE_NUMBER为99 HOT 3
- 安卓的全文检索什么时候更新? HOT 1
- 'WCDB.swift', '~> 2.0.3' 真机运行12.5.5创建database时崩溃 HOT 2
- iOS 扩展应用,在APP Group共享文件夹,无法创建数据库 HOT 8
- WCDBSwift2.0.4无法创建虚拟表 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from wcdb.