NOTE ---- The answer below uses iOS6 methods, Apple has since removed the developer access to the MAC addresses. If you are developing the first response of iOS7 + disregaurd and simply encrypt your IAP unlock data based on other variables that will be unique for each device (for example, from the date the application was first launched)
I have functions that need tonal unlocking, so I store them in my plist files ... a function, such as a new chat avatar, can have the identifier "13891", and if it is unlocked, I can assign it several keys for example , "93", and if it is locked, it can have any other key "37", for example .... So plist will say: "13891" = "93" My question is whether jailbroken phones can easily edit plist files and unlock features for yourself? What is the best way to store this data? I do not want to check Apple servers every time, it takes too much time with a low Internet connection.
Edit: current answer:
4 measures to take:
1) Store it in the keychain. (Or plist, I think, now I have added measure No. 4)
2) Check Apple servers every time, but if you are concerned about the backlog that follows, just check it in the background and thereby let the user use the application if he says he can.
3) Store the variables as encrypted keys in the keychain ... do not store "FishingRod = unlocked" store "3dhk34D @ HT% = d3tD @ #".
4) Encrypt each key with the MAC address of the device (these MAC addresses are NOT changed and are available with or without WiFi ... below). Thus, if a user downloads a layer from the Internet and tries to use it, it will not work, because when you decrypt it using your device identifier, you will not be able to use random nonsense instead of the unlock key (in my example, for example, " d3tD @ # ".) !!! - The Mac address can no longer be accessed with iOS7 +, instead it is encrypted with other unique things on the device, such as the date the application was first launched
MAC address code (just paste it into ViewDidAppear ... view controllers in .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 received the MAC address code from a friend ... I do not claim to have written the code ... I do not know if he wrote it or received it from someone else.