2

This tutorial works just fine with the following pieces of code.

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"];
        ...
    }];

...

When I use the same code in my other project it works fine for encrypting the existing sqlite database. But when I try to access table via sql select query I get the error, "File is encrypted or is not a database". Though, no issue with the tutorial app and I can update/insert/delete/select records there. Any clue?

luk2302
  • 55,258
  • 23
  • 97
  • 137
zeeawan
  • 6,667
  • 2
  • 50
  • 56

2 Answers2

2

I've got it fixed. As mentioned the same code is acting differently so there might be something wrong with the settings. In my app, I added the SQLCipher and FMDB as follows:

pod 'SQLCipher', '~> 3.1'
pod 'FMDB', '~> 2.5'

while in that tutorial they are being added as

pod 'FMDB/SQLCipher'

Though, this pod command download the same versions of SQLCipher and FMDB as per the terminal output shown here

Updating local specs repositories
Analyzing dependencies
Downloading dependencies
Installing FMDB (2.5)
Installing SQLCipher (3.1.0)
Generating Pods project
Integrating client project

So, I changed the pod command like that of the tutorial and that error is fixed. Though, I don't know how these commands differ.

zeeawan
  • 6,667
  • 2
  • 50
  • 56
  • 1
    [The FMDB/SQLCipher subspec declares SQLCipher as a dependency, allowing FMDB to be compiled with the -DSQLITE_HAS_CODEC flag.](https://github.com/ccgus/fmdb#cocoapods) More exactly, [this line](https://github.com/ccgus/fmdb/blob/master/FMDB.podspec#L42). – Iulian Onofrei Nov 10 '16 at 10:54
  • Yes, it makes sense. – zeeawan Nov 10 '16 at 12:46
2

I've fixed.I think there are some inter pod dependency with FMDB & SQLCipher. I have solved this problem using below link. Now my database file encrypt successfully using SQLCipher with FMDB.... :-D

How to Use FMDB With SQLCipher?

Uday Patel
  • 41
  • 5