BUY IT!
Securing Java

Previous Page
Previous Page
How to Sign Java Code
CHAPTER SECTIONS: 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8

Section 4 -- Signing Code with Sun's JDK 1.1.x

Next Page
Next Page

Sun makes its own set of signing tools. The tools have evolved along with the JDK. We'll briefly cover both the JDK 1.1 tools and the Java 2 tools.

The JDK ships with a command-line tool called javakey. Its job is to manage a database of entities (people, companies, etc.) and their public/private keys and certificates. It is also supposed to generate and verify signatures for archive files; however, verification is not implemented as of JDK 1.1.7.

As Chapter 3 describes, an applet contained within a digitally signed JAR file is allowed to leave the bounds of the Java sandbox under certain circumstances. In JDK 1.1, if a JAR is signed and the user who has browsed to the Web site containing the applet has a policy stating that he or she trusts the person who signed the JAR, the applet can do anything at all that Java code is capable of. For example, it can read and write from the file system, start another process running on the computer (outside of the browser), open a network connection to an arbitrary machine, or myriad other tasks that applets are not normally allowed to do. In other words, trusted signed code under JDK 1.1 is as powerful as Java application code from the JDK 1.0.2 days. Remember, under JDK 1.1, we're operating under a black-and-white security model.

To get going with code signing in JDK 1.1, there are few things to gather. On the development side, an applet that tries to perform actions that aren't normally allowed by the Java sandbox is needed (or at least one that can be augmented to attempt such an action). The most rudimentary operation that a signed applet can do that an unsigned applet can't do is read the user.name System property. An example applet follows:

public class UserApplet extends java.applet.Applet {
 public void init() {
 String username = "user: ";
 try {
 username += System.getProperty("user.name");
 } catch (SecurityException se) {
 username += "cannot read";
 }
 showStatus(username);
 }
}

A signed applet containing the preceding code (running in a browser of a user who trusts the entity that signed the applet) will be able retrieve the name of the user running the applet and display it in the status bar of the browser.

Once the applet to be signed and its containing Web page have been created, the class files that contain the applet must be put into a JAR file. Even if the applet in question is only one class, it must be placed inside a JAR file. It is not possible to sign standalone class files.

In order to sign Java code with javakey, a signing certificate needs to be created. Once this certificate is created, it can be used to sign the JAR file and distributed to users who wish to allow the signer's applet full access to their system.


Creating a Signing Certificate

A file called identitydb.obj stores all certificate information and lives in the directory specified by the Java System Property value user.home. For Unix Java users, this value evaluates to $HOME. For Win32 users, user.home can take a number of values. Different VMs assign the value of user.home either to the USERPROFILE directory, to the HOMEDRIVE\HOMEPATH directory, or when all else fails, to the value of the java.home System Property. To clear up any ambiguity, write and run a simple Java containing the line:

System.out.println("user.home= " + System.getProperty("user.home"));

Regardless of user.home, the location of identitydb.obj can be set explicitly by adding an identity.database entry to the java.security file that lives in the lib subdirectory of the java installation, wherever that may be on the system.

First, the signer's identity must be created in the database. To create an identity, signername, that will be able to sign objects, run the following command on the command line:

javakey cs signername true

Now that a signer has been created, that signer's public and private keys must be initialized. Keys can be between 512- and 1024-bits long. To initialize public and private keys for a signer, run the following command (where # is a number between 512 and 1024):

javakey gk signername DSA #

Higher numbers mean more security. We recommend always using 1024-bit keys. The parameter DSA signifies the algorithm used to generate the keys. The JDK only comes with the DSA algorithm by default.

To verify that all has gone well so far, run:

javakey ld

This command will list all the information in the current identity database. The entry for signername should identify it as a trusted signer as well as noting that the public and private keys have been initialized. The next step generates a certificate that will be valid for signing JAR files. This is different from Netscape Object Signing in that there is no Certificate Authority involved.

First, a directives file must be created. The directives file is a Java Properties file that provides values used during certificate generation. Here are the contents of an example directives file:

 issuer.name=signername
 subject.name=signername
 subject.real.name=Sol S. Signer
 subject.country=US
 subject.org=Signing Corp
 subject.org.unit=Development
 start.date=22 Jul 1998
 end.date=16 Aug 1999
 serial.number=41

To generate the certificate once the directives file exists, run:

javakey gc directivesfile

To verify that the certificate was generated properly, run:

javakey ld

Look for the signername entry to have the subject.* information from the directives file listed.

Everything is now finally set for signing. The command actually used to sign a JAR file also requires a directives file. This is a different directives file than the one used to generate the signing certificate. The first directives file used to generate the certificate will no longer be needed, unless a different certificate needs to be generated. The second kind of directives file is used whenever a JAR gets signed, and should be kept handy. An example directives file for signing a JAR looks like this:

 signer=signername
 # look at javakey ld for certificate numbers, should be 1
 cert=1
 # chain unsupported, must have as value=0
 chain=0 
 # must be 8 characters or less and not conflict with any other
 # digital signatures that could be inserted into the JAR
 signature.file=anything
 out.file=Signed.jar

Once the signingdirective file has been created, run the command:

javakey gs signingdirective UnsignedApplet.jar

Running this command will generate Signed.jar, which will be a signed version of UnsignedApplet.jar. Putting Signed.jar in the ARCHIVE field of the APPLET tag in an HTML page will cause a Java-enabled browser to bring the JAR file over the network and execute the signed code contained within. For more information on javakey, the official Sun documentation for Solaris can be found at java.sun.com/products/jdk/1.1/docs/tooldocs/solaris/javakey.html.

The Win32 specific version can be found at java.sun.com/products/jdk/1.1/docs/tooldocs/win32/javakey.html.


Testing the Signed Applet

Now that a signed applet exists, and it is embedded within a Web page, it's ready for testing before release. Testing requires either appletviewer or a Web browser that knows how to validate JARs signed by javakey and allows signed JARs to leave the sandbox. Unfortunately, neither of the two major browsers (Netscape Communicator and Microsoft Internet Explorer) support javakey-signed JARs.

HotJava and the appletviewer program that comes with the JDK can validate JARs signed by javakey. They will allow signed applets out of the sandbox if the signature is valid and the policy states that the user whose signature appears is trusted. Both of these programs search for the identitydb.obj in the same manner that javakey does.

The problem is that no one should be surfing the Net with HotJava (too dangerous), and the appletviewer cannot be used to browse the Internet. Since the VMs in Communicator and Internet Explorer do not support javakey signing, in order run javakey-signed applets with those browsers, users must download and install Sun's Java Plug-In.


Java Plug-In for Communicator and Internet Explorer

Java Plug-In can be used to run applets instead of the browser's default VM. The Java Plug-In can be configured to use the most recent version of the Java Runtime Environment available from Sun. When an applet is run through the Java Plug-In instead of the browser's default VM, javakey-signed JARs can be verified and can step outside of the sandbox (if policy allows).

Users must download the Plug-In from Sun and install it on their system. The download page for the Plug-In is java.sun.com/products/plugin/index.html.

Applet developers also need to modify the HTML pages that contain their applets and modify the <APPLET> tag. Applets that are in Web pages using the standard <APPLET> tag will still be run by the browser's default page. The Plug-In will run applets only when it detects a different set of HTML tags that specify an applet. Sun provides an application called HTMLConverter, which can convert pages with the <APPLET> tag into pages containing tags that will launch applets using the Plug-in. The HTMLConverter homepage is java.sun.com/products/plugin/converter.html.

Two things to note about using the Plug-In. On Solaris, JavaScript must be enabled for the Plug-In to work properly. With JavaScript disabled, applets did not load or run when we tested the Plug-In with Communicator 4.02 and 4.06.

On Win32, the Java Plug-In did not find the identitydb.obj file in the same place that javakey did. This has to do with different versions of the VM setting different values of the user.home Property. If you run into trouble, try moving the identitydb.obj file to a different location. Places to try are mentioned in the section, Creating A Signing Certificate (see page 298).


Distributing Public Keys and Certificates

In order for someone to verify who signed a signed JAR, he or she needs the public key of the entity who signed the JAR in the first place. Until the public key is distributed to people other than its owner, no one but the owner can verify that an applet is signed and by whom. Once the signed applet has been tested and has proven to be functional, it can be placed on a Web site for use by others.

In order for the applet to escape the sandbox imposed by other people's browsers, users must have the public key or certificate of the entity that signed the applet. Also, the user must tell the identity database that he or she trusts the entity that signed the applet. Trusting the entity that signed the applet allows the applet complete access to the host. Here's how to create a trusted entry:

javakey c signername true

To import the signer's public key contained in keyfile, run:

javakey ik signername keyfile

To import the signer's certificate (which contains the signer's public key) from certfile, run:

javakey ic signername certfile

The identity must be created in the database before trying to import either the public key or certificate. In order to verify the signature on a signed JAR, you need only the public key of the signer. Certificates include the public key.

The signer of the applet must make his or her public key (or certificate) available to users of the applet in some way. It could be linked from a Web site, phoned in, or delivered through email. Whichever way it is done, the identity must first be extracted from the identity database. To extract a public key from the database to a file keyfile, use the command:

javakey ek signername keyfile

To extract signername's certificate number 1 to a file certfile, use the command:

javakey ec signername 1 certfile

The information in the keyfile or certfile should be given to those who want to create a policy that allows applets signed with the identity to leave the sandbox.

Previous Page
Previous Page


Search Help
Next Page
Next Page


Menu Map -- Text links below

Chapter... Preface -- 1 -- 2 -- 3 -- 4 -- 5 -- 6 -- 7 -- 8 -- 9 -- A -- B -- C -- Refs
Front -- Contents -- Help

Copyright ©1999 Gary McGraw and Edward Felten.
All rights reserved.
Published by John Wiley & Sons, Inc.