Questions › Encrypting Plist File Method

I have a Property List titled GameData.plist. I am trying to see if the way that I am encrypting the plist is correct or not. Since you are unable to manually edit the main bundle files (which would have been an easy way to see if the data was indeed encrypted now), and I don't seem to be finding my plist in the available data through iExplorer, I am not sure if anything is actually being encrypted.

The goal is for the information to be overwritten with encrypted data. Im not sure if that's how it works, I am just trying to prevent the data in the plist to be viewed outside the app running or not running. Here is what I am doing:

- (void)encryptionWithAES256 {
        .
        .
        .
    NSString* path = [[ NSBundle mainBundle] bundlePath];
    NSString* finalPath = [ path stringByAppendingPathComponent:@"GameData"];
    NSDictionary *plistDic = [NSDictionary dictionaryWithContentsOfFile:finalPath];
    NSLog(@"Plist: %@", plistDic);

    NSData *plistData = [NSKeyedArchiver archivedDataWithRootObject:plistDic];
    NSData *encryptedData = [plistData AES256EncryptWithKey:@"<ENCRYPTION_KEY>"];
    [encryptedData writeToFile:finalPath atomically:YES];
        .
        .
        .
}

NOTE: for testing purposes, the GameData.plist is simply the default plist that Xcode creates for a project, as shown below:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>Test</key>
        <string>GameDataTest</string>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        <key>CFBundleExecutable</key>
        <string>$(EXECUTABLE_NAME)</string>
        <key>CFBundleIdentifier</key>
        <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleName</key>
        <string>$(PRODUCT_NAME)</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
        <string>1.0</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
        <string>1</string>
        <key>LSRequiresIPhoneOS</key>
        <true/>
        <key>UILaunchStoryboardName</key>
        <string>LaunchScreen</string>
        <key>UIMainStoryboardFile</key>
        <string>Main</string>
        <key>UIRequiredDeviceCapabilities</key>
        <array>
            <string>armv7</string>
        </array>
        <key>UISupportedInterfaceOrientations</key>
        <array>
            <string>UIInterfaceOrientationPortrait</string>
            <string>UIInterfaceOrientationLandscapeLeft</string>
            <string>UIInterfaceOrientationLandscapeRight</string>
        </array>
        <key>UISupportedInterfaceOrientations~ipad</key>
        <array>
            <string>UIInterfaceOrientationPortrait</string>
            <string>UIInterfaceOrientationPortraitUpsideDown</string>
            <string>UIInterfaceOrientationLandscapeLeft</string>
            <string>UIInterfaceOrientationLandscapeRight</string>
        </array>
    </dict>
</plist>

How can I check to see if the data is being "replaced" or overwritten by the now encrypted data? I tried to then insert a log of the file contents before this method gets called to see if it would retrieve and show encrypted plist data, but it does not. I am not sure if that's because it is just reading the data from the plist in the main bundle, or the writeToFile is not doing what I need. Thanks!

UPDATE This is for the average user trying to get hold of my apps data so that they could potentially be able to see the plist as a mess of encryption rather than all of the plain text plist data.

Comments :
rmaddy replied

You are attempting to write the new file over the old, read-only file. As you stated, you can't write to the app bundle.

How can I have a non-encrypted file in the apps bundle become encrypted to all eyes? Unless should I be encrypting the file before hand then adding it to the app already secure?

Hamish replied

While not nearly as secure as encryption, have you considered using NSKeyedArchiver? That way the file contents won't be a plain-text format, making it much harder for the "average user" to modify. Also, @rmaddy is right, you should be saving this file outside of your bundle (in the documents directory maybe)

rmaddy replied

@WillVonUllrich Any non-encrypted plist file packaged in the app bundle can easily be viewed by anyone that downloads your app. If you have sensitive data, either package it as an encrypted file or download the data (using https:) the first time the user runs the app.

Sulthan replied

@WillVonUllrich You cannot overwrite the app bundle. The app bundle and all information inside it is used by the system to load your application. If you could somehow overwrite the data, then your app wouldn't probably run. There are reasons why you cannot modify your own app from within the app. If you have some sensitive data there, you are doing that wrong.


1 Answers :
bbum answered

If you want to have encrypted data delivered with your application, it needs to be encrypted during the build process, not during runtime. The easiest way to do this is to encrypt the file however you want and then add it to your Xcode project as a resource. You then read it as an NSData as you would any other resource and decrypt in memory.

That is currently what I was going to do.. I felt kind of silly after figuring that one out lol. One question tho - would it be safer to use this approach, with a Documents file containing the encrypted NSData, OR to hard code all of the level data into a GameData.m/GameData.h and use it where needed? I am unsure of just how secure class files are in terms of being able to pull the lines of code (AKA being able to read the GameData.m file as a txt file);
bbum replied
Data is data; doesn't really matter where it is, it is just as readable as you make it. :) Honestly, I wouldn't bother trying too hard to secure this stuff. By definition, the decryption keys are going to either ship with your app or your app is going to require a network connection (or the user is going to be inconvenienced). I'd start with something as convenient as modular as possible; the best performing app is useless if it never ships. :);
ok thanks! I'll probably just use the encrypted file, a little easier to work with it feels like. Makes sense though too - in reality it really doesn't matter where the data goes, if someone wants to find it that bad they will. Might as well just make it annoying to get to and if they do get it, encrypt it just to piss them off even more haha;