【问题标题】:iOS sqlcipher fmdb “File is encrypted or is not a database”iOS sqlcipher fmdb“文件已加密或不是数据库”
【发布时间】:2015-11-09 11:01:28
【问题描述】:

这个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 查询访问表时,我收到错误消息“文件已加密或不是数据库”。不过,教程应用程序没有问题,我可以更新/插入/删除/选择那里的记录。有什么线索吗?

【问题讨论】:

    标签: ios sqlite encryption fmdb sqlcipher


    【解决方案1】:

    我已经解决了。如前所述,相同的代码行为不同,因此设置可能有问题。在我的应用程序中,我添加了 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 命令,并且该错误已修复。不过,我不知道这些命令有何不同。

    【解决方案2】:

    我已经修复了。我认为 FMDB 和 SQLCipher 存在一些 Pod 间依赖关系。我已经使用下面的链接解决了这个问题。现在我的数据库文件使用带有 FMDB 的 SQLCipher 成功加密...... :-D

    How to Use FMDB With SQLCipher?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 2014-11-05
      • 1970-01-01
      • 1970-01-01
      • 2010-12-03
      • 1970-01-01
      相关资源
      最近更新 更多