Question

I have a woocommerce store with a plugin which generates license keys.

The idea is that the user of my app, will enter a license key which will be checked against a server. If it is correct then the app will create a special file/persistent flag some how.

Once activated, the user can reset the device or whatever and the app will simply check to see if this persistent file/flag is there.

My questions are:

  1. Is there a library available specifically for this sort of thing?
  2. If not, what is the best/standard way of doing this so the file can't be copied to another device to fake an activation?
  3. Could I use something untouchable inside the application bundle that isn't a file to do this?

Thanks guys, some guidance or suggestions would be great.

Was it helpful?

Solution

The "standard" way to do it is to have Apple manage the licensing for you via in-app purchasing or subscriptions, they provide a secure implementation for checking if something is paid for, but this may not be an option for you.

If you need to roll it yourself, you need to use assymetric encryption, with a private key on a server that nobody can access (except you) and a public key distributed in the app. You also need the [UIDevice currentDevice].identifierForVendor.UUIDString value on the device, which is a value unique to that device which cannot be changed by the user (unless they jail break).

The server encrypts some data like 2014-03-23,purchased-three-month-license,<device-identifier-for-vendor>,<long-random-number> and gives the encrypted data to the device as the license key.

The device has the public key, and uses it to decrypt the license key. Then it checks the result to see if the date is in the last three months, the device identifier matches the device's actual identifier, and verifies that the long random number is there and at least 10 digits or something (it doesn't matter what the random number is, it just needs to be there).

Anybody who jail breaks their device will still be able to bypass your security. There is no way to prevent this. But it will take the user a lot of work, they'll probably just pay instead.

All the libraries you need for the encryption are built in, but they're low level APIs and a bit complicated to use and it's easy to screw it up. I recommend RNCryptor as a high level wrapper around them.

Also note that if the user uninstalls your app, then re-installs it (or sometimes when Xcode installs a new build) the identifierForVendor will change to a new value. Apple enforces this to protect user privacy, there's no way around it. You will need to have the server re-generate a new license key based on the new identifier... perhaps by asking the user to enter an email address and password. You can prevent piracy by monitoring how many times a particular email address is used. If they generate license keys 5 times in 30 days, then you could flag them as a pirate.

Whatever license key the "woocommerce store plugin" is generating will not work, because it won't be using [UIDevice currentDevice].identifierForVendor.UUIDString as part of the license key generation. Without that value, it's going to be trivial for anybody to pirate your software.

There is no such thing as "something untouchable inside the application bundle". The only such thing is the Secure Enclave in Apple's hardware. And to protect user privacy app developers are not allowed to use it directly. identifierForVendor is the only option.

In older versions of iOS there were more options, but they were abused by advertising companies tracking Apple's customers, and so one by one Apple has blocked access over the years.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top