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?
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.