Copy Protection with License Codes

Maybe you didn’t expect the term “copy protection” here. The term is closely related to Digital Rights Management (DRM) which has gained a very bad reputation on the internet. From my experience, it seems most developers (or “hackers”, as some still call themselves in the tradition of Eric S. Raymond) loathe the notion of copy protection in general. In its most general form, the sentiment states that information should be free, music should be free, video and games and code, too. And when you absolutely have to pay to obtain it, then nobody should hinder you from storing and sharing the data as you like, they say. That’s where most people think the music industry screwed up, and why some people prefer to buy games on GOG.com (no DRM) instead of Steam (has DRM).

I can get behind the latter easily: when you buy something, you should be able to use it for as long as humanly possible. That’s why I have qualms with most, but not all, subscription-based business models. You can find my take on the topic in the appendix.

So that’s what we’re aiming for: some hurdle to force users to pay once for using your application. It sounds harsh, but yes, it’s about forcing people to pay. You could give your app away for free and add a tip jar if you need money, after all. But the business model of paying to unlock features is gating users from having their computer execute parts of the binary application that is already stored on their computer. It’s very artificial, if you think of it. Thankfully, it’s a simple exchange, and people generally seem to understand it very well: you give money and get software. Regular folks compare this to buying groceries, which is technically not the same, but their frame of mind is what really counts here.

Before we dive into the technical implementation of making sure all the people one day either buy a license or stop using your app, we’ll start with some general explanations of the process.

Terms Used Throughout This Book

We’ll be talking about “keys” and “codes” a lot. To prevent confusion, I want to introduce a couple of important technical terms.

FastSpring
That’s your e-commerce solution. It’s your storefront and product management system. It is also the hub of your own little customer support center where order details are stored. You’ll be the person in charge when people request refunds, so you need access to all orders quickly.
CocoaFob
A set of algorithms, available as Open Source scripts, to generate and verify license codes. It’s supported by FastSpring and very easy to implement.
Source is available at: https://github.com/glebd/cocoafob
Public Key
OpenSSL-generated random number used for 3rd parties to verify the data comes from you. Used for e-mail to tell recipients it was really you who sent the mail. Used for license code verification in our case.
Private Key
OpenSSL-generated random number you have to, well, keep private. It’s needed to create and sign the license key data. Should be kept private because you can infer the public key from it.3 However, we’re going to need to give it to FastSpring for them to generate license codes. So please don’t re-use this private key for anything else. We’ll discuss the details in the upcoming chapter.
License Code
Also called “registration code”, this is the string of characters your customers will receive after they buy your app.
CocoaFob-generated license codes should look familiar if you ever bought a Mac app outside the App Store. They tend to look like this, broken into multiple lines for this page’s layout:
GAWQE-FCUGU-7Z5JE-WEVRA-PSGEQ-Y25KX-9ZJQQ-GJTQC-
CUAJL-ATBR9-WV887-8KAJM-QK7DT-EZHXJ-CR99C-A
Licensee
Also called “license name” or “registration name”, this is the name of your customer your app is licensed to. We will set up license code generation to be based on the customer’s name, but you can omit this information from the process or use company names if that better suits your business. We’ll talk about your options later.
License Code Verification
Also called “activation”, this is the process where the user enters a license code and the app unlocks itself or additional features if the code is valid.
This is the part you have to add to your app, where you use the public key to decrypt the license code and test the extracted information for matches. We’ll discuss the implementation in Chapter 2.

Licensing Is All About a Big State Change

The whole topic of protecting access to features of your application unless people pay for it can be boiled down to handling a transition of your app from “unactivated” state to “activated” state.

If you want, you could have a global variable in your code called appIsUnlocked and set it to true upon activation. We’ll be using a more sophisticated approach, but in the end, a single boolean value is a very good representation already.

To manage the state change in a clean way, and since it’s a very important part to get right, it pays off to implement all this as expressively as possible. You don’t want to guess when and why your app is locking and unlocking itself in two years from now. We’ll try our best to avoid creating tomorrow’s legacy code when we implement the activation process.

Think about a license code-activated application with a 30 day time-based trial. During the trial, users should have access to the full feature set. After the trial has ended, some or all features should be inaccessible unless the user enters a valid license code. In some sense, the activated app is identical to the app in trial mode, only without a clock ticking. How do you represent this?

The state the app is in is determined at least during app launch. Changes can happen during the app’s runtime when the trial period is up or the user enters a license code. The app has to represent its current state and its transitions.

With Swift, it’s trivial to represent the state of an app that has to be activated at first launch as an enum with an associated value for the details:

1 enum Licensing {
2     case registered(License)
3     case unregistered
4 }

It only gets a bit more complex if you want to support a time-based trial:

1 enum Licensing {
2     case registered(License)
3     case trial(TrialPeriod)
4     case trialExpired
5 }

The associated License type is based on license code and licensee name for the sample apps of this book:

1 struct License {
2     let name: String
3     let licenseCode: String
4 }

And the TrialPeriod type can be equally simple:

1 struct TrialPeriod {
2     let startDate: Date
3     let endDate: Date
4 }

That’s the foundation of everything we’re going to do: to give the application a means to find out which state it’s in at each moment, and to handle transitions. This is a first representation of the technical terms from the last section in code.

You could capture different details in your License, like a company name, an expiration date, or whatever else you like. For the sake of this book, we’ll stick to the very common combination of license code and licensee name.

Here’s a rehash of the battle plan for the next chapters in case you missed it in the intro:

We will start with setting up the app in your FastSpring dashboard. Then we’ll implement a simple license check in the app’s startup routine which determines if the app is allowed to run, or if the user only sees the dialog to enter license details. In the final chapter, we’re going to add a trial mode to enable users to test drive our software before they decide to buy.