Signing Code with JDK 1.2
Creating a simple policy for signed appletsJDK 1.2 introduces the notion of policy. Creating, understanding, and managing security policy for signed mobile code is a difficult and complex problem. Since this discussion is about signing code and not about constructing policy, an extremely simple example of how to construct policy is presented. Creating good policy is beyond the scope of this article. The example policy is strong enough to allow an applet limited file access to the host machine.
Java policy files can be created with a new tool that comes with JDK 1.2 called policytool. This application has a GUI to guide users though the many twists and turns encountered when creating policy files. It's a very simplistic GUI with no on-line help. In it's current form as of beta4, it is only useful if one does not know the syntax of a policy file.
Policy files are plain-text files that follow a format outlined at Default Policy Implementation and Policy File Syntax.
Permissions that can be granted in a java policy file are outlined at Permissions in JDK1.2.
To grant an applet permission to write or create any file in the c:\tmp directory, assuming the applet comes from http://www.friendly.com/~mybuddy/applets/ and is signed by a certificate known in the default keystore by the alias friend, create a file called .java.policy in the directory known to the VM as user.home which contains:
Note the double backslashes. All Win32 pathnames must use double backslashes to indicate directories. UNIX pathnames use regular singleton forward slashes. codeBase entries follows URL syntax.
Sign only privileged codeApplets that request permission to leave the sandbox are usually built for doing serious business tasks. These applets that require access to the local system are most likely some of the larger applets in terms of code size. It is unlikely that these applets will be built completely by one developer or one software company. Chances are some of the components of an applet will be bits of utility code found on the Internet or purchased from a tool vendor. A smart organization wants to sign only code that it produced. Third party utility code cannot be safely vouched for.
If all the code is signed, then any code can leave the sandbox based on the policy. But if some code in an applet is from a third-party, it should not be signed unless the individual signing the code is willing to vouch that the third-party code won't try to do anything malicious or introduce a security hole that others can exploit. To say the least, we don't recommend signing code you don't completely understand.
JDK 1.2 presents an API for privileged blocks. Privileged blocks are meant to be small sections of code that have a higher privilege than the code that invoked them. JDK 1.2beta4 changed the API for privileged blocks from previous beta releases. Using this API, the only code that needs to be signed is the code that invokes the AccessController class, and the code that performs the privileged action. All other code can remain unsigned, preventing it from leaving the sandbox on its own. Documentation on the new API can be found at New API for Privileged Blocks.
There are two things to consider when writing signed code that will be integrated with unsigned code. First, make the code in the privileged block as small as possible. The less code that is privileged, the less chance that granting it higher privilege will result in nasty and unwanted side-effects. Second, to prevent mix-and-match attacks, all the code for the applet should live in one JAR file, even if the third-party libraries that are used by the applet live in their own JAR.
To sign some portions of a JAR file and leave others unsigned takes a number of steps we'll cover now. First create a JAR file containing all classes that need to be signed. Classes that need to be signed when using privileged blocks include all classes that contain the call to the
jar cvf MyApp.jar Signme1.class Signme2.class
List all the classes that need to be signed in this step. Once the JAR containing classes that need to be signed is created, sign the JAR with jarsigner:
jarsigner MyApp.jar mykey
Now, add the remainder of the classes in the application to
jar uvf MyApp.jar Other1.class Others.class
All the remaining classes in the application should be added to the JAR in this step. If parts of the application are already in a JAR or ZIP file, they will need to be un-archived before being JARed into the new partially signed JAR file. To verify that all went correctly, use jarsigner to verify the contents:
jarsigner -verify -verbose MyApp.jar
Only the classes that were added before jarsigner was invoked to create the signature will be marked as signed. All the other classes will be listed, but no certificate or signature will be associated with their listing. If jarsigner fails to verify the entire JAR, or classes that are supposed to be signed appear not to be, use the jar command to list the contents of the JAR.
jar tvf MyApp.jar
The first entry in the JAR must be META-INF/MANIFEST.MF. If the manifest file is missing or not in the first position in the file, the JAR will not verify properly. Following the MANIFEST.MF file should be a .SF and .DSA file. If either of those files is missing, then the signature is missing from the JAR. Remove the JAR file and start over. If the commands listed above still move the META-INF/MANIFEST.MF file out of the first position in the file, it may not be possible to create a JAR containing signed and unsigned code. The JAR command with JDK 1.2beta4 did not move the META-INF/MANIFEST.MF file around in the JARs we created using the process described above.
Comparison to Netscape Object SigningLast week, we discussed Netscape Object Signing. Here's a brief summary of major differences from the JDK 1.2 keytool/jarsigner system.
Summing upIt's difficult to say if Sun's approach will enter widespread use. It may require one of the major browser vendors to adopt and support the use of keytool and jarsigner. Downloading and installing the Java Plug-In, finding, downloading and installing certificates, and managing policy are three hoops that Netscape users don't have to jump through. For developers, there's a trade off. Developing for Netscape requires paying for a certificate from a CA and tying their code to Netscape libraries. JDK 1.2 developers have to convert all their HTML pages with the HTMLConverter.
To see an example of an applet signed using jarsigner for JDK 1.2, take a look at To View the Signed Applet. Of course, to view the applet, you'll need the Java Plug-in.
Next week, we'll discuss Authenticode, Microsoft's Java code signing scheme.
Tom O'Connor is a software engineer in the research division at Reliable Software Technologies. His interests are computer security and object-oriented software development.
John Viega is a research associate at Reliable Software Technologies, in Sterling, Va. He holds an M.S. in Computer Science from the University of Virginia. He developed and maintains Mailman, the Gnu mailing list manager. His research interests include software assurance, programming languages, and object-oriented systems.
Portions of this article will appear as an appendix in the forthcoming book Securing Java: Getting Down to Business with Mobile Code (John Wiley & Sons, 1998), the second edition of McGraw and Felten's book, Java Security: Hostile Applets, Holes, & Antidotes.
Page 2 of 2