SQLCipher and CoreData issue: CoreData could not fulfill a fault for
Asked Answered
W

2

13

I have an issue with SQLCipher db encryption and CoreData: When I use persistent store coordinator with SQLCipher, it always crash with fault one-to-many relationship after first app relaunch. So when I first time launch the app, I create NSManagedObjects with relationships, then, when I save db, and reopen the app, it crash when I try to access to these relationship. Without SQLCipher everything works fine.

Here is the code for SQLCipher persistent store initialize:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (!_persistentStoreCoordinator) {
        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyApp.sqlite"];
        NSDictionary *options = @{EncryptedStorePassphraseKey: @"MyApp",
                                                            EncryptedStoreDatabaseLocation: storeURL};
        NSError *error;
        _persistentStoreCoordinator = [EncryptedStore makeStoreWithOptions:options managedObjectModel:[self managedObjectModel] error:&error];
        if (error) {
            NSLog(@"%@", error);
        }
    }

    return _persistentStoreCoordinator;
}

Code where I create NSManagedObject:

- (id)createObjectWithClassName:(NSString *)name
{
    NSManagedObject *object = [[NSClassFromString(name) alloc] initWithEntity:[NSEntityDescription entityForName:name inManagedObjectContext:self.context] insertIntoManagedObjectContext:self.context];
    return object;
}
Witten answered 5/12, 2014 at 9:11 Comment(6)
What does the code that creates the managed objects look like?Matteson
@TomHarrington I updated post with NSManagedObject creation codeWitten
useful link : developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…Cloudburst
Are you trying to run any migrations or did you make any changes to the managed object model between saving the database and reopening the app?Oration
I already implement such protection, but client want to use SQLCipher...Witten
@Oration no, database model don't changed during relaunch. I think problem can be in one-to-many ordered relationship. I'm looking further in EncryptedStore implementation, maybe I'll find answer thereWitten
W
1

Finally I find the answer by myself.

I investigate different cases, and figured, that issue happens only in my Data Model.

Problem was that I have one property in NSManagedObject class with name "index".

Looks like SQLCipher internally use such property and there was conflicts with it. Once I rename it to another name, everything works!

Witten answered 19/12, 2014 at 23:40 Comment(0)
M
1

With SQLCipher make sure you have a brand new SQLite database. Trying to pragma the database with a key while it already has data for some reason just tries to decrypt it.

ATTACH DATABASE 'encrypted.db' AS encrypted KEY 'secret'; -- create a new encrypted database
CREATE TABLE encrypted.t1(a,b); -- recreate the schema in the new database (you can inspect all    objects using SELECT * FROM sqlite_master)
INSERT INTO encrypted.t1 SELECT * FROM t1; -- copy data from the existing tables to the new tables in the encrypted database
DETACH DATABASE encrypted;

--

//For persistentStoreCoordinator:
// Give modelName = @"MyApp.sqlite";
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator:(NSString*)modelName
{
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }


    NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    @"PushNoticationModal.sqlite"
    NSURL *storeUrl = [NSURL fileURLWithPath:[docs stringByAppendingPathComponent:modelName]];
    NSError *error = nil;
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    NSError *error;
    persistentStoreCoordinator = [EncryptedStore makeStoreWithOptions:options managedObjectModel:[self managedObjectModel] error:&error];
    if (error) {
    NSLog(@"%@", error);
    }

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
        NSLog(@"persistentStoreCoordinator Error: %@,%@",error,[error userInfo]);
    }



    return persistentStoreCoordinator;
}
Mincey answered 18/12, 2014 at 4:59 Comment(2)
Your code not help me. And also it have a logical problem: you create persistentStoreCoordinator two times (normal and ecnrypted), which have no sense...Witten
last time there is some mistake, which i corrected but bot tested, due to shortage of time.Mincey
W
1

Finally I find the answer by myself.

I investigate different cases, and figured, that issue happens only in my Data Model.

Problem was that I have one property in NSManagedObject class with name "index".

Looks like SQLCipher internally use such property and there was conflicts with it. Once I rename it to another name, everything works!

Witten answered 19/12, 2014 at 23:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.