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
C:\Windows\DESKTOP\Signing\signtool13WIN95>signtool -d cacertdb -v PropsFrame.jar
using certificate directory: cacertdb
archive "PropsFrame.jar" has passed crypto verification.
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
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)
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
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
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
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