使用SQLCipher将加密数据库附加到未加密的数据库

时间:2012-01-19 18:46:47

标签: iphone encryption sqlite sqlcipher

我正在尝试使用SQLCipher将未加密的sqlite3数据库的内容添加到加密的数据库中。我的基础是thisthis。然而,有些事情我不清楚。

  1. 在第ATTACH DATABASE行中,加密数据库的类型是.db吗?可以.sqlite匹配我的原始数据库吗?

  2. 说加密数据库必须已经存在吗?如果是这样,它应该在应用程序中的哪个位置?我是否必须提供文件路径(文档目录等)?

  3. 在哪里可以找到成功加密的数据库?它会在哪里保存?

  4. 这是我的代码:

    + (void)encryptDB
    {
        sqlite3 *unencrypted_DB;
        NSString *path_u = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
                      stringByAppendingPathComponent:@"dict.sqlite"];
    
        if (sqlite3_open([path_u UTF8String], &unencrypted_DB) == SQLITE_OK) {
            NSLog(@"Database Opened");
            // Attach empty encrypted database to unencrypted database
            sqlite3_exec(unencrypted_DB, "ATTACH DATABASE 'dict_encrypted.sqlite' AS encrypted KEY '1234';", NULL, NULL, NULL);
    
            // Create new tables within encrypted database to match those in unencrypted database
            sqlite3_exec(unencrypted_DB, "CREATE TABLE encrypted.t1(A,B,C);", NULL, NULL, NULL);
    
            // Copy items from unencrypted database into encrypted database
            sqlite3_exec(unencrypted_DB, "INSERT INTO encrypted.t1 SELECT * FROM t1;", NULL, NULL, NULL);
    
            // Detach encrypted database
            sqlite3_exec(unencrypted_DB, "DETACH DATABASE encrypted;", NULL, NULL, NULL);
    
            NSLog (@"End database copying");
            sqlite3_close(unencrypted_DB);
        }
        else {
            sqlite3_close(unencrypted_DB);
            NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(unencrypted_DB));
        }
    }
    

3 个答案:

答案 0 :(得分:6)

使用最新版本的SQLCipher,我们有sqlcipher_export()函数可以缩短代码并且不会连接到现有的数据库结构:

+ (void)encryptDB
{
    sqlite3 *unencrypted_DB;
    NSString *path_u = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
                         stringByAppendingPathComponent:@"dict.sqlite"];

    if (sqlite3_open([path_u UTF8String], &unencrypted_DB) == SQLITE_OK) {
        NSLog(@"Database Opened");
        // Attach empty encrypted database to unencrypted database
        sqlite3_exec(unencrypted_DB, "ATTACH DATABASE 'dict_encrypted.sqlite' AS encrypted KEY '1234';", 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);

        NSLog (@"End database copying");
      sqlite3_close(unencrypted_DB);
    }
    else {
        sqlite3_close(unencrypted_DB);
        NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(unencrypted_DB));
    }
}

答案 1 :(得分:5)

  1. 加密数据库是否必须是.db类型? - 不,你可以使用你想要的任何扩展名。
  2. 说加密数据库必须已经存在吗? - 否则数据库不需要存在。附加不存在的数据库时,它将创建一个新的
  3. 我是否必须提供文件路径(文档目录等)? - 是的,您需要提供数据库的路径,否则应用程序的当前工作目录将使用。在iOS上,您通常应提供文件名的完整路径,包括应用程序文档目录。
  4. 我在哪里可以找到成功加密的数据库? - 加密数据库将位于您告知附加的位置。按#3,如果您要为iOS构建,请在文件名中包含文档目录的完整路径,然后加密数据库将位于此处。

答案 2 :(得分:0)

好吧,我从来没有完成ATTACH DATABASE,我使用的SQLCiper版本可能与你的不同,但是(对于我所处理的SQLCipher的实现),文件打开逻辑是标准的SQLite,其行为与没有SQLCipher的行为相同。

所以你不需要.db的后缀或其他任何特定的后缀 - 你可以使用你想要的任何东西。

在发出REKEY之前,任何新数据库都完全“正常”,并且将以“正常”方式为SQLite创建/删除。

重新ATTACH DATABASE,我怀疑最好首先创建数据库(和REKEY),然后附加它。