Name: rv122619 Date: 07/28/2004
Jars are the standard distribution method for Java code. Jar signing has long been used by the Java Plug-in, Java Web Start and the Java 2 security architecture in general to make downloaded code more trustworthy. However, exiting APIs allow reading (not writing) of some signature information at the jar entry level, while the unit in question is most often an entire jar.
It is far too difficult for general Java applications to leverage jar signing. Especially with Java 1.5 finally supporting time-of-signing for jar signatures, if the barriers to actually _using_ jar signatures can be overcome, it will be a great boon to Java developers.
Currently, standard Java APIs allow one to obtain a list of Certificate objects (if any) associated with each jar entry. Java 1.5 improves this slightly with the CodeSigner class, which gives access to timestamp information. But for applications to easily make use of signed jars, many things are missing.
This is a request for APIs which treat signed jars as whole units, allow easy access to signer information (including displayable information, timestamps, etc.). Also needed are ways to programmatically generate signed jars (and perhaps to easily sign content in general). This includes the need for sufficient APIs to manipulate common PKCS formats (both read and write).
I wrote a deployment tool for Java applets. It needed to grant extra privileges to signed code, and like the Plug-in, needed to give final choice about trust to the user. Writing even this most basic functionality for using signed jars was surprisingly involved and difficult:
A given entry in a jar might be signed, and if the jar is opened with verification on (the default), completely reading the entry contents will throw a security exception if the entry contents have been tampered with. This is fine and good, but is a far cry from determining that 1) all entries which should be signed are signed, 2) all of the signed entries have one or more shared signer identities 3) validating the common signers (against cacerts, checking time-of-signing), etc. and 4) Determining displayable information for the signer identities such that they can be presented in a dialog to the user.
Similarly, in helping write a tool to sign our internal jars, duplicating the effects of jarsigner is difficult. It's probably impossible to do without extensive use of non-public Sun classes and APIs or without downloading extensive 3rd-party libraries (if sufficient libraries exist to cover all needed functionality). Going the routes of build your own libraries or even re-using what 3rd-party libraries might be available requires a huge investment of time and skill! Even making use of the internal classes required significant time and research -- and it might break with the next release! Part of all of this is because the ONLY approved means to sign things is via jarsigner and there is no public API to use programmatically. Reasons to NOT use jarsigner include launching of a separate process for each signing operation, etc.
What is needed most are high-level APIs and components for verifying and generating signed jars and dealing with signature information. From the generally available info, the Certificate returned by JarEntry.getCertificates() is TERRIBLY unwieldy! That single array may represent signer information from multiple signers. When I originally looked, I don't think the documentation ever made any guarantees about the ordering of certificates in the array. One generally needs to cast the elements to X509Certificate to get any useable information out of them, etc. And that's apart from the entry-view vs. jar-view issue.
What would also be helpful is to go ahead and make the underlying frameworks available -- general APIs for reading and writing the various PKCS formats and, beyond that, general APIs for working in ASN.1. Since Sun is promoting fast web services via ASN.1, it might play nicely to give developers some public ASN.1 APIs to work with.
Signed jars have been around a long time. They are fairly well defined, generally accepted, and are frequently used in spite of the current drawbacks (needing to re-sign jars annually due to no time-of-signing support in any production version of Java). One would expect such an established security mechanism to be easily programmed, but there are no APIs for dealing with common operations.
The inability to easily make use of signed jars may be part of the reason so few (if any) applications, plug-in frameworks, etc. leverage jar signing. One of Java's strengths is security -- I would expect most applications to support plug-ins, skins, etc. using signatures.
There are no APIs for jar-level treatment of signed jars.
Signatures expire. The Plug-in has over-compensated for the problem by (in 1.4.2_04) presenting the user with a trust dialog even for jars using a self-signed certificate! Certainly some accommodation was necessary because jars expire, but that's going too far. At least Java 1.5 will provide time-of-signing support in jarsigner and hopefully in the Java Plug-in and Java Web Start as well. I hope that, when time-of-signing support is made available, the treatment of un-timestamped signatures is tightened up. (And I truly hope that signatures with time-of-signing information which indicates the signing occurred outside of validity or which use unknown time stamping authorities will be outright rejected!)
There is no API for programmatically creating a signed jar. The only supported means for creating a signed jar is to run a command-line tool (requiring the launch of a separate process) which is only available with the jdk, not the jre.