XNA Secure Unlock System

By on 7/7/2008

A recent forum thread unearthed a great idea by Jon Watte
To generate revenue, you could have an unlock mechanism, where someone pays you money and gets an unlock code. The unlock code would be some hash of their gamer tag and a key, and the game would know whether it's right or not. Because it's a hash, you can't use the same unlock code for two different gamer tags. Just beware that if you're not selling anything tangible, you should budget 10-20% of your revenue to credit card charge-backs and fraud.
I got curious on what it would take for such a solution to be implemented.  The first thing that occurred to me is that there would be two components to this feature.  One would be the in-game unlock mechanism, while the other is the external component that would more-than-likely be implemented as a website.

Sample Code: http://codecube.net/bloguploads/UnlockCodes.zip



In-Game Implementation

You might initially think that the in-game implementation would be rather simple through the use of the .NET framework's powerful cryptography namespace.  But alas, if you plan on targeting the XBox 360 or Zune platforms, you will quickly find yourself disappointed.  That namespace is not available on the Compact Framework.

Thankfully, the compact framework has been around longer than XNA ... and so others have had the need, and subsequently implemented the solution for this problem: http://www.flowgroup.fr/en/kb/technical/md5.aspx

From the fine folks at FlowGroup:
The cryptography classes are not available on the Compact Framework 1.0, so we ported the "MD5 Message-Digest Algorithm" from RSA Data Security, Inc. in C#.
With the ability to generate hashes on the compact framework, we can then focus on how we can implement our secure unlock mechanism.  Using three values:
  • Developer Secret: this is a string that is known only to the developer.
  • User Secret: this is something known only to the user.
  • GamerTag: The user's gamertag.  He must be logged in with this gamertag in order to use the code.
This technique is so simple you'll kick yourself for not having thought of it.  Taking the three values, simply concatenate them, and then compute the hash using the resulting string.  This provides a very secure way of providing personalized unlock codes.

Even if there were users that wanted to subvert your mechanism and share codes, it would not work.  Let's say a user with a GamerTag of SxyLvr decides he wants to post his unlock code to the world.  No one else would be able to use it because they would have to be signed in with SxyLvr in order for it to work.

Users will similarly be unable to create codes on their own because they are unlikely to know the developer secret.  That is something that will be known only on the server, and in your game code.  Of course, if you are distributing a windows game, then it can easily be decompiled ... but on windows you are free to use more traditional data security techniques; and of course on the xbox (via community games), the user is unable to get access to your binaries

With this in place, we are able to create a simple class that has the following interface:

public class UnlockCodeProvider {     public UnlockCodeProvider(string developerSecret, string gamerTag);            public string ComputeCode(string userSecret);

    public bool Validate(string userSecret, string codeToValidate); }

I won't go into the implementation as you can just download the sample code.  But this very simple class can be instantiated by supplying the developer secret, and the gamertag that we are working with.  The two methods allow you to compute a code using the supplied user secret (ComputeCode), while the other one allows you to validate that a code the user supplied is valid (Validate).

This class, and a dreadfully simple "game" shell can be found in the sample download at the top of this post.  This sample shows how to ask the user to log in, get his gamertag; then ask him for the user secret and code he received from the server. 

Once the user supplies this information, the game will validate the code against a locally computed hash.

Server Implementation

The server-side in this equation gives you many many options to choose from.  As mentioned before, this will more than likely be a web application that the developer controls.  The purpose of these unlock codes can be many; for example the developer could charge money for certain cards in a collectible card game.  Or the most active contributors in the developer's favorite community can be given codes as a reward.

Whatever the reasoning, the server can be used to generate unlock codes that can subsequently be used in-game to unlock whatever.

ASP.NET

I chose ASP.NET for several reasons ... I write C# code all day, and thus I am proficient in it.  This also allows me to re-use the exact same UnlockCodeProvider API that the in-game implementation uses. 

I threw together a painfully simple ASP.NET GUI that uses simple web forms (postbacks, et al)

unlock_server_gui

As with the in-game code, this can be found in the sample code found at the top of this article.

PHP

I wanted to write a reference implementation in PHP to illustrate the fact that the server-side implementation isn't limited to requiring ASP.NET.  You can use any technology that you are familiar with and/or already have infrastructure for.  PHP seems to be a common choice because hosting is so cheap these days.

Unfortunately, due to time constraints, this feature got cut ... so I'll leave it as a user exercise.  I assume though that anyone that's even modestly familiar with PHP can whip this up in about 30 seconds using the hash function :-)

http://us.php.net/manual/en/function.hash.php

Legality?

Of course, there are certain interpretations of the EULA that suggest this may not be a legal move for XBox games (ie. to sell unlock codes).  According to the ZMan:
I had the same idea but then I wondered how Microsoft would feel not getting a share of the millions I would be sure to make... Shame the EULA Forbids it right now ...

b. Programs developed for the Xbox 360 Platform i. Personal Use.  Use of any programs developed for the Xbox platform using the software is restricted to your personal, non-commercial use. 
That doesn't mean the idea is dead in the water.  You could always give unlock codes in return for email addresses (that you could then use to notify of your next game).  Or you could give them away for registering on your community site ... or really, anything. 

The world doesn't have to revolve around commercial aims just because Adam Smith says so :-)

See more in the archives