ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


Java Security

Java Plug-in 1.3 and RSA Signed Applets

03/22/2001

Java's support of applets was one of the early factors that led to Java's immense popularity. However, Java applets have achieved less success over the last few years than was expected. There are a number of technical reasons for the failure of applets to live up to their early expectations:

Fortunately, Sun worked hard over the years to address these shortcomings. There are now a number of reasons why applets are becoming a better solution for mobile code.

The above factors, combined with increased high-performance microprocessors and Internet connections, make applets a more appealing alternative to delivering executable content. In this column, I'll focus on the latest release of the Java plug-in (version 1.3) and its support for RSA signed applets and dynamic trust management.

Java Plug-in

The Java plug-in provides a way for users to run Sun's latest JVM and API within their browsers. The plug-in is run in place of the browser's native JVM and API classes.

For Java developers, the advantages of the plug-in are tremendous. The plug-in enables developers to write their applets for the latest version of Java. It is assured that their applets will work consistently and reliably with both older and newer browsers, whether they are from Microsoft or Netscape or whether they run on Windows, Linux, Solaris, or several other versions of Unix.

How does it work?
The Java plug-in works in generally the same way as other browser plug-ins, such as Flash and QuickTime. An HTML converter (available from Sun) converts <applet> tags to the <object> and <embed> tags used to identify plug-in content to Internet Explorer and Navigator.

The plug-in appears to Internet Explorer as an ActiveX control. When Internet Explorer encounters the <object> tag of a converted HTML page (that references the Java plug-in), it will check to see if the plug-in is installed. If the plug-in is installed, Internet Explorer will load and run the plug-in and use it to execute the applet referenced by the <object> tag. If the plug-in is not installed, Internet Explorer will download it from Sun and then install it (after asking the user for permission to do so).

When used with Navigator, the plug-in takes advantage of Navigator's plug-in API to simplify download and installation. The first time that Navigator encounters an applet's <embed> tag, it displays a missing plug-in icon to the user. If the user clicks on the icon, Navigator walks the user through the process of downloading and installing the plug-in. After the plug-in is installed, it will execute any applets referenced by <embed> tags.

The plug-in does not replace the browser's native JVM. The browser's native JVM is still used to run applets that are referenced by <applet> tags. The plug-in is run in place of the browser's native JVM when the browser encounters <applet> tags that have been converted to <object> or <embed> tags by Sun's HTML converter. No conversion of the applet's Java code takes place. The HTML converter only converts <applet> tags to <object> and <embed> tags within the HTML files that reference applets.

The plug-in and HTML converter are freely available from Sun.

Evolution of the Java Plug-In
The Java plug-in is not a new development. Plug-ins have existed for JDK versions 1.1 and 1.2. What's new and interesting about the Java plug-in 1.3 is its support for RSA signed applets and dynamic trust management.

Previous versions of Java plug-in supported DSA signed applets. The Digital Signature Algorithm (DSA) was developed by the U.S. National Institute of Standards and Technology (NIST) (see http://www.nist.gov). Even though DSA has been adopted as the standard for digital signatures within the U.S., the RSA algorithm is by far the most popular algorithm for digital signatures.

The RSA signature algorithm is a derivative of the RSA public-key encryption algorithm. RSA code signing certificates are supported in a uniform manner by both Navigator and Internet Explorer; DSA certificates are not. Prior to Java plug-in 1.3, a developer needed to obtain (and pay for) two code signing certificates -- one that was compatible with Navigator and one that was compatible with Internet Explorer. With Java plug-in 1.3, a single RSA code-signing certificate works with both Navigator and Internet Explorer.

Versions of Java plug-in prior to 1.3 required that the user's plug-in be statically configured to map sets of permissions to potential signers. This approach was cumbersome and difficult to manage. Java plug-in 1.3 provides support for dynamic trust management, which uses the browser's native certificate API and certification authority database to verify the certificates of code signers and to assign permissions to the signers. This is accomplished in a dynamic manner when signed JAR files are processed by the plug-in. Dynamic trust management eliminates the need to statically assign permissions to code signers.

Port scanner example

To show how the security features of Java plug-in 1.3 work and to illustrate their benefits, we'll develop a simple port scanner and then deploy it as a signed applet.

A port scanner is a program that checks to see if a TCP port is open. Internet servers, such as Web servers and mail servers, listen on TCP ports for connections from clients, such as Web browsers and mail programs. Web servers typically listen on port 80 and Simple Mail Transport Protocol (SMTP) servers usually listen on port 25. You can use a port scanner to tell whether a particular Internet host supports a TCP service on a particular port.

Security Implications of Port Scanners
Our port scanner will attempt to make a TCP connection to a specified host and port to determine whether the host is listening on that port. The default applet security policy prevents an applet from making TCP connections to hosts other than the one from which it is loaded. This means that our applet will need to be trusted to make connections to arbitrary hosts. This is accomplished by giving it an appropriate permission. In order to enable the applet to be eligible for this permission, we'll sign it using an RSA code signing certificate.

See It In Operation
Before we get into the details of the applet's implementation, you may want to see work. That way you'll have an idea of what to expect. The applet can be run from http://www.toolery.com/tools/portscanner/scan.jsp. You'll need version 4 or later of Internet Explorer or version 3 or later of Navigator to run the applet.

When you open up the applet's page, your browser will check to see if the Java plug-in version 1.3 is installed. If not, it will prompt you to install it. The Internet Explorer installation is a little smoother than the Navigator installation. Internet Explorer will pop-up a simple installation wizard, while Navigator waits until you click the plug-in icon before it initiates the installation process.

Once you've installed the plug-in, it will download and attempt to run the SimpleScannerApplet from a JAR file named scan.jar. When your browser encounters the JAR file's signature, it will prompt you to determine whether or not you want to trust the signed code. The plug-in will provide you with a prompt to accept the signed applet. You can choose to accept it for the current browser session, always, or never. If you don't accept the certificate, the applet won't be able to perform sensitive operations, like scanning other hosts. You can also click More Info to get more information about the signer.

Screen shot.

When you click the More Info button the following dialog is shown.

Screen shot.

You can use the dialog to examine the contents of the signer's code signing certificate.

Assuming that you've accepted the certificate, the following applet will be displayed.

Screen shot.

Enter a host name and port number and click the Scan button to see if the specified port is open on the host. For example, if you scan OnJava.com on port 80, you'll get the following output because ONJava's Web server listens on port 80.

Screen shot.

However, if you scan OnJava.com on port 23, you'll get the following output. That's because port 23 (which is used for the telnet protocol) is closed on OnJava.com.

Screen shot.

Note that the scanner reports the host's IP address in parentheses. Some hosts may have more than one IP address. These hosts can have some Internet services run on one IP address and other services run on the other addresses. If you want to scan a host using a specific IP address, enter the host's address in the Host name or IP address field. If a host does not have a name, you can just refer to it by one of its IP addresses.

The SimpleScannerApplet Source Code
Now that you know what the scanner does, let's see how it works. Listing 1 shows the source code of the SimpleScannerApplet. It extends the Swing JApplet class and defines two inner classes: Scanner and ScannerException. The Scanner class handles the clicking of the Scan button and performs the actual scanning. The ScannerException class is used to throw scanner-related exceptions.

Listing 1. The SimpleScanner Applet

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.net.*;

public class SimpleScannerApplet extends JApplet {

    // Declare the GUI components used by the applet
    JTextField hostTextField = new JTextField("localhost",20);
    JTextField portTextField = new JTextField("80",5);
    JTextField resultsTextField = new JTextField(40);
    JButton scanButton = new JButton("Scan");
    JLabel hostLabel = new JLabel("Host name or IP address: ");
    JLabel portLabel = new JLabel("Port number: ");
    JLabel resultsLabel = new JLabel("Results: ");
    JPanel mainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));

    public SimpleScannerApplet() {
        // Layout the applet's components
        Border etched = BorderFactory.createEtchedBorder();
        // Add an etched border to the main panel
        mainPanel.setBorder(BorderFactory.createTitledBorder(etched, "Simple Port Scanner"));
        // Host and port fields in top panel
        topPanel.add(hostLabel);
        topPanel.add(hostTextField);
        topPanel.add(portLabel);
        topPanel.add(portTextField);
        // Scan button and result field in bottom panel
        bottomPanel.add(scanButton);
        bottomPanel.add(resultsLabel);
        bottomPanel.add(resultsTextField);
        // Add top and bottom panels to main panel
        mainPanel.add(topPanel);
        mainPanel.add(bottomPanel);
        // Set up the button's event handler
        scanButton.addActionListener(new Scanner());
        // Add the main panel to the applet's content pane
        getContentPane().add(mainPanel);
    }

    // The Scan button's event handler does the actual scanning
    private class Scanner implements ActionListener {

        // Declare fields used as scan parameters
        String host;
        InetAddress address;
        int port;
        String ip;

        // Handle the button's action event
        public void actionPerformed(ActionEvent ev) {
            out("Checking scan parameters ...");
            if(validParameters()) {
               out("Scanning ...");
               try {
                    // Try to connect to the host/port
                    Socket s = new Socket(address, port);
                    // No exception: SUCCESS
                    out("Port "+port+" is open on "+host+" ("+ip+").");
                    s.close();
                }catch(Exception ex) {
                    // Could not connect
                    if(ex instanceof SecurityException) out(ex.getMessage());
                    else out("Port "+port+" is closed on "+host+" ("+ip+").");
                }
            }
        }

        // Validate scan parameters
        private boolean validParameters() {
            try {
                host = hostTextField.getText();
                String portString = portTextField.getText();
                // Convert host name to an InetAddress object
                address = InetAddress.getByName(host);
                // Get the host's IP address
                ip = address.getHostAddress();
                // Convert the portString to an int
                port = Integer.decode(portString).intValue();
                // Make sure that it's in range
                if(port > 65535) throw new ScannerException("Invalid port.");
            }catch(Exception e) {
                // Handle any validation-related exceptions
                out(e.getMessage());
                return false;
            }
            return true;
        }

        // Convenience method for writing results
        private void out(String msg) {
            resultsTextField.setText(msg);
        }
    }

    // Used to identify invalid scan parameters
    private class ScannerException extends Exception {

        public ScannerException(String msg) {
            super(msg);
        }
    }
}

SimpleScannerApplet
The SimpleScannerApplet begins by declaring the GUI components that it displays. It uses Swing components for maximum compatibility across browser platforms.

// Declare the GUI components used by the applet
JTextField hostTextField = new JTextField("localhost",20);
JTextField portTextField = new JTextField("80",5);
JTextField resultsTextField = new JTextField(40);
JButton scanButton = new JButton("Scan");
JLabel hostLabel = new JLabel("Host name or IP address: ");
JLabel portLabel = new JLabel("Port number: ");
JLabel resultsLabel = new JLabel("Results: ");
JPanel mainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));

The SimpleScannerApplet constructor lays out the applet's GUI and creates an instance of Scanner to act as the Scan button's event handler.

public SimpleScannerApplet() {
  // Layout the applet's components
  Border etched = BorderFactory.createEtchedBorder();
  // Add an etched border to the main panel
mainPanel.setBorder(BorderFactory.createTitledBorder(etched,
"Simple Port Scanner"));
  // Host and port fields in top panel
  topPanel.add(hostLabel);
  topPanel.add(hostTextField);
  topPanel.add(portLabel);
  topPanel.add(portTextField);
  // Scan button and result field in bottom panel
  bottomPanel.add(scanButton);
  bottomPanel.add(resultsLabel);
  bottomPanel.add(resultsTextField);
  // Add top and bottom panels to main panel
  mainPanel.add(topPanel);
  mainPanel.add(bottomPanel);
  // Set up the button's event handler
  scanButton.addActionListener(new Scanner());
  // Add the main panel to the applet's content pane
  getContentPane().add(mainPanel);
}

Scanner
The Scanner inner class performs the actual scanning. It begins by declaring field variables that store the scan parameters.

// Declare fields used as scan parameters
String host;
InetAddress address;
int port;
String ip;

It then implements the actionPerformed() method of java.awt.event.ActionListener to handle the clicking of the Scan button. It uses the validParameters() method to determine whether the user supplied a valid host name/IP address and port number and to convert the users inputs into an InetAddress object and int port value.

A try-catch statement is used to catch any exceptions that result from the scanning. An attempt is made to create a TCP socket to the specified address and port. If the attempt is successful, then the port is identified as being open and then the socket is closed. If the attempt is unsuccessful, then an exception is thrown by the Socket constructor. The catch block handles this exception by checking to see if the exception is a SecurityException or some other type of exception.

If a SecurityException is thrown, then the message associated with the exception is displayed in the Results field. Otherwise, the port is identified as being closed for the specified host/IP address.

// Handle the button's action event
public void actionPerformed(ActionEvent ev) {
   out("Checking scan parameters ...");
   if(validParameters()) {
      out("Scanning ...");
      try {
         // Try to connect to the host/port
         Socket s = new Socket(address, port);
         // No exception: SUCCESS
         out("Port "+port+" is open on "+host+" ("+ip+").");
         s.close();
      }catch(Exception ex) {
         // Could not connect
         if(ex instanceof SecurityException) 
out(ex.getMessage());
         else 
out("Port "+port+" is closed on "
+host+" ("+ip+").");
      }
   }
}

The Scanner class defines two other methods that support the scanning process. The validParameters() method checks to see if the user has entered a valid host/IP address and port number and then converts those values from String objects to an InetAddress object and int port value.

// Validate scan parameters
private boolean validParameters() {
  try {
    host = hostTextField.getText();
    String portString = portTextField.getText();
    // Convert host name to an InetAddress object
    address = InetAddress.getByName(host);
    // Get the host's IP address
    ip = address.getHostAddress();
    // Convert the portString to an int
    port = Integer.decode(portString).intValue();
    // Make sure that it's in range
    if(port > 65535)
throw new ScannerException("Invalid port.");
  }catch(Exception e) {
    // Handle any validation-related exceptions
    out(e.getMessage());
    return false;
  }
  return true;
}

The out() method simplifies the display of output to the Results field.

// Convenience method for writing results
private void out(String msg) {
  resultsTextField.setText(msg);
}

ScannerException
The ScannerException class extends java.lang.Exception to provide a mechanism for identifying scanner-related exceptions.

// Used to identify invalid scan parameters
private class ScannerException extends Exception {

  public ScannerException(String msg) {
    super(msg);
  }
}

Why SimpleScannerApplet needs to be trusted
The SimpleScannerApplet needs to be trusted because it has the potential to make network connections to arbitrary Internet hosts. This capability is not permitted by the default applet security policy. Attempts to make connections to hosts other than the one from which the applet is loaded will result in the throwing of a SecurityException.

The following HTML file can be used to run the applet.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "DTD/xhtml1-transitional.dtd">
<html>
<head><title>SimpleScannerApplet</title></head>
<body>
<div style="text-align: center">
<h1>SimpleScannerApplet</h1>
<applet name="ScanApplet" code="SimpleScannerApplet.class" archive="scan.jar"
  width="600" height="125">
Java not supported.
</applet>
</div>
</body>
</html>

If you compile the apple and run it iwth appletviewer and the HTML above, you'll get the following output.

Screen shot.

You'll be able to scan your local host for open TCP ports because the appletviewer loads the applet from your local file system.

Screen shot.

However, if you try to scan other hosts, you'll encounter a security exception.

Screen shot.

Using SimpleScannerApplet with Java Plug-in 1.3
In order to be able to use SimpleScannerApplet to scan other hosts, we'll make it available as an RSA signed applet that executes via the Java plug-in 1.3. This involves the following steps.

  1. Package the applet classes as a JAR file.
  2. Obtain and install an RSA code signing certificate.
  3. Sign the JAR file using the RSA code signing certificate.
  4. Convert the scanner.htm file with Sun's HTML converter.
  5. Deploy the converted scanner.htm file and signed JAR file.

I'll walk you through each of the above.

Using the jar Tool
JAR files are used to archive the class files and other files used by applets and applications. JAR files are similar to Unix tar files and Windows zip files. The applet's classes must be packaged into a JAR file for code signing. Sun's keytool only signs JAR files and not individual class files.

The process of creating a JAR file is simple. Go to the directory where you compiled SimpleScannerApplet.java. You'll find the following .class files in this directory:

SimpleScannerApplet$Scanner.class
SimpleScannerApplet$ScannerException.class
SimpleScannerApplet.class
SimpleScannerApplet$1.class

Use the following command to create a JAR file named scan.jar that packages these files:

jar -cvf scan.jar *.class

The above command will generate the following output:

added manifest
adding: SimpleScannerApplet$1.class(in = 180) (out= 130)(deflated 27%)
adding: SimpleScannerApplet$Scanner.class(in = 2376) (out= 1249)(deflated 47%)
adding: SimpleScannerApplet$ScannerException.class(in = 453) (out= 276)(deflated 39%)
adding: SimpleScannerApplet.class(in = 2185) (out= 1096)(deflated 49%)

If you've used the Unix tar command, you'll notice the similarity between the jar syntax and the tar syntax.

Obtaining an RSA Code Signing Certificate
To sign scan.jar, you'll need an RSA code signing certificate. This step is the most complicated one in the process and can take days to weeks depending upon the certificate authority that you use.

Generating a Self-Signed Certificate

The first thing that you'll need to do is to create an RSA public-private key pair, a self-signed certificate, and a keystore to hold the key pair and the certificate. Fortunately, you can use Sun's keytool to accomplish this in a few simple steps.

Open up a command line window and enter the following command. (You can substitute your own alias for jamie. An alias is just a name by which you refer to your public-private key pair.)

keytool -genkey -alias jamie -keyalg rsa

The keytool will prompt you for information that will be used to generate your self-signed certificate. Substitute your information for the information that I entered (indicated in bold). Use your domain name in place of your first and last name. Also, select a password that is different than mine.

Enter keystore password: 123456
What is your first and last name?
[Unknown]: jaworski.com
What is the name of your organizational unit?
[Unknown]: Software development
What is the name of your organization?
[Unknown]: James Jaworski
What is the name of your City or Locality?
[Unknown]: Chula Vista
What is the name of your State or Province?
[Unknown]: CA
What is the two-letter country code for this unit?
[Unknown]: US
Is <CN=jaworski.com, OU=Software development, O=James Jaworski, L=Chula Vista, ST=CA, C=US> correct?
[no]: yes

Enter key password for <jamie>
(RETURN if same as keystore password): 123456

The keytool will generate the key pair and self-signed certificate and store them in a file named .keystore that is located in the directory specified by the user.home Java system property. You can use the following program to find the value of user.home.

public class DisplayUserHome {
public static void main(String[] args) {
System.out.println(System.getProperty("user.home"));
}
}

Generating a Certificate Signing Request

The next step in obtaining your certificate is to submit a certificate signing request (CSR) to a certificate authority (CA). A CSR is a request to have the CA sign your self-signed certificate (thereby legitimizing it). When a CA signs your certificate, it tells the world that it has verified your identity and the fact that the certificate belongs to you. That way, when others use your signed JAR files, they will have a high degree of assurance that your JAR files were, in fact, signed by you, and not someone else posing as you.

You use keytool to create a CSR as follows. Substitute your alias for jamie and your password for 123456.

keytool -certreq -alias jamie
Enter keystore password: 123456
-----BEGIN NEW CERTIFICATE REQUEST-----
MIIBvzCCASgCAQAwfzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRQwEgYDVQQHEwtDaHVsYSBW
aXN0YTEXMBUGA1UEChMOSmFtZXMgSmF3b3Jza2kxHTAbBgNVBAsTFFNvZnR3YXJlIGRldmVsb3Bt
ZW50MRUwEwYDVQQDEwxqYXdvcnNraS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPb5
Yt3M48Lwf2OjVYBG8+89HF35JB/YpHyyHt4DTohFeS2KbAQEvI03FGtG9KXZpzgumBttxhfiqRF8
6bF2GO8eDK1COubJ6ckEZziSlTUFYoLXqmLTui85TApXB8kJzj+SygQ2OP0APtVy6E3dq66izl89
RUzMdTH60QPxtbc5AgMBAAGgADANBgkqhkiG9w0BAQQFAAOBgQBEtAffkQVHRB8bGsm6yP7Sb8zZ
ert3h8pXdBlFjtC+SZZxUQq/rOGyqh1H320ZqJlcnmRBrgQth3KDh3WPXposnTt4eHwJKyK/whUk
0ucbkDo3cdidLLg4/as0QsVmje7udzcCdnCX6NuQqjvAayaOviU1i5GvN8ALbpWwbrf0uw==
-----END NEW CERTIFICATE REQUEST-----

The output of the keytool is your CSR. Redirect or copy it to a text file.

Submitting Your CSR to a Certificate Authority

Now that you have a CSR, you need to get it signed by a recognized certificate authority. Although there are a number of CAs that will sign your certificate, I would suggest that you use Thawte Consulting or Verisign because their certificates are recognized by all browsers and have been proven to work with the Java plug-in 1.3. Of the two, I recommend Thawte because they provide excellent service and their certificates are about half the price of Verisign's.

If you decide to use Thawte, you can find out more information about obtaining an RSA code signing certificate. If you use Verisign, check out their information.

Importing Your Signed Certificate

When your CA has verified your identity and signed your certificate. It will return a certificate or certificate chain in a standard text format (such as PKCS #7). The following is an example.

-----BEGIN PKCS #7 SIGNED DATA-----
MIIGhwYJKoZIhvcNAQcCoIIGeDCCBnQCAQExADALBgkqhkiG9w0BBwGgggZcMIID
QTCCAqqgAwIBAgIDB9BsMA0GCSqGSIb3DQEBBAUAMIHEMQswCQYDVQQGEwJaQTEV
MBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xHTAbBgNV
BAoTFFRoYXd0ZSBDb25zdWx0aW5nIGNjMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u
IFNlcnZpY2VzIERpdmlzaW9uMRkwFwYDVQQDExBUaGF3dGUgU2VydmVyIENBMSYw
JAYJKoZIhvcNAQkBFhdzZXJ2ZXItY2VydHNAdGhhd3RlLmNvbTAeFw0wMTAxMjIy
MzAyNDNaFw0wMjAxMjIyMzAyNDNaMIGHMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
Q2FsaWZvcm5pYTEUMBIGA1UEBxMLQ2h1bGEgVmlzdGExFzAVBgNVBAoTDkphbWVz
IEphd29yc2tpMR0wGwYDVQQLExRTb2Z0d2FyZSBkZXZlbG9wbWVudDEVMBMGA1UE
AxMMamF3b3Jza2kuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM6Wku
ZYeoaEQVZWbKBLxbnID4N3wcDVsYAPDI/nIY5dnC2bFGyHNGCxEmeiAYdjb+rHuN
g2uhycZ1TtRNBOf9hnOw+NMyHAXytsIEf7wrf/H0WoAyvbZeG+sXrVMRpJJeCem0
BDAdairYkly/fdWIujlIa7mwVEBK9csgfIcutQIDAQABo3wwejAfBgNVHSUEGDAW
BggrBgEFBQcDAwYKKwYBBAGCNwIBFjARBglghkgBhvhCAQEEBAMCBBAwHQYDVR0E
BBYwFDAOMAwGCisGAQQBgjcCARYDAgeAMBcGA1UdEQQQMA6CDGphd29yc2tpLmNv
bTAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBBAUAA4GBADQdapQceZZ++qQJdSVT
i7wNFjDI72RkQzvGNWzmDg8mfIa7ZxsVCBblvOrCu9Ow8m1H+IJdyLTKLllXgo5M
zRIk8eB1+AY2H1MRI+G6fTudGCJbdfXS+G7ceGLf9HZ32gVIWvEJ682ihnefPsHE
W3WW05VtaTKidC0WAZAoe4h/MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQF
ADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UE
BxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYG
A1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQ
VGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRo
YXd0ZS5jb20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkG
A1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBU
b3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2Vy
dGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNl
cnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20w
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC
2oQl/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNk
CXDF/rFrKbYvScg71CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0
e982OsK1ZiIS1ocNAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
AQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllD
fU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpa
PNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEcxAA==
-----END PKCS #7 SIGNED DATA-----

Once you receive your signed certificate from your CA, you need to import it into your keystore using keytool. I stored my certificate in the file thawtecert.txt before I imported it.

keytool -import -alias jamie -file thawtecert.txt
Enter keystore password: 123456
Enter key password for <jamie>: 123456

Top-level certificate in reply:

Owner: EmailAddress=server-certs@thawte.com, CN=Thawte Server CA, OU=Certification Services Division, O=Thawte Consulting cc, L=Cape Town, ST=Western Cape, C=ZA

Issuer: EmailAddress=server-certs@thawte.com, CN=Thawte Server CA, OU=Certification Services Division, O=Thawte Consulting cc, L=Cape Town, ST=Western Cape, C=ZA
Serial number: 1
Valid from: Wed Jul 31 17:00:00 PDT 1996 until: Thu Dec 31 15:59:59 PST 2020
Certificate fingerprints:
MD5: C5:70:C4:A2:ED:53:78:0C:C8:10:53:81:64:CB:D0:1D
SHA1: 23:E5:94:94:51:95:F2:41:48:03:B4:D5:64:D2:A3:A3:F5:D8:8B:8C

... is not trusted. Install reply anyway? [no]: yes
Certificate reply was installed in keystore

That's all you need to do to obtain and install your RSA code signing certificate. Now let's sign the scan.jar file.

Using Your Certificate to Sign JAR Files
If you got to this point and you still don't have an RSA code signing certificate, don't worry, I'll show you how to sign scan.jar using my certificate.

To sign scan.jar, use the following jarsigner command. Substitute your alias for jamie.

jarsigner scan.jar jamie
Enter Passphrase for keystore: 123456
Enter key password for jamie: 123456

The jarsigner tool will replace scan.jar with a signed version of the same file. The signature will use the public-private key pair identified by the alias (jamie) and the signed certificate associated with the key pair (the one that you received from the CA).

You can also verify the JAR files signature using jarsigner:

jarsigner -verify scan.jar

If your scan.jar is properly signed it will respond with "jar verified." Otherwise, it will respond with a message indicating that the signature is missing or invalid.

Using HTMLConverter
Now that you have a signed JAR file, you need to convert any HTML files that reference the applet so that the applet executes with the Java plug-in. You do this using Sun's HTML converter.

The HTML converter is packaged as a .zip file. Unzip the file to a directory on your system.

In the converter/classes directory, you'll see two shell files (HTMLConverter.bat and HTMLConverter.sh) that are used to execute the HTML converter. Use HTMLConverter.bat if you're running Windows and HTMLConverter.sh if you're running Linux/Solaris.

When you run the shell file, the following window will open.

Screen shot.

Select the directory containing scanner.htm and then click the Convert button. The contents of the converted scanner.htm will appear similar to the following.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"DTD/xhtml1-transitional.dtd">
<html>
<head><title>SimpleScannerApplet</title></head>
<body>
<div style="text-align: center">
<h1>SimpleScannerApplet</h1>
<!--"CONVERTED_APPLET"-->
<!-- CONVERTER VERSION 1.3 -->
<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
WIDTH = "600" HEIGHT = "125" NAME = "ScanApplet"
codebase="http://java.sun.com/products/plugin/1.3/jinstall-13-win32.cab#Version=1,3,0,0">
<PARAM NAME = CODE VALUE = "SimpleScannerApplet.class" >
<PARAM NAME = ARCHIVE VALUE = "scan.jar" >
<PARAM NAME = NAME VALUE = "ScanApplet" >
<PARAM NAME="type" VALUE="application/x-java-applet;version=1.3">
<PARAM NAME="scriptable" VALUE="false">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.3"
CODE = "SimpleScannerApplet.class" ARCHIVE = "scan.jar"
NAME = "ScanApplet" WIDTH = "600" HEIGHT = "125"
scriptable=false pluginspage="http://java.sun.com/products/plugin/1.3/plugin-install.html">
<NOEMBED></COMMENT>
Java not supported.

</NOEMBED></EMBED>
</OBJECT>

<!--
<APPLET CODE = "SimpleScannerApplet.class" ARCHIVE = "scan.jar" WIDTH = "600" HEIGHT = "125" NAME = "ScanApplet">
Java not supported.

</APPLET>
-->
<!--"END_CONVERTED_APPLET"-->

</div>
</body>
</html>

Deploying the Signed Applet
Having created and signed scan.jar and converted scanner.htm using HTML converter, you're ready to deploy these files. Put scan.jar in the same directory as scanner.htm. You can also run the scanner from your local file system using Navigator or Internet Explorer. In fact, it's a good idea to do so, just to make sure that everything works as it should. The following screen capture shows the scanner working in Internet Explorer 5.5.

Screen shot.

Jamie Jaworski is a Java security expert and author, focused on cryptography and such.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.