I'm working on an iOS app, but if there is an answer here, it may apply to other platforms as well.
There are basically two ways to validate an in-app purchase: locally and server-side. The server side method is documented here. (I can't find the docs for the local method at the moment.)
Let's say I validate the purchase server-side. My question is about what happens after that, to enable the purchased feature(s). I don't see documentation on this. Am I missing it?
I imagine two or three steps:
Server sends an HTTPS response to the iOS app, saying "yes, you made X purchase".
The app flips some boolean variable in memory to enable the purchased features.
[Maybe] The app saves this state to local storage so that it doesn't need to revalidate the receipt via the internet every time it launches.
All of these steps seem vulnerable to attack on a hacked/jailbroken client device. Obviously there are tradeoffs between the difficulty of hacking and the cost of the in-app purchase and potential lost revenue. I'm thinking about the case where the app is more expensive or popular and there may be incentive to hack it.
Example possible vulnerabilities: (again, all of these probably require a helpful - to the hacker - OS kernel)
a real server response could be sniffed and inspected and then faked for other users
the app's memory could be inspected and the boolean variable flipped
if the state is saved (for example, in a file, or in the user defaults key-value store) that state could be altered
So, are there some techniques to mitigate or prevent these hacks? Or do companies simply accept that a determined hacker can steal software, and take it as part of the cost of doing business?
Don't know if there is a "correct" answer here since you outlined it pretty well:
Obviously there are tradeoffs between the difficulty of hacking and the cost of the in-app purchase and potential lost revenue.
If there was an official way of handling this then it does just become a target for hacking.
Most apps I've seen (even large ones) are keeping data in local storage to determine purchase status. But... you can keep this data on a short cache and refresh it in the background every 5 min or so. That way a hacker would need to overwrite it every 5min which makes normal usage pretty impractical.
Unless you have a high cost of supporting users (e.g. Spotify paying licensing costs) then there's probably better areas to invest in than this.
Health related data for a user is a privacy thing and its need to be very secure i.e. it needs to be stored in secure place. For example, while I was watching Apple's official video on Finger print unlock, they told that finger print data is stored at place where it is impossible to hack. So, for a curiosity, I have a question in mind that where these data are securely stored?
I have had a look at this link from Apple Documentation but could not found the information on it. One thing I have figured out is that data are encrypted and stored but where?
Does anyone has idea on the same?
Apple describes the security attributes of various iOS features in this document. To quote:
This data is stored in Data Protection class Protected Unless Open.
Access to the data is relinquished 10 minutes after device locks, and
data becomes accessible the next time user enters their passcode or
uses Touch ID or Face ID to unlock the device.
Read the "Encryption and Data Protection" section of the document to learn more about Data Protection. Any app can use the "Protected Unless Open" data protection class for its persistent data.
As you already know, NSUserDefaults is simple and effective for saving small, simple bits of data, like NSNumbers or NSStrings, to your device’s file system. But this data is in no way stored securely as hackers can access it pretty easily from the device.
You have figured out that sensitive data are encrypted. But you need to find the answer where it need to be stored. The Answer is:
Keychain Services:Apple has provided the Keychain Services API to deal with this problem and help developers build apps that safely handle passwords and other sensitive information.
Now the question might rase why?? and the answer is:
Keychain is great because data encryption automatically is taken care of before it is stored in the file system so there is no need to waste time building encryption algorithms.
You can go through this link for better explanation.
https://developer.apple.com/documentation/security/keychain_services
I am so happy that I get an ID per device, so I can keep data per user anonymously with firebase! The only thing that could be better is if I could get an id per user's iCloud storage for the app.
I understand that how the authentication token is maintained per app, at least on the web, is that it is stored in local storage. It implies that a similar approach is being used per app in iOS in something like UserDefaults. I'm hoping there's an easy way to keep it instead in NSUbiquitousKeyValueStore.
edit with use case:
I have an app that is (with permission) capturing and anonymously collecting location data. I would like to have that data stored per user rather than per device, and I essentially can't use signed logins.
(actually, the reality is that I am not capturing that in firestore, I am capturing accompanying metric data from other apps designed to work with this one)
So "why anonymous?", right? I am collecting time series data for third party apps - this presents risk of "use" to the user, and loss of control for that same data for the subscriber apps using the service I am writing.
Honestly, at a later point in time this might be converted to a library that allows apps to swarm their information together instead. But there are overhead concerns, and difficulty in trust for sharing data, with that approach and for my research project that approach is further from topic.
I know Apple will reject apps that backup data that can be reloaded from the app bundle. However, in the app I'm working on, we'll be providing some basic data that users will want to keep in the Core Data store along with the new data they have created and entered. So, users will use the "library" data we provide by integrating it with their own data as they work with the app.
My concern is whether Apple will require me to segregate these data in some way such that data from the bundle is not backed up to iCloud? Once the data are co-mingled, disaggregation would be complex and burden the app excessively.
So, my question is whether I have to concern myself with the co-mingling of user data with that data which is supplied in the app bundle?
TIA for any input on this as I've not found anything about it in the docs.
I had a similar situation in my app. It has sample data, but the sample data is designed to be edited by the user, and has metadata attached to it that is user specific. In other words, the data is mutable, and belonged with the rest of the user's personally created data.
At one point, the app was rejected. I first appealed to the reviewer, explaining that the data was mutable, and personal to the user — it would not be possible to reproduce the data purely from the app bundle. The reviewer would not budge, so I appealed, and they sided with the reviewer. Game over.
You may be able to get away with a small amount of data loaded from your bundle (<1MB). If you plan to include images or anything that will push up that amount, they will likely reject you.
I also heard from another developer rejected for including data downloaded from a web service in the user's store. Apple claimed that the data could be re-downloaded, which may be partially true, but ignores the fact that the web service was operated by a third party, and the downloaded data could be unshared at any time. It also ignores that the user can edit the downloaded data, and that the client app is attaching user-specific metadata that cannot be downloaded.
That developer was rejected as well. He eventually got the app through review by introducing a complex set of procedures to import the data: the user had to first download the data to a temporary holding area that was not backed up. They then had to explicitly import the data, and dismiss a wordy dialog warning that the imported data would contribute to their iCloud backup quota. Horrible. But that is apparently what Apple wants.
The rule is pretty mindless, in my view, and Apple seem to be completely oblivious to the implications in terms of user interface changes and drastic refactoring of an app's model. I can't imagine any engineers were involved in forming the rule, because they surely would have realized how much unnecessary complexity it would impose on developers. We can only hope they see reason at some point.
How can I make a 30-day trial for my application? I need to allow users to use an application only 30 days. How to count these days?
I keep the first and the last date in registry. But if to change a system time - no protection will be. I need to count these 30 days.
You could probably come up with a system that requires an internet connection, but without something that the user can't tamper with, I don't see a solution.
Any solutions that rely on an untrusted element (an element of the protection that is under the user's control) is critically weak.
The simplest way I can think of to protect against the user moving the clock back is to limit the total number of launches.
However, attempts to limit the number of launches requires persistence -- saving data to the disk, perhaps encrypting and storing a modified version of your activation data file -
Imagine that you count one of the 30 days as "used up" once the app has been launched, on a unique occasion, even when the same date is re-used. In order to avoid using up more than 1 "activation time day" when launched, the user must allow your software to re-save its activation file each time it runs.
To block that approach, the user needs only to keep the apparent date from changing, plus they must either prevent you from storing anything to disk; or they can simply track and record your changes and reverse them out, either using a monitoring process, or using VMWare snapshots. About VMWare snapshots, you can do nothing. The virtual machine's disk is not under your control.
You can protect your app of users setting the clock back simply by storing in the registry the date of last execution.
Each time the app is started you need to do the following:
Check current date (as reported by the system clock) against the stored last execution date and, if current date is earlier than the last execution one, consider that the trial period has expired (or whatever you prefer).
If the previous check is ok, save the current date in the registry and continue execution.
As WarrenP says, any technique storing information locally can be easily circumvented using VMware snapshots.
And anyone, including those who check via internet, can be skipped via assembler level hacking.
Here's a discussion on Shareware trial enforcement with Delphi:
Best Shareware lock for Delphi Win32
Along with discussions on various 3rd-party solutions, techniques for DIY, etc..
IMO, DIY is feasible if your app produces data that the user will want to keep around, then you can simply embed a copy of the usage/day counter in the database in such a way that they can't wipe it without destroying their data. I also like watermarking (printing "trial" on reports, etc..), escalating nag severity, but I do not recommend or condone "drop-dead" crippling until WAY past the expiration data. I also like to measure "days of actual use", instead of using a calendar.
Registry manipulation works, and many of the 3rd-party protectors use it. But you need to be stealthy, and keep backups in several locations simultaneously.
You should also consider having separate trial and registered versions. But also consider that pirates will buy the registered version with a stolen card, and put it on Rapidshare, BitTorrent, etc..
Also note that elaborate defenses lead to support headaches. Sometimes PCs crash and the clock gets set backwards. They install new harware. PCs get rebuilt, restored from backup, etc.. If a user is running a debugger, he may be a software developer, not a pirate. If your app looks like it has been patched, it may be an overly-aggressive antivirus. And at any time, a shoddy patch for Windows may cause your program to think that it's being attacked, hacked, or reverse-engineered. You have been warned...
Encrypt a date and store it in registry the best way to do it is that date to be stored by the installer itself and if the date doesn't exist the application should quit.
There is an open source project (which was a commercial product before):
TurboPower OnGuard is a library to create demo versions of your Borland Delphi & C++Builder applications. Create demo versions that are time-limited, feature-limited, limited to a certain number of uses, or limited to a certain # of concurrent network users.
I have not checked which Delphi versions are supported.
For this kind of "protection" and some others, I have used TmxProtector (open source) from MaxComponents in the past with good results. From the link provided:
The TmxProtector is a software protection component. It was designed
for quick implementation of application protection functions. You can
create time-trial and password protected applications. You can set the
maximum number of execution, and it can work with registration keys as
well.
This compoment uses very simple encryption to store the expiration date in the registry and it provides some simple detection for tampering on the system date.
It sounds like you need to store the date the last registry entry was written. Then inside your program, test if the current date is less than the date last registry entry was made. If true display a message that the trial period has expired and the program must be purchased.
Here are some ideas on how to deal with clock changes during the trial period:
Save both the date of first and the date of the last program start. If the date of the last program start is greater than the current date, then the user has moved the clock back. I simply increase a day and save the new date as the date of last start. You can of course decide to just end the trial.
To try to defeat trial bypass programs (RunAsDate for example) which run your application by setting the date and time to a specific value, you can instead of getting the date via the usual Delphi way (Date, Now), get, for example, the last modification date of NTUSER.DAT.
Save your trial data on two separate locations, either two registry locations, or file and registry. This way even if the user deletes one of the trial data locations, you'll still have a backup one to use.
If you keep your trial info in registry, the registry could be deleted by the user. Evey one expects to find the registration info there.
There is one place where the user might not think to look into: your own app (EXE file). Put an ANSI string constant (MUST by ansi/ascii or other 1 byte string, static array, etc) into your program, like 'xyxyxyxyxyxy'. Compile your app. Open your complied app with a hex editor. Search for that string. Now your program could use that area to store the trial info into itself.
Use this method in conjunction with others: store your info in registry also, on disk, etc.
Anyway, the best would be to get the registration info from your server.
The big drawback: 1. The server must be ALWAYS online! 2. The user must be connected to internet (when it uses your app).
Also use a Delphi license management library to help you encrypt the license info and generate a string-based key that you can send to your customers upon registration.
Anyway, whatever you send to your server needs to be based on the hardware fingerprint of that computer. Otherwise your license key will leak out on some warez website and everyone will be able to use that key. But if the key is hardware-based it would be useless if it is leaked on Internet.
Just remember: don't over do it! There is no such thing as unbreakable software protection. Microsoft could not do it!
As the thread pointed to mentioned, I encourage you to look into WinLicense: http://www.oreans.com.
I've been using it for quite some time and it handles trial periods quite well. It also handles licensing, customer lists, etc.
Tom