Question

I'm currently storing a bunch of data in NSUserDefaults or simple plists like points, levels etc. which works perfectly fine.

The problem is, anyone can edit any pList file. No need for a jailbreak. You can even use the free trial of iExplorer...

I thought of keychain but that seems to be a LOT more complex than NSUserDefaults. I don't mind if the user can see the files. I just don't want them to be able to edit anything.

Kai

Was it helpful?

Solution

My recommendation is to use Keychain for any data that you'd like to protect from being edited by user. That might look complicated at first, but it's not that complicated: Keychain can store arbitrary NSData, so you can write a function that will take your NSPropertyList, serialise it, and store into Keychain.

Function to store arbitrary NSData into keychain will look like this:

+(BOOL)setKeychainData:(NSData*)value forAccount:(NSString*)account {
    if (account == nil || value == nil) {
        return false;
    }

    NSDictionary* query = @{
        (__bridge id) kSecClass          : (__bridge id) kSecClassGenericPassword,
        (__bridge id) kSecAttrAccessible : (__bridge id) kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, // <- read about this in docs and pick the right one
        (__bridge id) kSecAttrService    : @"MyServiceName",
        (__bridge id) kSecAttrAccount    : account,
        (__bridge id) kSecValueData      : value,
    };

    OSStatus err = SecItemAdd((__bridge CFDictionaryRef) query, NULL);

    if (err != errSecSuccess) {
        NSLog(@"SecItemAdd(): %d", (int) err);
    }

    return (err == errSecSuccess);
}

Alternative way of ensuring integrity of your data would be to continue to store it in property list files and compute digest of those files (e.g. SHA-1 or SHA-256) and store those digests in the Keychain. Your app will have to recompute digest every time it writes the file and it will have to verify the digest when loading data from the property list.

OTHER TIPS

If a piece of data is not sensitive (e.g., default font size), store it in NSUserDefaults.

If it needs to be secure from casual snooping (e.g., user's password), store it in the Keychain.

If it needs to be secure from the user (e.g., registration code), you will need to roll your own encryption, then store the data wherever you like.

EDIT:

Or if your data structure is simple, more straightforward way (than encrypting) is writing them to a .txt file which will not be editable or visible to the user.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top