Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration Old unencrypted Core database to Encrypted Core Data base(using SQLCipher). #331

Open
emorphisgit opened this issue Aug 20, 2020 · 0 comments

Comments

@emorphisgit
Copy link

emorphisgit commented Aug 20, 2020

I have a live iOS application on apple app-store which is using the core data.
Now I want to encrypt the core-data using EncryptedCoreData (https://github.com/project-imas/encrypted-core-data 2).
I am successfully able to implement the same with my project and it working fine for fresh installed but when I tried to override my existing application which is not using the encrypted coredata with the new application which is using the encrypted coredata at that time I am unable to get my old data back.
I don't know what I am doing wrong.
Following is my code sample

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (persistentStoreCoordinator_ != nil) {
        return persistentStoreCoordinator_;
    }
    else if (!storeUrl)
        return nil;
    
    NSError *error = nil;
    persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
    NSDictionary *options = @{          EncryptedStorePassphraseKey : @"123456",
                                        EncryptedStoreFileManagerOption : [EncryptedStoreFileManager defaultManager],
                                        NSMigratePersistentStoresAutomaticallyOption : @YES
                                        };

    NSPersistentStore *store = [persistentStoreCoordinator_
                                addPersistentStoreWithType:EncryptedStoreType
                                configuration:nil
                                URL:storeUrl
                                options:options
                                error:&error];
    
    if (!store && error)
    {
        [self encryptDB:[storeUrl absoluteString] url:storeUrl];

        NSError *error1 = nil;
        NSPersistentStore *store1 = [persistentStoreCoordinator_
                                    addPersistentStoreWithType:EncryptedStoreType
                                    configuration:nil
                                    URL:storeUrl
                                    options:options
                                    error:&error1];
    }
    
    return persistentStoreCoordinator_;
}

//encryptDB used for encriptt the existing DB with password
- (void)encryptDB:(NSString*)path_u url:(NSURL*)url
{
    sqlite3 *unencrypted_DB;
    sqlite3 *encrypted_DB;
    NSString *tempFile = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
                        stringByAppendingPathComponent:@"encrypted.sqlite"];
    
    NSURL *tempUrl = [NSURL fileURLWithPath:tempFile];

    if (sqlite3_open([path_u UTF8String], &unencrypted_DB) == SQLITE_OK) {
        NSLog(@"Database Opened");
        // Attach empty encrypted database to unencrypted database
        
        NSString *strEncryptedPath = [NSString stringWithFormat:@"ATTACH DATABASE '%@' AS encrypted KEY '123456';",tempFile];
        
        sqlite3_exec(unencrypted_DB, [strEncryptedPath UTF8String], 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);
        
        int version = [self queryUserVersion:unencrypted_DB];
        sqlite3_close(unencrypted_DB);
        NSLog (@"End database copying");

        
        if (sqlite3_open([tempFile UTF8String], &encrypted_DB) == SQLITE_OK) {
                  const char* key = [@"123456" UTF8String];
                  sqlite3_key(encrypted_DB, key, (int)strlen(key));
                 [self setVersion:encrypted_DB version:(int)version];
          }
         sqlite3_close(encrypted_DB);
        
        NSError *error = nil;
       [[NSFileManager defaultManager] removeItemAtURL:url error:&error];

         BOOL result = [[NSFileManager defaultManager] moveItemAtURL:tempUrl toURL:url error:&error];
        if(!result)
            NSLog(@"Error: %@", error);
    }
    else {
        sqlite3_close(unencrypted_DB);
        //NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(unencrypted_DB));
    }
}
-(void)setVersion: (sqlite3*) db version:(int)version {
    
    // get current database version of schema
    static sqlite3_stmt *stmt_version;
    
    if(sqlite3_prepare_v2(db, "PRAGMA user_version;", -1, &stmt_version, NULL) == SQLITE_OK) {
        while(sqlite3_step(stmt_version) == SQLITE_ROW) {
            db = sqlite3_bind_int( stmt_version, 1, version ); // Bind first parameter.
        }
    } else {
        NSLog(@"%s: ERROR Preparing: , %s", __FUNCTION__, sqlite3_errmsg(db) );
    }
    sqlite3_finalize(stmt_version);
}
-(int)queryUserVersion: (sqlite3*) db {
    // get current database version of schema
    static sqlite3_stmt *stmt_version;
    int databaseVersion;

    if(sqlite3_prepare_v2(db, "PRAGMA user_version;", -1, &stmt_version, NULL) == SQLITE_OK) {
        while(sqlite3_step(stmt_version) == SQLITE_ROW) {
            databaseVersion = sqlite3_column_int(stmt_version, 0);
            NSLog(@"%s: version %d", __FUNCTION__, databaseVersion);
        }
        NSLog(@"%s: the databaseVersion is: %d", __FUNCTION__, databaseVersion);
    } else {
        NSLog(@"%s: ERROR Preparing: , %s", __FUNCTION__, sqlite3_errmsg(db) );
    }
    sqlite3_finalize(stmt_version);

    return databaseVersion;
}

Following code I am using for fetch the data

NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"HistoryEvent" inManagedObjectContext:dbDataFile.managedObjectContext];
    [request setEntity:entity];
NSMutableArray* andPredicateArray = [[NSMutableArray alloc] init];
    if (guid)
    {
        [andPredicateArray addObject:
         [NSPredicate predicateWithFormat:@"guid = %@", guid]];
    }
    NSPredicate* predicate = [NSCompoundPredicate andPredicateWithSubpredicates:andPredicateArray];
    [request setPredicate:predicate];
    
    [request setFetchLimit:limit];
NSMutableArray* sortDescriptors = [[NSMutableArray alloc] init];
        [sortDescriptors addObject:
         [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:[isAscendingCreationDatesNum boolValue]]];
[request setSortDescriptors:sortDescriptors];
    NSError *error = nil;
    NSMutableArray *mutableFetchResults = [[dbDataFile.managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
    if (!mutableFetchResults && errorMessage && error)
    {
		NSLog(@"Error to fetch”); //I am not getting any error here
    }
    
    return mutableFetchResults; //Count is zero

Can anyone please help me and point out what I am doing wrong.
Again If I installed fresh application then the same code is working fine
I am only getting empty data when tried to override the existing app i.e installing encrypted coredata app on non-encrypted coredata.
I also created an issue at https://discuss.zetetic.net/t/unable-to-fetch-data/4560

@emorphisgit emorphisgit changed the title Migration Old database to Encrypted Core Data base. Migration Old Core database to Encrypted Core Data base(using SQLCipher). Aug 20, 2020
@emorphisgit emorphisgit changed the title Migration Old Core database to Encrypted Core Data base(using SQLCipher). Migration Old unencrypted Core database to Encrypted Core Data base(using SQLCipher). Aug 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant