|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 6 of 6
In keeping with our theme, the Java Secure Socket Extension (JSSE) supplements Java core security just as do JAAS and JCE. JSSE enables secure Internet communications by providing a framework supporting the SSL and TLS protocols, both designed to protect the privacy and integrity of data while it is transferred across the network. Unlike using JCE, the key agreement and the cipher-suite agreements happen transparently over SSL.
Table 2 illustrates the algorithms and the key lengths used by JSSE for key agreement and/or authentication.
| Algorithm | Valid Key Lengths(bits) |
| RSA public key | 2,048 or 512 |
| Diffie-Hellman public key | 1,024 or 512 |
| DSA public key | 2,048 |
Table 3 illustrates the algorithms and the key lengths used by JSSE for bulk encryption and decryption. Note: public key algorithms tend to be much slower than secret key algorithms; therefore, they are used only in the initial phase of key agreement and authentication, as we saw earlier.
| Algorithm | Valid Key Length(bits) |
| RC4 | 128 or 128 (40 effective) |
| DES | 64 (56 effective) or 64 (40 effective) |
| Triple DES | 192 (112 effective) |
The reference implementation, SunJSSE, provides some limited support for accessing PKCS12 keys as well. PKCS12 keys can be used in the keytool command with the -storetype option set to pkcs12. The default supports X.509 formats.
JSSE classes can be found in the following packages:
javax.netjavax.net.ssljavax.security.certThe main classes comprise:
SSLSocketSSLServerSocketSocketFactoryServerSocketFactorySSLSocketFactorySSLServerFactoryThe class javax.net.ssl.SSLSocket stems from the java.net.Socket class. It supports all of the standard socket methods and adds additional methods specific to secure sockets. The SSLServerSocket class creates server sockets. The method createSocket() can create instances of sockets. Alternatively, the method accept() can also create server-side sockets.
The class SSLSocketFactory, a concrete implementation of the abstract SocketFactory, acts as a factory for creating secure sockets. The SSLServerSocketFactory class creates server sockets. We will use its getDefault() static method to obtain an instance of the class.
Several other support classes and interfaces exist, as detailed in the API documentation provided with the kit.
The programs use a keyStore and a trustStore for the purposes of authentication, provided via the properties javax.net.ssl.keyStore and javax.net.ssl.trustStore, respectively. These work in tandem, that is, a key entry amongst the keyStore entries should correspond to an entry in the trustStore entry on the other side. For example, a keyEntry, duke on the server side, should have a trustedCertEntry for the same key on the client side for server authentication to succeed.
The outline for the server code looks like:
import javax.net.ssl.*;
// Provide entries for keyStore which contains server key
// Create an instance of the factory
SSLServerSocketFactory sslSrvFact = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
// Create a server socket
SSLServerSocket s =(SSLServerSocket)sslSrvFact.createServerSocket(port);
// Accept connections
SSLSocket in = (SSLSocket)s.accept();
Here's the corresponding client code:
import javax.net.ssl.*;
// Provide entries for trustStore to enable server authentication
// Create an instance of the factory
SSLSocketFactory sslFact =(SSLSocketFactory)SSLSocketFactory.getDefault();
// Create a socket and connect
SSLSocket s = (SSLSocket)sslFact.createSocket(host, port);
A session key and a cipher suite are negotiated transparently for use during the session as long as the handshake process completes.
The following program pairs enable socket communications between systems without the use of SSL. Using a simple program like
snoop on Unix systems, you can see the communications in the clear. Later, we will see how this problem can be avoided by using
JSSE.
Below you'll find the code for the server. It waits for a connection, communicates once, then terminates. The examples use port 8181. Any other free port can be used as far as these examples are concerned:
import java.io.*;
import java.net.*;
public class HelloServer {
public static void main(String[] args) {
try {
ServerSocket s = new ServerSocket(8181);
Socket in = s.accept();
PrintWriter out = new PrintWriter (in.getOutputStream(),
true);
out.println("Hello on a socket");
in.close();
} catch (Exception e) {}
}
}
You'll find the corresponding client code below. 127.0.0.1 is the localhost. Using it in the program indicated below enables both the server and the client to run on the same machine, providing an
argument will enable a connection to the respective server, if possible:
import java.io.*;
import java.net.*;
public class HelloClient {
public static void main(String[] args) {
try {
Socket s = new Socket(args.length == 0 ? "127.0.0.1" : args[0], 8181);
OutputStream out = s.getOutputStream();
BufferedReader in = new BufferedReader (
new InputStreamReader(s.getInputStream()));
String str = in.readLine();
System.out.println("Socket message: " + str);
in.close();
} catch (Exception e) {}
}
}
From a programming viewpoint, it's easy to convert these simple programs to use SSL. To do so, we employ the javax.net.ssl package and the relevant classes. The code for the server and client looks as below, with the bold indicating changes made to the previous programs. The server uses the SSLServerSocket and SSLServerSocketFactory classes for SSL:
import java.io.*;
import java.security.*;
import javax.net.ssl.*;
public class HelloServerSSL {
public static void main(String[] args) {
SSLServerSocket s;
try {
Security.addProvider(
new com.sun.net.ssl.internal.ssl.Provider());
SSLServerSocketFactory sslSrvFact =
(SSLServerSocketFactory)
SSLServerSocketFactory.getDefault();
s =(SSLServerSocket)sslSrvFact.createServerSocket(8181);
SSLSocket in = (SSLSocket)s.accept();
PrintWriter out = new PrintWriter (in.getOutputStream(),
true);
out.println("Hello on a SSL socket");
in.close();
} catch (Exception e) {
System.out.println("Exception" + e);
}
}
}
Next, you'll find the corresponding client code:
import java.io.*;
import java.security.*;
import javax.net.ssl.*;
public class HelloClientSSL {
public static void main(String[] args) {
try {
Security.addProvider(
new com.sun.net.ssl.internal.ssl.Provider());
SSLSocketFactory sslFact =
(SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket s =
(SSLSocket)sslFact.createSocket(args.length == 0 ? "127.0.0.1" : args[0], 8181);
OutputStream out = s.getOutputStream();
BufferedReader in = new BufferedReader (
new InputStreamReader(s.getInputStream()));
String str = in.readLine();
System.out.println("Socket message: " + str);
in.close();
} catch (Exception e) {
System.out.println("Exception" + e);
}
}
}
Below, I indicate the command line options for both the server and the client, as well as the command line options used to
run the program for providing the keyStore, trustStore entries, and the corresponding output. jilebi is the server machine and jamoon is the client. If you need more details about the underlying SSL protocol or diagnostic information, substitute all for none in the command line below. The keyStore and testkeys in the first entry, and truststore and samplecacerts in the second entry are provided as part of the samples in the JSSE installation. These should be substituted with production-quality
entries after the testing and debugging cycle.
The following command line was used to create SSL sockets on the server:
jilebi> java -Djavax.net.debug=none -Djavax.net.ssl.keyStore=testkeys -Djavax.net.ssl.keyStorePassword=passphrase HelloServerSSL
Here's the corresponding command line on the client side:
jamoon> java -Djavax.net.debug=none -Djavax.net.ssl.trustStore=samplecacerts HelloClientSSL jilebi Socket message: Hello on a SSL socket
The keyStore entries in the server enable server authentication by using the key, duke. Clients that do not have a trusted entry for the certificate authority (CA) used to sign the corresponding public key cannot
authenticate the server and will fail to connect. The client program uses the trustStore entry for the purposes of trusting the key. The trustStores are checked in the following order:
trustStore indicated in the javax.net.ssl.trustStore system property
jssecacerts file in the directory <java-home>/lib/securitycacerts file in the directory <java-home>/lib/security, which is a standard part of the JRE installation; this file contains certificates of most CAs
For example, to use the code signing certificates that we used in Part 3, we merely specify the newkeyStore entry in the server as indicated below:
jilebi> java -Djavax.net.debug=none -Djavax.net.ssl.keyStore=rags.p12 -Djavax.net.ssl.keyStorePassword=changeit -Djavax.net.ssl.keyStoreType=pkcs12 HelloServerSSL
Notice that we used the pkcs12 format rather than the default JKS format. JSSE provides limited support for a pkcs12 key and requires an option in the <java-home>/lib/security/java.security file to support pkcs12 entries:
security.provider.3=com.sun.net.ssl.internal.ssl.Provider
When using keys signed by standard CAs, the trustStrore entry is not needed on the client side, as the CA used to sign the public key is trusted by default as indicated in the cacerts file.
If you desire client authentication (optional by default), add a line to the server program, as indicated below:
import java.io.*;
import java.security.*;
import javax.net.ssl.*;
public class HelloServerSSL {
public static void main(String[] args) {
SSLServerSocket s;
try {
Security.addProvider(
new com.sun.net.ssl.internal.ssl.Provider());
SSLServerSocketFactory sslSrvFact =
(SSLServerSocketFactory)
SSLServerSocketFactory.getDefault();
s =(SSLServerSocket)sslSrvFact.createServerSocket(8181);
s.setNeedClientAuth(true);
SSLSocket in = (SSLSocket)s.accept();
PrintWriter out = new PrintWriter (in.getOutputStream(),
true);
out.println("Hello on a SSL socket");
in.close();
} catch (Exception e) {
System.out.println("Exception" + e);
}
}
}
The previous command line options do not work since the client will need to send a key that can be trusted by the server to
enable client authentication. Both the server and the client will have to provide the keyStore and trustStore entries to enable mutual authentication. A sample command line is indicated below:
jilebi> java -Djavax.net.debug=none -Djavax.net.ssl.keyStore=testkeys -Djavax.net.ssl.keyStorePassword=passphrase -Djavax.net.ssl.trustStore=samplecacerts HelloServerSSL
Next, we see the corresponding command line on the client:
jamoon> java -Djavax.net.debug=none -Djavax.net.ssl.keyStore=testkeys -Djavax.net.ssl.keyStorePassword=passphrase -Djavax.net.ssl.trustStore=samplecacerts HelloClientSSL jilebi
As a final example, we will look at how a downloaded applet can initiate an SSL connection to any host using the Java Plug-in
(see "Sidebar 2: Java Plug-in Primer"). We will modify the writeFile.java, as shown later. We must set up the client system by:
samplecacerts to <java-home>/lib/security as jssecacerts. Alternatively, we could set up an entry -Djavax.net.ssl.trustStore in the Java Run Time Parameters to point to the appropriate file, in the Java Plug-in panel.
-DwriteFileSSL.hostname to the desired host for making the SSL connection. If not provided, that will initiate an SSL connection to the server running
on the same system as the applet, as illustrated in Figure 7.
Figure 7. Set options in the plugin control panel
Later, we will modify the HelloServerSSL.java as HelloServerSSLMultiple.java to be able to accept multiple connections. Make sure that this server is running on the system to which the applet tries
to initiate an SSL connection.
writeFileSSL.java, a modification of the writeFile.java, is shown below. It's an applet that runs under the Java Plug-in and tries to make an SSL connection to any host:
/**
* By default, this raises a security exception as an applet.
*
*
* @version JDK 1.2
* @author Marianne Mueller
* @Modified by Raghavan Srinivas[Rags]
*/
import java.awt.*;
import java.io.*;
import java.lang.*;
import java.applet.*;
import java.security.*;
import javax.net.ssl.*;
public class writeFileSSL extends Applet {
String myFile = "/tmp/foo";
File f = new File(myFile);
DataOutputStream dos;
public void init() {
String osname = System.getProperty("os.name");
if (osname.indexOf("Windows") != -1) {
myFile="C:" + File.separator + "tmpfoo";
}
}
public void paint(Graphics g) {
try {
// If the following property is null just connect to localhost
String hostname = System.getProperty("writeFileSSL.hostname");
if (hostname == null)
hostname = "127.0.0.1"; //localhost
Security.addProvider(
new com.sun.net.ssl.internal.ssl.Provider());
SSLSocketFactory sslFact =
(SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket s =
(SSLSocket)sslFact.createSocket(hostname, 8181);
OutputStream out = s.getOutputStream();
BufferedReader in = new BufferedReader (new InputStreamReader(s.getInputStream()));
String str = in.readLine();
s.close();
dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(myFile),128));
dos.writeBytes("Cats can still hypnotize you when you least expect it\n");
if (str != null)
dos.writeBytes(str);
dos.flush();
dos.close();
g.drawString("Successfully wrote to the file named " + myFile + " -- go take a look at it!", 10, 10);
}
catch (SecurityException e) {
g.drawString("writeFile: caught security exception", 10, 10);
}
catch (IOException ioe) {
g.drawString("writeFile: caught i/o exception", 10, 10);
}
}
public static void main(String args[]) {
Frame f = new Frame("writeFile");
writeFileSSL writefile = new writeFileSSL();
writefile.init();
writefile.start();
f.add("Center", writefile);
f.setSize(300, 100);
f.show();
}
}
Next, we see the code allowing HelloServerSSLMultiple to accept multiple connections. It serves multiple connections by spawning a thread to handle the connection:
import java.io.*;
import java.security.*;
import javax.net.ssl.*;
public class HelloServerSSLMultiple {
public static void main(String[] args) {
SSLServerSocket s=null;
int i=1;
try {
Security.addProvider(
new com.sun.net.ssl.internal.ssl.Provider());
SSLServerSocketFactory sslSrvFact =
(SSLServerSocketFactory)
SSLServerSocketFactory.getDefault();
s =(SSLServerSocket)sslSrvFact.createServerSocket(8181);
while(true) {
SSLSocket in = (SSLSocket)s.accept();
Thread t = new SocketHandler(in, i++);
t.start();
}
}
catch (Exception e) {
System.out.println("Exception" + e);
}
}
}
class SocketHandler extends Thread {
private SSLSocket in;
private int connection;
public SocketHandler (SSLSocket in, int connection) {
this.in = in;
this.connection = connection;
}
public void run() {
try {
PrintWriter out = new PrintWriter (in.getOutputStream(),
true);
out.println("Hello on a SSL socket : You are socket #" + connection);
in.close();
} catch (Exception e) {
System.out.println("Exception" + e);
}
}
}
We will sign the code, modify the .html file, and invoke the applet we studied in Part 3. As illustrated before, ensure that the server is running on the system to which the applet tries to initiate an SSL connection.
Running the code should generate the output (seen below) in the temporary file -- /tmp/foo or c:\tmpfoo -- if everything worked successfully. The number will keep going up by one for every time a new SSL connection is made in
the paint() method of the applet:
Cats can still hypnotize you when you least expect it Hello on a SSL socket : You are socket #1
In the JSSE examples above we saw how to use SSL, starting with programs that use regular sockets and ending with an applet
that initiates a connection to any host running the SSL server. The sample programs provided as part of the JSSE 1.0.2 kit
illustrate examples of using the https URL class, RMI sockets, and so on.
To test the results, follow the installation instructions in the Readme file, then run the applet. (Note: you can find all of the applet-related files in the /security/ directory.)
In Parts 1 and 2 of this series I introduced Java security, starting with how it has evolved. In Part 3, I combined the concepts with get-your-hands-dirty applet code, a frequently misunderstood aspect of Java security. In this article I discussed the optional packages that enhance Java core security with some simple examples.
My aim throughout this series was to provide simple examples to drive home the concepts. As an exercise, I've left it to you to build more complex and realistic solutions. I hope any reader who wishes to build more complex solutions will benefit from a knowledge of these simple examples and concepts.
Read more about Core Java in JavaWorld's Core Java section.
writeFileSSL.java source file, associated with this article, go to