Executing Signed JAR Archives

M. Gallant 07/08/2001

Java2 Security infrastructure provides the capability to execute Java *applications* under a security manager, with customized user policy file settings. The following article describes how to run signed Java applications within JAR archives, under a local customized security "sandbox". The application here PropsFrame.java, signed and packaged into a single PropsFrame.jar archive, is a simple application that lists all Java System Properties in a TextArea within a pop-up Frame. The application is packaged into a JAR archive in order to digitally sign it, and to be executed directly. Most of the example here refers to the win32 platform.

Signing and Verifying the Signature

The Java code is compiled using javac.exe. The class files (2) can be conveniently archived and signed in one step using Netscape Signtool.exe Version 1.3:
     signtool -k "keynickname" -m manif.txt -d cacertdb -Z PropsFrame.jar signdir
It is assumed that the code-signing certificate (and associated CA certificate) have already been imported into the Netscape key files key3.db and cert7.db. The manifest in the archive is supplemented with the contents of a single-line file manif.txt containing the single line:
     + Main-Class: PropsFrame
which is the proper format for Signtool.exe. The PropsFrame.jar contents and the manifest can be easily viewed to show the details.

The signed JAR archive can be verified using either Signtool.exe:

C:\Windows\DESKTOP\Signing\signtool13WIN95>signtool -d cacertdb -v PropsFrame.jar

using certificate directory: cacertdb
archive "PropsFrame.jar" has passed crypto verification.

          status   path
    ------------   -------------------
        verified   PropsFrame$1.class
        verified   PropsFrame.class
or, the signed JAR can be verified using jarsigner.exe (only from j2se1.3 version):
C:\Windows\DESKTOP>jarsigner -verify -verbose PropsFrame.jar

sm       461 Sun Jan 14 16:07:36 EST 2001 PropsFrame$1.class
sm      1594 Sun Jan 14 16:07:36 EST 2001 PropsFrame.class
         404 Sun Jan 14 16:07:36 EST 2001 META-INF/manifest.m
         489 Sun Jan 14 16:07:36 EST 2001 META-INF/zigbert.sf
        1207 Sun Jan 14 16:07:36 EST 2001 META-INF/zigbert.rs

  s = signature was verified
  m = entry is listed in manifest
  k = at least one certificate was found in keystore
  i = at least one certificate was found in identity scope

jar verified.

Note that the Java runtime verifies the integrity of the signature against the contents of the JAR archive when the JAR loads, and if the JAR is corrupted for any reason, the loading will fail, and the executable JAR archive will not execute. This checking occurs before the security manager is called to check what privileges the JAR archive should have based on the identity of the signer, what security manager was invoked and the contents of any local client policy file.

Executing the JAR application

Under J2SE1.2+, a JAR file with a Main-Class: manifest entry can be launched directly, without a security manager:
     java -jar PropsFrame.jar
which enables Java applications with arbitrary capability and no traceable authentication to execute. The signed JAR archive provided here should execute without any errors or prompts.

The JAR'd application can be launched under fully restrictive sandbox conditions (very similar to Java applet default security sandboxing):
     java -jar -Djava.security.manager PropsFrame.jar
in which case the application will typically throw a security exception when PropsFrame is executed:

C:\Windows\DESKTOP>java -jar -Djava.security.manager PropsFrame.jar
Exception in thread "main" java.security.AccessControlException: access denied (
java.util.PropertyPermission * read,write)
        at java.security.AccessControlContext.checkPermission(Unknown Source)
        at java.security.AccessController.checkPermission(Unknown Source)
        at java.lang.SecurityManager.checkPermission(Unknown Source)
        at java.lang.SecurityManager.checkPropertiesAccess(Unknown Source)
        at java.lang.System.getProperties(Unknown Source)
        at PropsFrame.main(PropsFrame.java:23)
To provide a "sandbox" environment with digital signature authentication in which to run a JAR archive under strict security control, the public key of the signer, typically in the form of an X509v3 certificate, must first be imported, using keytool.exe into the Java2 keystore file (default is .keystore). In addition, the issuing CA must also be recognized (typically already present in the cacerts J2SE file for commercial Verisign, Thawte issued certificates), unless the certificate is "self-signed". If the CA is a custom one (for example, from an enterprise CA on a corporate intranet), then it must be explicitly imported into cacerts using keytool.exe.

Client Policy File

A client policy file (default is .java.policy) is then configured. This is most easily done using Policytool.exe. The example here configures the Policy File with a single policy entry to allow only code signed by an entity (represented by an alias in .keystore) and only code found within a specific folder on the local disk to execute. The only permission granted to any code from this signer is the ability to transparently read all Java System Properties and nothing more! Now, executing the command:
     java -jar -Djava.security.manager PropsFrame.jar
under these restrictive security conditions allows this JAR'd application to run successfully. The advantage of having to import code-signers' public certificates explicitly (and not just having the issuing CA certificate recognized) is that it provides greater control and awareness of code-signing responsibility. The disadvantage is greater inconvenience.

Win32 File Extension Configuration

On Win32 systems, installing the J2SE1.2.2+ provides a file association automatically for .jar files so that double-clicking the .jar file icon will automatically launch the command:
     C:\Program Files\Java Web Start\1.3.0\bin\javaw.exe -jar jarfile
It is easy to modify this file association to transparently provide the enhanced security infrastructure for launching Java applications in JAR archives described above:
     C:\Program Files\Java Web Start\1.3.0\bin\javaw.exe -jar -Djava.security.manager jarfile

A Note on "current directory" Issues with JAR Applications

When a JAR'd Java application is launched by double-clicking an icon on the win32 desktop, the default current directory, as returned by the Java System Property user.dir is C:\windows (for Win95) and NOT c:\windows\desktop. However, if the JAR file is placed in a folder on the desktop and launched by double-clicking, the user.dir path returns the actual path to this subfolder. However, if the JAR file on the desktop is launched by shelling to a command-prompt with the desktop as the current directory, and executing with java -jar javaapp.jar then user.dir will be the path to the desktop. This can lead to confusion if the Java application in this JAR archive uses relative references to files in the "current directory". [Exactly the same considerations seem to apply to win32 javaapp.exe files generated by MS jexegen.exe tool.]. To avoid path problems, run the JAR archive from a well-defined explicit folder, or read and use the user.dir Java property.