Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

.NET

How Do I Create a Signed Applet?


Dr. Dobb's Journal August 1997: Java Q&A

Cliff, vice president of technology of Digital Focus, can be contacted at [email protected]. To submit questions, check out the Java Developer FAQ web site at http://www.digitalfocus.com/faq/.


Java is a platform-independent language, which makes it possible for you to write programs that can be automatically deployed across a TCP/IP network of heterogeneous computers. To protect users' systems from malicious programs from untrusted sources, such programs must be greatly restricted by the local Java security manager. Since there has been no way to distinguish trusted programs from untrusted ones, all Java programs downloaded via a browser were subject to severe restrictions in terms of reading and writing files, opening network connections, and reading local system properties.

However, signing a program with a digital signature provides a means of verifying the origin and authenticity of a program. When a browser receives an applet that has been signed, it can verify the origin of the applet and detect whether or not the applet has been modified since it was signed. A signed applet can be granted much greater freedom because users can be sure that a third party has not maliciously modified it. If you trust the original source, you can trust the applet.

A signed Java applet takes the form of a Java Archive (JAR) file. In addition to providing security, JAR files also allow faster downloads because all the files an applet needs are encapsulated into one object, instead of multiple files. Consequently, only one network connection must be established by a browser to transfer an applet. Without a JAR file, separate connections may need to be created every time a new class file is needed.

Digital Signatures

The most useful type of digital signature uses public/private key encryption, or what is also known as "asymmetric key encryption." It is asymmetric because a single key cannot be used to both encrypt and decrypt the same message. If a message is encrypted using the private key, only its corresponding public key can decrypt it, and vice versa.

A digest is a value that is, in effect, a hash value of a message. It is important that the algorithm used to compute the digest be a one-way algorithm, so that, given the digest, the original message cannot be computed. Thus, the digest represents a signature of the message. If you give someone the digest in a secure way, then give them the message in an unsecure way, he can recompute the digest from the unsecure message. If the unsecure message equals the secure digest he was given, you can be confident that the message is unaltered. Thus, the digest serves as a proxy for the message within the signature. This does not prevent someone from eavesdropping on the message, since the actual message is in clear unencrypted form. (This typically isn't an issue with signed applets.) The most common digest algorithm is the MD5 checksum algorithm. (For more information on one-hash algorithms in general, and the MD5 algorithm in particular, see "One-Way Hash Functions," by Bruce Schneier, DDJ, September 1991.)

To create a digital signature, you encrypt a digest of a message, using a private key that only you know. See Figure 1. You could encrypt the entire message, but then it would not be a signature -- it would be an encrypted message. Since you used your private key to encrypt the digest, only your public key can be used to decrypt it. You can give your public key to the intended recipient.

The only issue is the manner in which you give recipients your public key. They need to be sure that it is really your public key, and that you are who you say you are. If you give them the public key by putting a diskette in their hand, and they recognize you by sight, then they have no doubt about the authenticity of the key. If, however, they received the key electronically, someone else could be pretending to be you. This is where digital certificates come into play; see Figure 2 and Figure 3.

Digital certificates provide a way to use a trusted third party to authenticate communication between two parties. If you trust the third party, and the third party tells you, in a secure way, that the other person has a specified public key, then you can trust that key. To do this, the third party writes the other person's key into a message, and signs it (by encrypting it) using the third party's private key. This assumes that you have the public key of the third party. Assuming you do, you can use that public key to decrypt the message and retrieve the person's public key. Thus, the person's key has been transferred to you securely. Since you trust the third party, you can trust the new key. Typically, the third party is either a certificate authority such Verisign (http://www .verisign.com/) for an Internet application, or your own organization for an intranet application.

Signing proves that you have received an uncorrupted message and identifies the originating party. It does not protect your system from invasion; it merely provides traceability. Note that you are relying on the certifying authority to safeguard against misrepresentation. You are still vulnerable to theft of keys and accidental invasion due to an errant program.

In "How Do I Create My Own Security Manager?" (DDJ, June 1997), I discussed the Java security manager that safeguards your local system against invasion. Signing provides a means for guaranteeing the integrity and origin of transferred content. Any kind of content may be signed, including, but not limited to, applets and other Java class files. You can, for example, sign the data files that accompany an applet in a JAR file, or any resource files that the applet uses.

From the user's point of view, there needs to be a tool for managing the certificates the user owns (for sharing private communications with others), associated private keys, and the copies of certificates that they have received from others (in a JAR file, for instance). Netscape Navigator, for example, has a set of tabs for managing this information, and will automatically read the certificate embedded in the JAR file, and install it, with the user's permission.

So What is a JAR File?

A JAR file is a ZIP file and can be opened by any tool that can open ZIP files. What makes a JAR file different from an ordinary ZIP archive is that JARs may contain special files that provide information used to digitally sign the contained files.

JARs contain a special directory called META-INF, which contains a "manifest" file, signature instruction files, and actual signature files. The manifest contains a list of all of the signed files in the archive. JAR files can contain multiple digital signatures for the same content, possibly using different encryption algorithms: A recipient may not have one of the specified algorithms available, so signatures using other algorithms may be included in the archive to accommodate more users. Some Java Virtual Machine clients will have more algorithms installed than others.

Each signature-instructions file is essentially a list of the files to sign and how to sign them. The signature-instructions file gets signed, so the signature-instructions file contains a value that is a function of the files the user wants to sign. The signature-instructions file also contains digests of the entries in the manifest, which contains digests of the actual files.

In short, the signature-instructions file is derived from the manifest, which is derived from the files in the archive. Signing the signature-instructions file is, therefore, equivalent to signing the actual files themselves, but is more economical. A signature-instructions file is signed by encrypting it with a specified algorithm, then placing the encrypted version in the archive along with a copy of the certificate. Figure 4 summarizes the contents of a signed JAR file.

How Do I Make a JAR File?

To create a signed JAR file, you first need a "certificate" containing your name and public key. This would normally be created for you by another certificate owner, who is trusted by those who will be receiving your JAR file. (You can, however, create your own certificates for testing purposes.) Those recipients, further, need to have the public key of this trusted certificate holder (for example, a copy of its certificate). Thus, if you are creating a JAR file for internal corporate use, you could have your company issue the certificate to you. On the other hand, if you are publishing the JAR file on a web site, you will probably want to obtain a certificate from the likes of Verisign or the U.S. Postal Service (which, in conjunction with Cylink, is developing digital certificates. For more information, see http://www.usps.gov/ and http://www .cylink.com/).

Upon obtaining a certificate, you get the private key you will use for encrypting messages and signing files. People who have a copy of your certificate can use the public key included in it to decode your messages and signatures. Since only your private key can be used to create messages that can be decoded with the public key, this proves that you (or someone with your private key!) created the message. If the encoded message contains information that can be derived from other parts of your clear-text document, this is indirect proof that those parts, too, are unaltered and original.

In the context of a JAR file, the signature file is the encoded message. Its contents can be derived from the other files in the archive. When the signature file is decrypted, its message is compared with a new message computed from the contents of the other files in the archive (using the same algorithm). If there is a mismatch, then one of the archive files has probably been tampered with.

A few important things to remember are that you:

  • Need to obtain a certificate from a trusted authority in order to be able to sign JAR files.
  • Can use the JAR facility to create the initial, unsigned JAR archive.
  • Can use the javakey facility to perform the signing.

Once you have a certificate, you can make certificates for other people. These are only useful, however, to the extent that you can be considered a trusted authority, and also to the extent that others can be sure that you have not been careless with your private key.

You use the private key to sign the signature-instructions file. This is done with the javakey facility.

The sequence of events is:

1. Use JAR to create the unsigned archive.
2. Enter your name into your javakey database.
3. Obtain a certificate from a source that is trusted by your target audience (a source from which your audience is likely to already have a certificate).
4. Import your certificate into your javakey database.
5. Use your certificate, with javakey, to sign the archive.

To create a certificate (instead of obtaining one), steps 3 and 4 would be replaced with:

3. Generate a public/private key pair using javakey.
4. Generate a certificate using javakey.

Creating a Privileged Applet

When writing Java applets, you have probably run into the limitations imposed by the security managers of Navigator and other browsers. Applets must run in a "sandbox" to ensure that they do not invade the local system. For example, an applet is not allowed to read a file from the local system, much less write to a file or read system properties. It is reasonable to give a signed applet more freedom, however, because if it does harm, you can at least find out who is responsible! By the time you read this column, the latest versions of popular browsers should begin to support signed applets, allowing users to give signed applets more privileges. If you don't have such a browser, you can at least test the concepts using the JDK AppletViewer program.

Listing One is the DirectoryViewer program that reads the user.dir property (the user's current directory), then obtains and displays a directory listing in that directory. It also allows users to specify an alternative directory, then obtain a listing of that directory. An applet run in a browser cannot ordinarily do these things; but when the applet is encapsulated into a signed JAR file, a browser that supports signed applets will permit the applet to perform these functions.

The first step, of course, is to compile the source code. Next, you create a small HTML file to run it, place that HTML on a web site with the .class file, and attempt to load the applet remotely. It should generate a security exception. (Make sure that your current directory does not include the .class file or AppletViewer will load that instead.)

To create the JAR file, you run the JAR tool, specifying options followed by the name of the output file and the files that are to be included in the archive -- in this case, jar cf DirectoryLister.jar DirectoryLister.class, since you are only placing one file in the archive.

To create a trusted entry in my javakey database, I type javakey -cs Cliff true, which says "create an entity called 'Cliff' who is trusted;" that is, if anything signed by "Cliff" is encountered, it should be considered trusted. Of course, at this point, we have no way of authenticating Cliff.

In order to sign and test my JAR file, I need to create a certificate. To do so, I use javakey to generate a public/private key pair. Then I use javakey again to make a certificate. To create the key pair, I type javakey -gk Cliff DSA 512 CliffsPublicKey CliffsPrivateKey, which will use the Digital Signature Algorithm (DSA) to compute a 512-bit key pair, and put the public and private keys in the files CliffsPublicKey and CliffsPrivateKey, respectively. You could specify an algorithm other than DSA, but you'll have to install that algorithm. (To statically install a new algorithm, a class that extends the abstract Provider class must be placed in the classpath, and an entry must be made to your java.security file.)

To generate a certificate from the key pair, you need to create a directives file for javakey. Listing Two, my directives file, provides the information javakey uses to create an X.509-compliant digital certificate. Note that the issuer name and subject name are identical because I am issuing myself a certificate. If you obtain a certificate from a certificate issuer, this process would be performed for you. The start and end dates are important because private keys are sometimes discovered, so you don't want a certificate to have an indefinite lifetime. The serial number uniquely identifies this certificate and is assigned by the certificate issuer. The certificate will be created and placed in the specified output file (Cliff.certificate). I called this directive file "Certificate.directives."

To actually create the certificate, I ran javakey with the command javakey -gc Certificate.directives. I now have a certificate to sign my JAR file. To perform the signing, I use javakey. To sign a JAR file, javakey needs a directive file as well. In my directive file (see Listing Three), the first line specifies my identity. This must match the subject name in the certificate. The second line specifies which certificate in my javakey database to use for the signing. This certificate is automatically inserted into the JAR file when the file is signed.

The third line is not used, and the last line specifies the base name to use for the signature instructions and signature files in the archive; it must have no more than eight characters. I called this directives file "Signature.directives." To run javakey to sign the JAR file, I type javakey -gs Signature.directives DirectoryLister.jar. The javakey program then creates a new file, with the same name as the input JAR file, but with a .sig extension. Since this is the actual signed JAR file that you will distribute, you should rename it to give it a .jar extension.

You can now place this file on a web site. All you need is some HTML to identify it. Your HTML must specify the name of the JAR file, in addition to the usual class file name, width, and height. Listing Four is the HTML I used. If you load this applet from a remote web site, using HotJava, AppletViewer, or any browser that supports signed applets, it should be able to display the directory contents of your local hard drive, without generating a security exception (as long as you have not disabled this in the browser).

Conclusion

Digital signatures make remote deployment of full-featured applications practical. Browsers like Netscape's Navigator allow users to verify that a signed applet has the right to perform operations that might threaten the local system. Once approved, the applet can proceed. However, an applet that should have no need to access the local drive will be forced to request permission to do so at least once, getting the user's attention. This is because the Java security manager must still approve all operations, whether the applet is signed or not. Thus, unexpected behavior is still detected; the applet does not have free reign and you -- the user -- are still in control.


Listing One

public class DirectoryLister extends java.applet.Applet    implements java.awt.event.ActionListener
{
    private java.awt.TextField tf;
    private java.awt.TextArea ta;
    private java.awt.Button b;
    String[] files;
    
    public static void main(String[] args)
    {
        java.awt.Frame f = new java.awt.Frame();
        f.setSize(400, 220);
        f.show();
        DirectoryLister dl = new DirectoryLister();
        f.add("Center", dl);
        dl.init();
        dl.start();
    }
    public void init()
    {
        setLayout(null);
        ta = new java.awt.TextArea();
        add(ta);
        ta.setSize(300, 100);
        ta.setLocation(10, 10);


</p>
        tf = new java.awt.TextField();
        add(tf);
        tf.setSize(300, 20);
        tf.setLocation(10, 124);
        
        b = new java.awt.Button("Display");
        add(b);
        b.setSize(100, 20);
        b.setLocation(10, 154);
        
        b.addActionListener(this);


</p>
        // Attempt to get the current directory
        
        String dir = System.getProperty("user.dir");
        getListing(dir);
        displayListing();
    }
    public void actionPerformed(java.awt.event.ActionEvent event)
    {
        Object source = event.getSource();
        
        if (source == b)
        {
            System.out.println("button clicked");
            // Obtain listing for the specified directory
            
            getListing(tf.getText());
            
            // Display the listing in the text window
            
            displayListing();
        }
    }
    protected void getListing(String dir)
    {
        java.io.File f = new java.io.File(dir);
        files = f.list();
    }
    protected void displayListing()


</p>
       ta.setText("");
        for (int i = 0; i < files.length; i++)
        {
            ta.append(files[i]);
            ta.append("\r\n");
        }
    }
}

Back to Article

Listing Two

issuer.name=Cliffsubject.name=Cliff
subject.real.name=Cliff Berg
subject.org.unit=Digital Focus
subject.org=Digital Focus
subject.country=US
start.date=1 June 1997
end.date=1 Dec 1997
serial.number=100
out.file=Cliff.certificate

Back to Article

Listing Three

signer=Cliffcert=1
chain=0
signature.file=Sig

Back to Article

Listing Four

<html><applet code="DirectoryLister.class" archive="DirectoryLister.jar" 
    width=400 height=220>
</applet>
</html>

Back to Article

DDJ


Copyright © 1997, Dr. Dobb's Journal


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.