This is intended to be a simple how-to for signing JARs (applet JARs in particular) with RSA signatures. For information on testing RSA signing on a developer machine, see Testing Applets With RSA Signing.
There are different ways to sign an applet, but currently the most useful (and the one we'll cover) is called RSA signing. In this paper, the term signing, unless otherwise qualified, refers to RSA signing. RSA signing is sometimes called Netscape Object Signing because Netscape used it in their browser before the Sun added RSA signing support to the Java Plug-in. This paper assumes use of the Java 2 Plug-in (version 1.2.2 or later, preferably 1.3.0_01 or later).
Most applets have very limited access to the computer on which they run. These intentional restrictions are designed to prevent malicious applets from taking over your computer, silently stealing your data or overwhelming your network. But what about good applets which might need to save files or talk to other computers on the network?
Signing an applet can give it the access that applets are normally denied: accessing files on the client computer, connecting to arbitrary machines on the network, etc.
In order to sign an applet, you need the following:
Note: The Java 2 platform is supported directly by ADS 2.0 (which uses version 1.3.0_01 of the Java Plug-in).
An applet in a JAR is signed by analyzing the classes and data in the JAR and calculating some relatively unique numbers based on the analysis. These numbers are then stored in some extra files added to the applet JAR.
When the browser (or Java Plug-in) runs the applet, it notices the extra files, runs the same analysis on the applet content and compares its results with those stored in the extra files. If they match, it is VERY unlikely that the applet has been modified since signing. The analyses done are carefully chosen so that even small changes to any of the applet's content would produce different analysis results.
So, an applet is signed when the applet JAR contains signature information and that information correctly matches the other contents in the JAR.
Most locks we're familiar with have a single key. That key both locks and unlocks a house, car, and so on. Many types of computer security work the same way. In many situations, a single password both locks and unlocks data. This type of security isn't always the best match for the internet. For applets, the goal is not to lock or hide the entire applet -- often the applet must be used by many people. Rather, the goal is to ensure that the applet downloaded onto your machine hasn't been altered from its original design or intent. This is the everyday concept of a signature.
Many electronic signature methods, including RSA signing, make use of two keys (passwords, if you will). One (the private key) is used to create the signature, and the other (the public key) is used to read it. The two keys are referred to as a key pair. The public and private keys aren't passwords in the normal sense -- you can't just pick any value that you want. Instead, they are mathematical parameters used during the analysis of the content to be signed. The public and private keys are matched to each other and must be chosen (generated) such that the signature created by the private key can only be read by the public key. The public key is sent along with the original content and the signature. In our case, the content is the applet JAR, the signature is contained in files added to the JAR, and the public key is encoded in a certificate or certificate chain, which is also added to the JAR.
A certificate is a signed or encrypted copy of a public key or of another certificate, and acts as a voucher asserting that a particular entity has a particular public key. A self-signed certificate is one where the private key used to generate the certificate is the same as the public key advertised in the certificate. A certificate chain is a list of certificates where one certificate is signed by another, which is signed by another and so on, until the last certificate in the chain, which signs itself.
Key pairs work as follows: something encrypted with the private key can only be decrypted with the public key and vice-versa. So, if a trusted third party says your public key is foo and using public key foo decrypts the signing data in a JAR, you must be the one who signed the JAR.
Consider the following example. Sally needs to electronically send a contract to Bob, whom she has never met. She could sign the contract, but if someone were to intercept it, they could alter both the contract and the signature. However, there is a third party, Fred, whom both Bob and Sally know. Fred creates a certificate chain for Sally. For the first certificate in the chain, the content is Sally's public key (which Fred knows), which Fred signs with his private key. For the second and last certificate in the chain, Fred uses his private key to sign his own public key. This certificate chain declares Sally's public key to anyone who trusts Fred and already knows his public key.
Since keys are matched pairs, if the certificates in the chain decode correctly, only Fred's private key (which only Fred possesses) could have been used to create the certificate chain. Sally signs the contract with her private key and sends the signed contract together with the certificate chain to Bob. If someone intercepts and alters the contract, it won't match Sally's signature. The interceptor can't fake Sally's signature, because the certificate chain cannot be correctly altered without Fred's private key.
In our example, Fred is acting as a Certificate Authority (CA). For most signing situations, the CA is a company like VeriSign, which is paid to verify a person's or company's credentials (birth certificate and driver's license or articles of incorporation, and so on) and supply certificates containing that person's or company's public key. The Java Plug-in and modern browsers ship with a list of self-signed certificates for well known Certificate Authorities.
When the Plug-in downloads a signed applet, it checks the signing info (unwrapping each certificate in turn) until it reaches the last one. If the last one is from a trusted CA (one that the Plug-in knows about) the Plug-in considers the applet successfully signed. This signing doesn't in itself grant access. Instead, it makes it possible to reliably say that a particular identity did indeed sign the applet, and that the applet hasn't been tampered with since then. This reliability makes it possible for the Plug-in to ask the user whether to grant the applet extended privileges, based on who signed the applet.
An RSA signature refers to specific set of analysis algorithms used to generate the signature data. RSA Securities licenses the RSA algorithms and has a variety of information on their Web site.
For successfully signed applets, the Plug-in operates as follows. If the signer is already in the Plug-in's list of trusted signers, the applet runs with full access to everything -- just as if it were an application. Otherwise a dialog is displayed asking the user if they want to trust the signer. The user can choose to grant access to the signer's code for the current session, to always grant access to any content signed by the signer, or to deny extra access. If an applet isn't successfully signed or if the user refuses to grant special access, the Plug-in still runs the applet, but with normal applet restrictions.
Public and private key pairs are generally too long to remember or quickly type in. Typically, the key data is stored in files or databases, and is referred to by a shorter alias. Java 2 platforms store signing info like keys and certificates in a file called a keystore. Some tools to manage and use keystores are supplied with the jdk. We will be using keytool and jarsigner.
The RSA signing key pair will be generated by keytool (and saved in a keystore file). One must then obtain a certificate from a known Certificate Authority and import it (also using keytool) into the same keystore file. Jarsigner can then be used to sign JARs with the key pair and will automatically include a copy of the certificate in the JAR's signing data.
The following steps are taken from How to Sign Applets Using RSA Certificates.
To get your signing data (keys and certificate):
Your command line might look like the following:
keytool -genkey -keyalg rsa -alias MyAlias -keystore a:\mystore
keytool will then read additional info from stdin. See the keytool documentation for further info. Make sure the distinguished name you enter (which can include address information as well as corporate or personal name) contains all the pieces which your Certificate Authority needs. Check your Certificate Authority's Web site first. Generally, you will have to use your legal name exactly how it's spelled on your paper credentials.
keytool -certreq -alias MyAlias -keystore a:\mystore
will generate output like
-----BEGIN NEW CERTIFICATE REQUEST----- MIIBtjCCAR8CAQAwdjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwE AYDVQQHEwlDdXBlcnRpbm8xGTAXBgNVBAoTEFN1biBNaWNyb3N5c3RlbX MxFjAUBgNVBAsTDUphdmEgU29mdHdhcmUxEzARBgNVBAMTClN0YW5sZXk gSG8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALTgU8PovA4y59eb oPjY65BwCSc/zPqtOZKJlaW4WP+UhmebE+T2Mho7P5zXjGf7elo3tV5uI 3vzgGfnhgpf73EoMow8EJhly4w/YsXKqeJEqqvNogzAD+qUv7Ld6dLOv0 CO5qvpmBAO6mfaI1XAgx/4xU/6009jVQe0TgIoocB5AgMBAAGgADANBgk qhkiG9w0BAQQFAAOBgQAWmLrkifKiUYtd4ykhBtPWSwW/IKkgyfIuNMML dF1DH8neSnXf3ZLI32f2yXvs7u3/xn6chnTXh4HYCJoGYOAbB3WNbAoQR i6u6TLLOvgv9pMNUo6v1qB0xly1faizjimVYBwLhOenkA3Bw7S8UIVfdv 84cO9dFUGcr/Pfrl3GtQ== -----END NEW CERTIFICATE REQUEST-----
keytool -import -alias MyAlias -keystore a:\mystore -file MyVeriSignCert.cer
Now, to sign your applet, do the following.
jarsigner -keystore a:\mystore myApplet.jar MyAlias
The WebAF 2.0 Package Wizard can automatically run jarsigner for you, as part of the packaging process. Obviously, you must have a suitable keystore for jarsigner to use. Just fill in the information on the signing page of the Package Wizard:
Choose to sign the JAR, enter the keystore password and the alias to sign with. Like jarsigner, if you do not specify a key password, it is assumed to be the same as the keystore password. You may use the default keystore or specify the keystore file to use. The Package Wizard will now sign your project JAR each time you package your project.
Note: While the Package Wizard remembers most of your settings, it deliberately does NOT store any passwords you enter. You will need to re-enter these each time.
Keytool can generate private keys, but doesn't currently have the ability to import them, and without the private key, you can't sign anything. However, if what you have are RSA keys, you may be able to use Netscape's signing tools to sign a JAR, but they are much more troublesome to use. Netscape's signing tool uses its own database format (rather than Javasoft's keystore format). It can, however, use some of the PKCS formats for reading private keys.
The overall process is similar (you generate keys, obtain a certificate and then sign the JAR). So, if your public and private keys and certificate are stored within Netscape, you may need to export them to files on disk for the command-line signing tool to use. Netscape's signing tool doesn't operate on JARs, but directories. So you'll have to expand your applet's .jar into its own directory. To run Netscape's signing tool, you'll point it to the directory containing signing data as well as the directory containing your applet's content, and it will create a signed JAR. Refer to the documentation in the Resources section for more information on using Netscape's tools. (The link on how to sign applets using RSA Certificates also contains some info on Netscape's tools.)
A third option, if your existing data is in PKCS format, is to download Sun's Java(TM) Secure Socket Extension (JSSE) to read PKCS files. Classes available with the JSSE can be used with jarsigner to treat PKCS files as a keystore. It is also possible to write a program that uses the JSSE classes to copy data from PKCS files into a regular keystore file. Once your data is available as a keystore, signing can proceed as normal.