Where to store sensitive data - ios

What is the best practice to store sensitive(not secure) data on iOS devices?
Where should I store information that user bought something in app? For example where should I store BOOL showAds variable if user bought "Remove Ads"?
I do understand that everything breakable, especially on jailbroken devices, I just asking what is the best practice.
My variants:
.plist in App Documents -- Editable using iFunBox, for example
NSUserDefaults -- Same here, I guess
Keychain -- best variant in my opinion so far

You can store you data in NSUserDefaults using base 64 encoding data to keep safe it.
The code is very simple:
NSUserDefaults *persistValues;
persistValues = [NSUserDefaults standardUserDefaults];
To set data (encoding it using base 64):
// Create NSData object
NSData *nsdata = [#"iOS Developer Tips encoded in Base64" dataUsingEncoding:NSUTF8StringEncoding];
// Get NSString from NSData object in Base64
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
[persistValues setObject:base64Encoded forKey:#"some_key"];
To get data:
base64Encoded = [persistValues stringForKey:#"some_key"];
NSData *nsdataFromBase64String = [[NSData alloc]
initWithBase64EncodedString:base64Encoded options:0];
// Decoded NSString from the NSData
NSString *base64Decoded = [[NSString alloc]
initWithData:nsdataFromBase64String encoding:NSUTF8StringEncoding];
And if you data is bigger I suggest you uses web services and store it in a web server

Keychain is best option to store sensitive data.
Other than sensitive data below are 2 options :
Small data can be stored in NSUserDefault as its best way as physical file will not be available for changing data.
Bigger data can be stored in database with encryption

Related

Do property lists save between app sessions?

I was wondering if property lists, (.plist) would save the contents if i were to exit the app and then re-open it. I would like to save a couple of variables to a plist so I could read from it every time I need some universal information about the user in my app.
Do plists save the variables if I were to close and reopen the app?
Should I be using plists or is there a better way to do this?
Thank you!
Yes, you can use plist to save user infomation. This is a sample way. Make a plist and write to the sandbox.
NSString *urlStr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
urlStr = [urlStr stringByAppendingPathComponent:#"userInfo.dic"];
NSURL *url = [NSURL fileURLWithPath:urlStr];
[userInfoDictionary writeToURL:url error:NULL];
You can also use SQLite database or Core Data if the information is complex.

How to cache JSON web response locally on iOS - objective c

I am building a mobile iOS app for a web backend. I retrieve the JSON response using the following code:
NSError *error;
NSString *url_string = [NSString stringWithFormat: #"https://myURL"];
NSData *data = [NSData dataWithContentsOfURL: [NSURL URLWithString:url_string]];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
What would be the best/simplest way to store this data locally so that I can use a local database when internet connectivity is not available? The intention is to check web connectivity at launch of the app. If connection is available, get JSON response, parse and update local copy, if connection is not available parse the data from local storage.
Thanks in advance.
If you wish to cache the JSON data so you can still use it offline, I would write the JSON dictionary (or the data) to a file in your app's sandbox. A subfolder of the "Application Support" folder would be a good place. You don't want to use the Caches folder in this case because the files could be purged by iOS when you need them offline.
The trick is to map a given URL to a filename. You need this mapping to both save a file for a given URL and to later load the file if offline. You should be able convert a URL to a useful filename simply by converting all / characters to something else such as an underscore.
You probably don't want these files backed up when a user backups their iOS device so be sure you mark the files with the "do not backup" attribute. There are many existing question covering that topic.
The best way is CoreData and
the simplest way is NSUserDefaults
NSUserDefaults Class Reference
[[NSUserDefaults standardUserDefaults] setObject: jsonDict forKey:#"dictionaryKey"];
//...
NSDictionary * myDictionary = [[NSUserDefaults standardUserDefaults] dictionaryForKey:#"dictionaryKey"];

UIWebView must get localStorage item and store it in the app natively / retrive it natively

I have the first part figured out...
- (void)webViewDidFinishLoad:(UIWebView*) myTapView {
NSString *jsString = #"localStorage.getItem('username');";
NSString *someKeyValue = [tapView stringByEvaluatingJavaScriptFromString:jsString];
// This is where I would start storing it so I can retrieve it later
}
So here is my issue, I need to store the value I just got from localStorage so I can use it again. Problem is I don't know where to start. This code is inside my ViewController for the WebView, so I need to be able to use it in other areas in the ViewController.m file.
What is the best method for storing the info? I would also want the above code to be able to update the value, as it won't always be the same username (people can switch accounts).
There are a few ways to store data on iOS, but it depends on what kind of value you want to store. If it's just a plain string or other "light" data, the best approach is to save it to NSUserDefaults. If it's an image or video, you may want to consider archiving it using NSKeyedArchiver. Otherwise, if you want to build a complicated data model, use Core Data.
Here's a good post on NSHipster that describe in detail pros and cons of each approach.
According to your code, you want to store a string. I'd go with NSUserDefaults in this case.
Use NSUserDefaults to store UIWebView local storage value as follows
- (void)webViewDidFinishLoad:(UIWebView*) myTapView {
NSString *jsString = #"localStorage.getItem('username');";
NSString *someKeyValue = [myTapView stringByEvaluatingJavaScriptFromString:jsString];
// Store your Username in iPhone persistence variable and use it later in the application
NSUserDefaults *userdefault = [NSUserDefaults standardUserDefaults];
[userdefault setObject:someKeyValue forKey:#"username"];
[userdefault synchronize];
//use of User default
NSLog(#"User name %#",[userdefault valueForKey:#"username"]);
}

hide registration code from user on iOS

Only a short question here, I would like to know the best place to put my registration code for the user that I get back from the server. I am encrypting it as seen here.
//encrypting
NSString* strToEncrypt =NewPINField.text
NSString* theKey = #\"KeyKeyKeyKey\";
NSData* dataToEncrypt = [strToEncrypt dataUsingEncoding: NSUTF8StringEncoding];
NSData *encryptedData = [dataToEncrypt EncryptWithKey: theKey];
NSLog(#\"Encrypted data: %#\", encryptedData);
//decrypting
NSData* encryptedData = (NSData*)[profileData objectForKey:#\"PIN\"];
NSString* theKey = #\"KeyKeyKeyKey\"; //notice this is the same as above. It MUST be
NSData *decData = [encryptedData DecryptWithKey: theKey ];
currentPIN = [NSString stringWithUTF8String:[decData bytes]];
NSLog(#\"Decrypted pin: %#\", currentPIN);
The only other specification is to hide it / put it somewhere no know would think to look.
I need to save state so it needs to be some sort of plist, I was just wondering if there is a way to hide it a little better than just adding it straight to my plist file.
what would you do?
Any help would be greatly appreciated.
If you need to securely store data, I would highly recommend using the keychain. There is a tutorial on creating a basic keychain app here: http://www.raywenderlich.com/6475/basic-security-in-ios-5-tutorial-part-1
You can safely store data in the keychain without worrying about encrypting it first, since that is handled by the OS. But you can if you want to.
When implementing security, never try to hide things where someone won't look: http://en.wikipedia.org/wiki/Security_through_obscurity

Encryption of contents in compiled iOS app ( IPA )

As IPA structure is just a zipped file containing compiled codes & media contents like images & audio, how can I protect the contents from being extracted and stolen by others? Is there any encryption I can add into the IPA?
This answer mentions that the application is already encrypted by the time it gets onto your users' devices: Does Apple modify iOS application executables on apps submitted to the App Store?
Sorry, that's only the application binary. The other media are not encrypted, and no, there's no way to encrypt the .ipa. You could try encrypting your images and other media on your system, providing a bunch of application code to decrypt those resources when the app runs, and then your decryption code will become a part of the encrypted application binary. You can't submit an encrypted IPA though, it needs to be the file directly output from Xcode.
In response to your comment, the one I've used in the past is CommonCrypto. You can use this crypto library as a starting point.
Simple usage example of the above:
NSError *error;
NSMutableData *encryptedData = [NSMutableData dataWithContentsOfFile:pathToEncryptedFile];
NSData *decryptedData = [RNDecryptor decryptData:encryptedData
withPassword:#"SuperSecretDecryptionKey"
error:&error];
UIImage *decryptedImage = [UIImage imageWithData:decryptedData];
IMPORTANT NOTE HERE: IF someone was to run the strings utility on your .app on a jailbroken iphone, or even on an iPhone they have filesystem access to via USB, they will get a list of all strings declared in your app. This includes "SuperSecretDecryptionKey". So you may want to use an integer, floating-point or other constant to do on-the-fly generation of a string decryption key, or make sure that the string you use to decrypt things is exactly the same as a normal system string so no-one suspects it as the true key. Security through obscurity, in this case, is advantageous.
To encrypt/decrypt *.strings files, you should encrypt the key and value strings in some manner (maybe one which gives you hexadecimal back, or any alphanumeric characters), and when you want to access a given value, say LicenceNumber, do this:
NSError *error;
NSData *unencryptedKey = [#"LicenceNumber"
dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedKey = [RNEncryptor encryptData:unencryptedKey
withSettings:kRNCryptorAES256Settings
password:#"SuperSecretEncryptionKey"
error:&error]
NSData *encryptedValue = [[NSBundle mainBundle]
localizedStringForKey:[NSString
stringWithUTF8String:[encryptedKey bytes]]
value:#"No licence"
table:#"EncryptedStringsFile"];
NSData *decryptedValue = [RNDecryptor decryptData:encryptedValue
withPassword:#"SuperSecretDecryptionKey"
error:&error];

Resources