Make Better Things



I like to make better things.

Create a folder inside documents directory in iOS apps

 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"/MyFolder"];

if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
    [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder

iOS app security: Data Protection (Part 1)

Are you storing User’s credentials in app, Communicating with web services, getting user’s credit card details in your app? using in app purchases? If your answer is yes for any of these questions then you should seriously consider improving security of your application? Are you implementing proper security measures? if no then read on.. I am going to write a series of posts on iOS app security.

In this first post of this series I am going to explain how we can protect files which we are creating in our app.

iOS provides hardware-level encryption of files. Files marked for protection are encrypted using a per-device key, which is encrypted using the user’s password or PIN. Ten seconds after the device is locked, the unencrypted per-device key is removed from memory. When the user unlocks the device, the password or personal identification number (PIN) is used to decrypt the per-device key again, which is then used to decrypt the files.

You can configure the protection of files that you create with NSFileManager or NSData. The options, shown in the following list, have slightly different names. NSFileManager applies string attributes to the file, whereas NSData uses numeric options during creation, but the meanings are the same. The FileManager constants begin with NSFileProtection…, and the NSData constants begin with NSDataWritingFileProtection….

…None — The file is not protected and can be read or written at any time. This is the default value.

…Complete — Any file with this setting is protected ten seconds after the device is locked. This is the highest level of protection. Files with this setting may not be available when your program is running in the background. When the device is unlocked, these files are unprotected.

…CompleteUnlessOpen — Files with this setting are protected ten seconds after the device is locked unless they’re currently open. This allows your program to continue accessing the file while running in the background. When the file is closed, it will be protected if the device is locked.

…CompleteUntilFirstUserAuthentication — Files with this setting are protected only between the time the device boots and the first time the user unlocks the device. The files are unprotected from that point until the device is rebooted. This allows your application to open existing files while running in the background.

Sample usages with NSData -

 
[data writeToFile:path
             options:NSDataWritingFileProtectionComplete
               error:&error]

Sample usages with NSFileManager -

 
[[NSFileManager defaultManager] createFileAtPath:[self filePath]
                                        contents:[@"super secret file contents" dataUsingEncoding:NSUTF8StringEncoding]
                                      attributes:[NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey]];

If your application needs to know whether protected data is available, you can use one of the following:

- Implement the methods applicationProtectedDataWillBecomeUnavailable: and applicationProtectedDataDidBecomeAvailable: in your application delegate.

- Observe the notifications UIApplicationProtectedDataWillBecomeUnavailable and UIApplicationProtectedDataDidBecomeAvailable (these constants lack the traditional Notification suffix).

- Check[[UIApplication sharedApplication] protectedDataAvailable]

The weakest point in using file protection is that it depends on the 4 digit PIN user use, which offer only 10,000 combinations. Also if user is not using PIN then this won’t work at all.

Pro Tip -

The easiest way to create a protected file when you may or may not be in the background is as follows:

 
   [data writeToFile:path
             options:NSDataWritingFileProtectionComplete
               error:&error] ||
   [data writeToFile:path
             options:NSDataWritingFileProtectionCompleteUnlessOpen
               error:&error];

Note “||” between two statements.

If you use this technique, upgrade your file protection at startup with a routine like this:

 
-(void)upgradeFilesInDirectory:(NSString *)dir
                            error:(NSError **)error {
     NSFileManager *fm = [NSFileManager defaultManager];
     NSDirectoryEnumerator *dirEnum = [fm enumeratorAtPath:dir];
     for (NSString *path in dirEnum) {

		NSDictionary *attrs = [dirEnum fileAttributes];
		if (![[attrs objectForKey: NSFileProtectionKey]
    				isEqual:NSFileProtectionComplete]) {
			attrs = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
			[fm setAttributes:attrs ofItemAtPath:path error:error];
		}

	} 

}

File protection is very easy, simple and hardware-optimised, you should use this in every project of yours, unless you have a good reason to not to.