NOTE ---- The answer below uses iOS6- methods, Apple has since then removed developer's access to MAC addresses. If you are developing for iOS7+ disregaurd first answer and just encrypt your IAP unlock data based on other variables that will be unique to each device (like the date the app was first launched)
I have features that need tone unlocked so I store them in my plist files.... a feature like a new avatar in a chat room could have the id "13891" and if it is unlocked I might assign it some key like "93" and if it's locked it might have any other key "37" for example.... So the plist will say: "13891" = "93" My question is can jailbroken phones edit the plist files easily and unlock features for themselves? What's a better way of storing this data? I don't want to have to check Apple's servers every time, it takes too long with low internet connection.
Edit: Current Answer:
4 measures to take:
1) Store it in the keychain. (Or plist I guess now that I've added measure #4)
2) Check Apple's servers every time but if you are worried about the lag that follows just check it in the background and in the meantime let the user use the app if it says they can.
3) Store your variables as encrypted keys in the keychain... don't store "FishingRod = unlocked" store "3dhk34D@HT% = d3tD@#".
4) Encrypt each key with the devices MAC address (these MAC addresses do NOT change and are available with or without WiFi connection... code below). That way if a user downloads a plist off of the internet and tries to use it, it won't work because when you decrypt it using their device ID you will can't random nonsense instead of the unlock key (in my examples case that would be "d3tD@#".)!!! -- Mac Address can no longer be accessed as of iOS7+, instead encrypt with other device unique things, such as the date the app was first launched
MAC address code (Just stick it in the view controllers ViewDidAppear... in the .H import )
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
-(void)viewDidAppear:(BOOL)animated {
int mgmtInfoBase[6];
char *msgBuffer = NULL;
NSString *errorFlag = NULL;
size_t length;
// Setup the management Information Base (mib)
mgmtInfoBase[0] = CTL_NET; // Request network subsystem
mgmtInfoBase[1] = AF_ROUTE; // Routing table info
mgmtInfoBase[2] = 0;
mgmtInfoBase[3] = AF_LINK; // Request link layer information
mgmtInfoBase[4] = NET_RT_IFLIST; // Request all configured interfaces
// With all configured interfaces requested, get handle index
if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0)
errorFlag = @"if_nametoindex failure";
// Get the size of the data available (store in len)
else if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0)
errorFlag = @"sysctl mgmtInfoBase failure";
// Alloc memory based on above call
else if ((msgBuffer = malloc(length)) == NULL)
errorFlag = @"buffer allocation failure";
// Get system information, store in buffer
else if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
{
free(msgBuffer);
errorFlag = @"sysctl msgBuffer failure";
}
else
{
// Map msgbuffer to interface message structure
struct if_msghdr *interfaceMsgStruct = (struct if_msghdr *) msgBuffer;
// Map to link-level socket structure
struct sockaddr_dl *socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);
// Copy link layer address data in socket structure to an array
unsigned char macAddress[6];
memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);
// Read from char array into a string object, into traditional Mac address format
NSString *macAddressString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
macAddress[0], macAddress[1], macAddress[2], macAddress[3], macAddress[4], macAddress[5]];
NSLog(@"Mac Address: %@", macAddressString);
// Release the buffer memory
free(msgBuffer);
//return macAddressString;
NSLog(@"MAC: %@", macAddressString);
//F0:DC:E2:1D:EB:50
}
// Error...
NSLog(@"Error: %@", errorFlag);
}
Note: I got the MAC address code from a friend... I'm not claiming that I wrote the code... I don't know if he wrote it or got it from someone else as well.