Issue 57 * September 26 2008

How to Make a Registration Scheme
An overview of concepts and principles

by Mark Schonewille

A question that pops up very often is how to make a good registration scheme. This is a problematic issue, because developers usually don't share this trade secret. I will show how to create a very simple registration scheme. The system described in this article is very simple and aims at making the concept understandable rather than presenting you with a ready-made solution. You will want to experiment with variations on my approach, to make it more complex and reliable.

The essence of a simple registration scheme is a code that is checked by the software. If the code is correct, the user gets unlimited access to all features of the software. If the code is incorrect or if no code has been entered, the user will have limited or no access.

Let's assume that your customer wants to buy a license for your software. He sends you an e-mail with a request, pays by bank, cash, or on-line, and eventually you will send an e-mail with a license. You need to generate the license on your computer while the software installed on the user's computer will need to validate the license key.

First, we will generate a license code that includes the date and the version number of the software. This allows you to issue license codes that work with all past and current versions of your software, but not with future versions. If you want the license to be valid for future versions of the software as well, you can replace the version number with an arbitrary number, which changes only once in a while.

I start my script for generating the license key with defining two constants. The constant dot is just for readability purposes and because dot types more quickly than "." (quote-period-quote). We assume that you are releasing version 1.0.0 of your software.

constant dot = "."
constant kVersion = "1.0.0" 

Next follows a function licenseKey. The first line of this function takes the time in milliseconds and converts the last 8 characters of the milliseconds to a hexadecimal number. We use the baseConvert function to obtain the hexadecimal number.

function licenseKey
   put baseConvert(char 2 to -1 of the millisecs,10,16) into myDate 

The next step is to take the version number and convert it to another hexadecimal number. For this, we first need to set the item delimiter to dot. Once we consider the version number as three items, we can multiply each item by an appropriate factor and add up the results. Note that this approach assumes that the version number is anything between 0.0.0 and 99.99.99. Once we have converted the version number to a big number, we convert it to a hexadecimal code, again using the baseConvert function.

set the itemDel to dot
put item 1 of kVersion * 10000 + item 2 of \
kVersion * 100 + item 3 of kVersion into myVersion
put baseConvert(myVersion,10,16) into myVersion

Each license scheme needs something unique. The unique part of the algorithm makes sure that only specific sequences of characters and numbers can be used to unlock the software. How you do this isn't very important. You could use a highly sophisticated encryption algorithm, but we will keep it simple. Our license key identifying function takes the two components we already have, mixes them up, and returns a new number. The function is shown here, without further comments, because every license scheme should have its own function.


function licenseIdentifier theNr
   put true into mySwitch
   repeat for each char myChar in theNr
      if myChar is "Q" then next repeat
      put value("0x" & myChar) into myNr
      if mySwitch then add myNr to myIdentifier1
      else add myNr to myIdentifier2
   end repeat
   put char -3 to -1 of (myIdentifier1*2-myIdentifier2) \
   into myIdentifier
   if myIdentifier > 255 then put 999 - myIdentifier \
   into myIdentifier
   return baseConvert(myIdentifier,10,16)
end licenseIdentifier

The licenseIdentifier function is called by the licenseKey function.

put licenseIdentifier(myDate & myVersion) into myIdentifier 

Now we can put the three components together. Since hexadecimal numbers only contain characters 0, 1, 2,... 9, A, B, ...F, we can safely use any character between H and Z as special item delimiters for our three components. Here, we use Q and X as delimiters.

return myDate & "Q" & myVersion & "X" & myIdentifier
end licenseKey

Below follows the entire licenseKey function one more time.

function licenseKey
   put baseConvert(char 2 to -1 of the millisecs,10,16) into \
   myDate
   set the itemDel to dot
   put item 1 of kVersion * 10000 + item 2 of \
   kVersion * 100 + item 3 of kVersion into myVersion
   put baseConvert(myVersion,10,16) into myVersion
   put licenseIdentifier(myDate & myVersion) into myIdentifier
   return myDate & "Q" & myVersion & "X" & myIdentifier
end licenseKey

We can call this function in any way we want, e.g. from the message box or a button. If we want to call the function from a button, we create a button with the following script:

on mouseUp
   put licenseKey() into fld 1
end mouseUp

This mouseUp handler puts a license key into a text field.

Please note: if a user figures out what the parts of the license key represent and finds out that this license key needs to contain a Q and an X at a specific position, the user might try to type a random number and make a guess about the last component. If the user also understands that the last component consists of 2 characters, the user will have a probability of 0.004 to guess correctly! Therefore, use this script for demo purposes only.

Now that we have the scripts to generate a license key, we need to write the scripts to validate the license. These are the scripts that will be built into the software.

As one of many defence mechanisms, we don't want the distributed software to contain all scripts that are needed to create the license key. So, although you might use the date as well to check the validity of the license, we will not do so in this example. Instead, just take the license key and use the licenseIdentifier function to validate it. Again, we keep it as simple as possible.

First, we need to take the first two components of the license key. We make X the item delimiter and take the first item of the license key, which contains the date component and the version number components.

function validateLicense theKey
   set the itemDel to "X"
   put item 1 of theKey into myNumber

The variable myNumber now contains the first two components, separated by character Q. We call the licenseIdentifier function to calculate the last components. The licenseIdentifier function is identical to the one used to generate the license key.

put licenseIdentifier(myNumber) into myIdentifier 

Now all we need is to compare the value in myIdentifier to the value of the last component of the license key.

put (last item of theKey is myIdentifier) into myValid 

If myValid contains true, then the license key is correct. Otherwise, it is incorrect. The last line of the validateLicense function returns true or false.

return myValid
end validateLicense

Here is the validateLicense function one more time in its entirety.

function validateLicense theKey
   set the itemDel to "X"
   put item 1 of theKey into myNumber
   put licenseIdentifier(myNumber)  into myIdentifier
   put (last item of theKey is myIdentifier) into myValid
   return myValid
end validateLicense

If you want, you could modify the validateLicense function to include an explicit date and version check. For example, you can convert the date component back to milliseconds and check that the date is within an acceptable range. Additionally, you can check that the version number component can be calculated from the actual version number of your programme. Obviously, you can add more components to the license key and have the validateLicense function check them.

Next time, we will build a simple interface, which will allow the user to enter the license key and validate it. If the license key is correct, we will save the necessary information in a preferences file for use in the next session.

The scripts presented in this article are, with slight modifications, sufficient for hobbyists to add to their own, small shareware projects. If you want to secure a large commercial project, I highly recommend hiring a pro who knows all the peculiarities of protecting your hard work. A professional knows how to make the scripts sufficiently complex, how to hide the scripts from prying eyes, and how to tie a license key with a user name, e-mail address and hardware. If you have any questions about this article, you can send them to m.schonewille@economy-x-talk.com. Many thanks to Malte Brill for his comments.


Main Menu What's New