Chapter 12

Protecting Applet Code

by Mark Wutka


CONTENTS

Protecting Your Code from Unauthorized Use

Although many people put their applets out on the Web for free, you may not want someone else to take your applet and use it on their own Web page. Some people are critical of protective attitudes but it is completely your choice.

You may have put in a lot of hard work and you don't want someone else taking advantage of your work for free. Or you may be developing a commercial applet that your customers will be paying for. They don't want to pay a lot of money only to have a competitor use the same applet for free.

The downloadable aspect of Java makes copyright protection much harder. With traditional software packages, you can protect your software from unauthorized use through authorization keys, license servers, and other means. This doesn't work so well for Java, however, because the people who end up running your applet may not be the people who paid for its development.

If you developed a cool applet for some big corporation's Web page, they probably paid for it. But the people who run the applet are the people who visit the Web page. They have to be able to run the applet unrestricted.

Caution
If you intend to take legal recourse if your code is stolen or misused, be sure to consult a lawyer before making the software available on the Web. Many firms specialize in copyright and intellectual property laws, and can advise you on the best ways to protect yourself.

Embedding Copyrights in Your Code

The first step to take in protecting your code is to embed a copyright statement in your code warning against unauthorized redistribution. Try to make it as plain as possible. Also, put a notice in the source for your Web page.

Note
If you don't want your code misused, make that point very plain. If someone has to go digging through your code or through a lengthy license agreement just to find out that they can't use it, they probably won't take the time to look. They'll use it anyway.
Many people who use others' applets don't steal them intentionally. They just assume that the applets can be reused freely, since so many on the Web can be.

You might include a copyright statement in your code this way:

char copyright = "Copyright (c) 1996 by Mark Wutka - "+
"Unauthorized distribution is forbidden. For questions "+
"about licensing this code, send mail to wutka@netcom.com.";

You should also include a similar copyright on your Web page:

<! Copyright (c) 1996 blah blah blah >

If you want to ensure that the copyright notice has been retained on the Web page, you can turn the copyright into a parameter and make the applet check for it. For example:

<APPLET codebase="." code="VerifyCopyright.class width=200 height=200>
<PARAM name="copyright" value="Copyright (c) 1996 by Mark Wutka - All Rights ÂReserved">

Your applet then checks for the copyright parameter:

import java.applet.*;

public class VerifyCopyright extends Applet
{
     public String copyright = 
          "Copyright (c) 1996 by Mark Wutka - All Rights Reserved";

     public void init()
     {
          String copyrightParam = getParameter("copyright");
          if ((copyrightParam == null) || !copyrightParam.equals(
               copyright)) {
               throw new SecurityException("Invalid Copyright");
          }

     }
}

This doesn't stop someone who's clever enough to change the copyright statement in your code, however. But it does remind someone to include the copyright on their Web page if they use your applet.

Verifying the Origin of the Applet

One very effective way of ensuring that your applet isn't misappropriated accidentally is to check the location from which the applet was loaded. In your init method, call getDocumentBase and check to see that the host name is the host name of your Web page.

If you use a public Web provider, you may also want to check the file name since someone else on your Web provider could be using your applet. The following code fragment verifies the origin of the applet:

public void init()
{
     if (!getDocumentBase().getHost().equals("www.webcom.com")) {
          throw new SecurityException("Unauthorized Applet Use!");
     }

Although this will protect you from someone accidentally using your code without your permission, it does not help when someone intentionally reuses your applet. A code thief could easily disassemble your program and either change the host name in the check, or remove the check completely. To protect yourself against intentional misuse, you can try hiding the security checks in your code.

Hiding Information in Your Applet

If someone wants to hack into your applet to get around your security or figure out one of your complex algorithms, they will. Accept that fact right now and you'll save yourself a lot of disappointment later.

The best you can do is to make it more costly to get around the security than to write the applet in the first place. One of the most popular techniques for doing this is called obfuscation.

Obfuscation is intentional misdirection in your code. It is like encryption except that the code is never decrypted.

Typical forms of obfuscation include meaningless loops, tests, computations, function names that have nothing to do with the function, very long functions that do a lot of unnecessary things or are interspersed with unnecessary things, and strange interactions between variables and functions.

There is a market for good code obfuscators, because obfuscation by hand frequently leads to bigger, slower programs. An ideal obfuscator would make your program terribly confusing while not increasing the size, the speed, or the correctness of the program. Keep your eye out for such obfuscators if you are worried about someone stealing your code.

Note
There is no such thing as security by obscurity. Don't think that you can hide a password in your code without someone figuring it out. Just because you can come up with a function that you wouldn't be able to unravel doesn't mean someone else can't figure it out. You would be amazed at the things people can figure out when deciphering code.
If you need secure transactions, such as banking funds transfers, don't even think about obfuscation. Use a secure, encrypted protocol and a signed applet. This is discussed later in this book.

Obfuscating a Working Program

Although you can't absolutely protect information in your code without some form of encryption, you can make it hard to unravel. In lieu of an object-code obfuscator or an obfuscating compiler, you can use some techniques on your code to make it harder to read.

Tip
Don't try to build obfuscation into your program from the start. It will take you forever to debug. Start with a good, easy-to-read program, get it working, and then start applying obfuscation techniques.

Make All Your Function and Variable Names Meaningless

Variable names like extraShips or maxMissiles are easy targets for someone who wants to hack your game program to make it easier to play. This shouldn't be a concern if the game is a stand-alone game.

If someone wants to cheat, that's their concern. However, if you are writing a networked game or you have a central repository for the high scores of your game, you want to make it harder to cheat.

You can do this by changing all your variable and method names to things like xx1y and zzqb. You can make a simple editing script to go through and change the real names to the obfuscated ones before you compile the release version of your program. You must, however, always keep a real copy available.

No one wants to debug obfuscated source code. Some of us have trouble figuring out why we did something in a plainly readable source file!

Perform Occasional Useless Computations or Loops

If someone is trying to unravel a complex algorithm, you may want to throw garbage into the middle. Just make sure that you aren't killing your applet's performance. When you do useless computations, you might take advantage of various mathematical properties.

For example, shifting a value left 1 bit is the same as multiplying by two. Shifting 1 bit to the right is the same as dividing by 1. You can multiply a number by any value using a combination of adds and bit shifts.

Suppose you want to multiply a number by 12. Find all the powers of 2 that add together to make 12-in this case, 4 and 8. Every number will have exactly one combination like this. Now, to multiply a number by 4, you shift it left 2 bits. To multiply by 8, you shift it left by 3 bits. Thus, x * 12 can be written as (x << 3) + (x << 2).

To use this for obfuscation, take the simple equation

int c = a + b;

You can rewrite b as (13*b)-(12*b), then replace the 12*b with some bit shifts, leading to:

int c = a + (13*b) - (b << 4) - (b << 2);

You can also use the principle that the sum of the numbers between 0 and n (including n) is n * (n + 1) / 2. The following example illustrates how this might add to the confusion:

int sum = 0;
for (int i=0; i<= n; i++) {
	sum += i * n;
}
sum /= (n * (n + 1)) >> 1;

Would you have guessed that this is the equivalent of the following statement:

int sum = n;

Remember that this kind of obfuscation increases the size of your code and makes it slower. Don't add loops like this when you have to do the computation many times.

Hide Small Numbers in Strings

Suppose you have written a shoot-em-up space game in which each player gets five ships. No matter how you change your variables, if users see something like

static int fdkj = 5;

they are going to try to change that value and see if it changes the number of ships. For small values, you can hide the values inside strings. For example, you might have a string like

static String alert = "Exception in computation.";

which looks like an unobfuscated error message. The letter 'E' has an ASCII value of 69, meaning that you can use 'E' - 64 as the number of ships:

int ships = alert.charAt(0) - (1 << 6); // ('E' - 64 or 5)

Of course, you would obscure the variable name of ships.

Create Large Methods

This may be one of the hardest parts of code obfuscation since you tend to create a lot of small, specialized methods. If someone is trying to unravel your code, they may pick one method at a time, figure out what it does, then assign it a meaningful name wherever it is used.

You can discourage this by "unrolling" your methods where they are called. In other words, take the code that is in the method and insert it in place of the method call. For example, if you originally had the following method:

public int computeAverage(int values[])
{
     int sum = 0;
     for (int i=0; i < values.length; i++) {
          sum += values[i];
     }
     return sum / values.length;
} 

You would replace every occurrence of the call to computeAverage with the code from the method, preferably with an obfuscated name for the sum variable.

Spread Methods Out Among Subclasses

Rather than grouping all your methods into one object, you can split the object using inheritance and implement methods in different classes. This makes it much harder to find a particular method when you are trying to trace the code. As with several other obfuscation methods, this tends to slow the code down and uses up more memory, since the runtime must now keep track of several classes.

Note
The problem of code obfuscation is a hot topic. It has been rumored that Sun may start building an obfuscator into the Java compiler that ships with the Java Development Kit. This has yet to come about, however.

Using a Commercial Obfuscator

There was a flurry of debate on the Internet after the introduction of a very successful Java decompiler called Mocha. It was able to take a .class file and turn it into a very readable Java source file. It didn't always reproduce the original source code exactly, and comments were missing, of course, but the program worked well enough to cause great concern among Java developers.

You can try Mocha for yourself. It is available for free at http://web.inter.nl.net/users/H.P.van.Vliet/mocha.htm. Keep in mind, however, that many source code licenses, including those from Sun, prohibit you from decompiling or disassembling any of their code. The purpose of such a restriction is usually to prevent code theft. Many times, a company won't mind if you are doing the disassembly just to find out how something works or even to fix a crucial bug.

While Mocha was causing a storm in the Java community, its author was busy working on the counterpart to Mocha, which is called Crema. The Crema program is a code obfuscator, and does a very good job at jumbling up a .class file. Unlike Mocha, Crema is not free, but you can download it for evaluation purposes. The Crema Web page is located at http://web.inter.nl.net/users/H.P.van.Vliet/crema.html. Obfuscating your code may be a very tough thing for you to do. Hopefully you won't have to do it very often. After all, the Internet fosters a spirit of information sharing, not hiding.