6

I'm planning to use In-App Purchases to unlock some features in my app. What is the most secure way to do this?

Originally I planned to set a Bool in the NSUserDefaults:

[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isPro"];

But I'm not really sure whether there is a possibility to set this value via a "hack" (as NSUserDefaults are managed by iOS and not directly by the app) so that the user doesn't have to perform the In-App Purchase in order to get the full version.

What's the best practice to handle this?

Patrick
  • 3,091
  • 4
  • 26
  • 29
  • Check [this answer](http://stackoverflow.com/questions/4978852/storing-in-app-purchase-receipts-in-the-application-keychain) for how to store that in the Keychain. – Eric Jun 07 '13 at 00:07

4 Answers4

8

Yes, it's relatively easy to modify application preferences. But does it really matter? I would wager that anybody who is willing to crack open their iPhone filesystem and modify config files to save a quid or two is not the type of person who would be inclined to spend the money if they were unable to do so.

Jim
  • 72,985
  • 14
  • 101
  • 108
3

Security through Obfuscation is the simplest way to go here (e.g. don't name your var "isPro" and perhaps don't have it's value be a simple BOOL but instead have it be some "magic" integer. Not foolproof but another speed bump to cracking.

As an alternative to using NSUserDefaults you could save a file to the app filesystem and then check it's contents at app launch.

Not sure it is worth the time and trouble though.

spring
  • 18,009
  • 15
  • 80
  • 160
1

You could save it in the keychain, but then on a jailbroken device it's also easy to read and change that. So you should encrypt the data. Make sure that the encryption password can not be found easily in your app by scanning the binary.

Edwin Vermeer
  • 13,017
  • 2
  • 34
  • 58
0

I came across some problem and found two common ways for secure storing of In-App Purchases:

1) Using secure version of NSUserDefaults:

a) "Secure NSUserDefaults". This version of NSUserDefaults generate hash for any saved secret item and provide to you validation of this hash for item after. So, you can easily deal this situation of "hack" defaults .plist by user.

Check here: https://github.com/matthiasplappert/Secure-NSUserDefaults

b) "SecureNSUserDefaults". NSUserDefaults with AES encryption. My advise here not just storing secure bool values for purchases, but rather some obfuscated string for indication of payment done or not.

Check here: https://github.com/nielsmouthaan/SecureNSUserDefaults

2) Using KeyChain

a) "RSSecrets" Simple class to store key-value items in KeyChain. See also discussion here: Storing In App Purchase receipts in the application Keychain

And check project: https://github.com/jeffargast/RSSecrets

b) "STKeychain" Mostly this class used for storing login/pass in KeyChain, but in project of MKStroreKit (popular In-App Purchases StoreKit for iOS devices) they actually use this class for storing In-App Purchases.

Check here: https://github.com/ldandersen/STUtils/blob/master/Security/STKeychain.h

P.S. I am not yet used any of this classes in my project, but think to use "RSSecrets"

Community
  • 1
  • 1
Anton Malmygin
  • 3,406
  • 2
  • 25
  • 31
  • Does the user need to have iCloud keychain enabled for option 2) to work? Will keychain work on Apple Watch? – Ace Green Oct 19 '15 at 15:45
  • @AceGreen As I remember correctly, you don't need to enable iCloud to use solution 2) (at the moment of 2014 it was like this). And also I wasn't test it to use with Apple Watch. – Anton Malmygin Oct 19 '15 at 21:51
  • should have rephrased it differently. I guess iCloud Keychain needs to be enabled if you want to keychain to sync so you can get your key on Apple Watch that you set on iOS – Ace Green Oct 19 '15 at 22:38