iOS sqlcipher fmdb “文件已加密或不是数据库”
iOS sqlcipher fmdb “File is encrypted or is not a database”
此 tutorial 与以下代码片段配合使用效果很好。
pod 'FMDB/SQLCipher'
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [documentPaths objectAtIndex:0];
self.databasePath = [documentDir stringByAppendingPathComponent:@"gameDefault.sqlite"];
[self createAndCheckDatabase];
...
}
...
-(void) createAndCheckDatabase
{
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
success = [fileManager fileExistsAtPath:self.databasePath];
if(success) return; // If file exists, dont do anything
// if file does not exist, make a copy of the one in the Resources folder
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"gameDefault.sqlite"]; // File path
[fileManager copyItemAtPath:databasePathFromApp toPath:self.databasePath error:nil]; // Make a copy of the file in the Documents folder
// Set the new encrypted database path to be in the Documents Folder
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [documentPaths objectAtIndex:0];
NSString *ecDB = [documentDir stringByAppendingPathComponent:@"encrypted.sqlite"];
// SQL Query. NOTE THAT DATABASE IS THE FULL PATH NOT ONLY THE NAME
const char* sqlQ = [[NSString stringWithFormat:@"ATTACH DATABASE '%@' AS encrypted KEY 'secretKey';",ecDB] UTF8String];
sqlite3 *unencrypted_DB;
if (sqlite3_open([self.databasePath UTF8String], &unencrypted_DB) == SQLITE_OK) {
// Attach empty encrypted database to unencrypted database
sqlite3_exec(unencrypted_DB, sqlQ, NULL, NULL, NULL);
// export database
sqlite3_exec(unencrypted_DB, "SELECT sqlcipher_export('encrypted');", NULL, NULL, NULL);
// Detach encrypted database
sqlite3_exec(unencrypted_DB, "DETACH DATABASE encrypted;", NULL, NULL, NULL);
sqlite3_close(unencrypted_DB);
} else {
sqlite3_close(unencrypted_DB);
NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(unencrypted_DB));
}
self.databasePath = [documentDir stringByAppendingPathComponent:@"encrypted.sqlite"];
}
...
[db setKey:@"secretKey"]
...
// FMDatabase
FMDatabase *db = [FMDatabase databaseWithPath:[self getDatabasePath]];
[db open];
[db setKey:@"secretKey"];
// FMDatabaseQueue
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:[self getDatabasePath]];
[queue inDatabase:^(FMDatabase *db) {
[db setKey:@"secretKey"];
...
}];
...
当我在我的其他项目中使用相同的代码时,它可以很好地加密现有的 sqlite 数据库。 但是当我尝试通过 sql select 查询访问 table 时,我收到错误 "File is encrypted or is not a database". 虽然,没有问题教程应用程序,我可以在那里 update/insert/delete/select 记录。有什么线索吗?
我已经修好了。如前所述,相同代码的行为不同,因此设置可能有问题。在我的应用程序中,我按如下方式添加了 SQLCipher 和 FMDB:
pod 'SQLCipher', '~> 3.1'
pod 'FMDB', '~> 2.5'
而在该教程中,它们被添加为
pod 'FMDB/SQLCipher'
尽管如此,此 pod 命令会根据此处显示的终端输出下载相同版本的 SQLCipher 和 FMDB
Updating local specs repositories
Analyzing dependencies
Downloading dependencies
Installing FMDB (2.5)
Installing SQLCipher (3.1.0)
Generating Pods project
Integrating client project
所以,我像教程中那样更改了 pod 命令,错误已修复。虽然,我不知道这些命令有何不同。
我 fixed.I 认为 FMDB 和 SQLCipher 存在一些 pod 间依赖性。我已经使用以下 link 解决了这个问题。现在我的数据库文件使用带 FMDB 的 SQLCipher 成功加密了....:-D
此 tutorial 与以下代码片段配合使用效果很好。
pod 'FMDB/SQLCipher'
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [documentPaths objectAtIndex:0];
self.databasePath = [documentDir stringByAppendingPathComponent:@"gameDefault.sqlite"];
[self createAndCheckDatabase];
...
}
...
-(void) createAndCheckDatabase
{
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
success = [fileManager fileExistsAtPath:self.databasePath];
if(success) return; // If file exists, dont do anything
// if file does not exist, make a copy of the one in the Resources folder
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"gameDefault.sqlite"]; // File path
[fileManager copyItemAtPath:databasePathFromApp toPath:self.databasePath error:nil]; // Make a copy of the file in the Documents folder
// Set the new encrypted database path to be in the Documents Folder
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [documentPaths objectAtIndex:0];
NSString *ecDB = [documentDir stringByAppendingPathComponent:@"encrypted.sqlite"];
// SQL Query. NOTE THAT DATABASE IS THE FULL PATH NOT ONLY THE NAME
const char* sqlQ = [[NSString stringWithFormat:@"ATTACH DATABASE '%@' AS encrypted KEY 'secretKey';",ecDB] UTF8String];
sqlite3 *unencrypted_DB;
if (sqlite3_open([self.databasePath UTF8String], &unencrypted_DB) == SQLITE_OK) {
// Attach empty encrypted database to unencrypted database
sqlite3_exec(unencrypted_DB, sqlQ, NULL, NULL, NULL);
// export database
sqlite3_exec(unencrypted_DB, "SELECT sqlcipher_export('encrypted');", NULL, NULL, NULL);
// Detach encrypted database
sqlite3_exec(unencrypted_DB, "DETACH DATABASE encrypted;", NULL, NULL, NULL);
sqlite3_close(unencrypted_DB);
} else {
sqlite3_close(unencrypted_DB);
NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(unencrypted_DB));
}
self.databasePath = [documentDir stringByAppendingPathComponent:@"encrypted.sqlite"];
}
...
[db setKey:@"secretKey"]
...
// FMDatabase
FMDatabase *db = [FMDatabase databaseWithPath:[self getDatabasePath]];
[db open];
[db setKey:@"secretKey"];
// FMDatabaseQueue
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:[self getDatabasePath]];
[queue inDatabase:^(FMDatabase *db) {
[db setKey:@"secretKey"];
...
}];
...
当我在我的其他项目中使用相同的代码时,它可以很好地加密现有的 sqlite 数据库。 但是当我尝试通过 sql select 查询访问 table 时,我收到错误 "File is encrypted or is not a database". 虽然,没有问题教程应用程序,我可以在那里 update/insert/delete/select 记录。有什么线索吗?
我已经修好了。如前所述,相同代码的行为不同,因此设置可能有问题。在我的应用程序中,我按如下方式添加了 SQLCipher 和 FMDB:
pod 'SQLCipher', '~> 3.1'
pod 'FMDB', '~> 2.5'
而在该教程中,它们被添加为
pod 'FMDB/SQLCipher'
尽管如此,此 pod 命令会根据此处显示的终端输出下载相同版本的 SQLCipher 和 FMDB
Updating local specs repositories
Analyzing dependencies
Downloading dependencies
Installing FMDB (2.5)
Installing SQLCipher (3.1.0)
Generating Pods project
Integrating client project
所以,我像教程中那样更改了 pod 命令,错误已修复。虽然,我不知道这些命令有何不同。
我 fixed.I 认为 FMDB 和 SQLCipher 存在一些 pod 间依赖性。我已经使用以下 link 解决了这个问题。现在我的数据库文件使用带 FMDB 的 SQLCipher 成功加密了....:-D