You are on page 1of 16

Secure Internet Programming with Java 2, Standard Edition

(J2SE) 1.4

Print-Iriendly Version





Articles Index

Part I: The Server Side
By Qusay H. Mahmoud
November 2002
Any inIormation transmitted over computer networks, or the Internet,
is subject to interception. Some oI that inIormation could be sensitive,
such as credit card numbers and other personal data. To make the
Internet more useIul in an enterprise setting and Ior e-commerce,
applications must protect their users' inIormation, using encryption,
authentication, and secure communications protocols. The secure
Hypertext TransIer Protocol (HTTPS), which is HTTP over the Secure
Sockets Layer (SSL), is already being used successIully Ior e-
commerce applications.
The Java Secure Socket Extension (JSSE), which is a set oI Java
packages that enable secure Internet communications, is a Iramework
and 100 Pure Java implementation oI the Secure Socket Layer
(SSL). These packages enable you ,the Java developer, to develop
secure network applications that Ieature the secure passage oI data
between a client and a server running any application protocol, such as
HTTP, FTP, Telnet, or NTTP, over TCP/IP.
The good news is that JSSE has been integrated into the Java 2 SDK,
Standard Edition, version 1.4 (J2SE 1.4). This means iI you have J2SE
1.4 installed, then you can build secure Internet applications based on
SSL without downloading any additional packages. This two-part
series oI articles provides a hands-on tutorial explaining how to
develop secure Internet applications Ior today's and tomorrow's
market. This article is concerned with the server-side and the next
article will be concerned with the client-side. This article starts by
presenting a detailed overview oI SSL, then shows you how to:
O Use the JSSE APIs
O Integrate SSL into your existing client-server applications
O Develop a simple HTTP server
O Revise the HTTP server to handle HTTPS requests
O Generate your own certiIicates using the keytool delivered with
J2SE

O Develop, conIigure, and run a secure HTTP server
verview of SSL
The SSL protocol, which was developed by Netscape in 1994, allows
clients (Web browsers, typically) and HTTP servers to communicate
over a secure connection. It oIIers encryption, source authentication,
and data integrity as means to protect inIormation exchanged over
insecure, public networks. There are several versions oI SSL: SSL 2.0
has security weaknesses and is hardly used today; SSL 3.0 is
universally supported; and Iinally the Transport Layer Security (TLS),
which is an improvement on SSL 3.0, has been adopted as an Internet
standard and is supported by almost all recent soItware.
Encryption protects data Irom unauthorized use by converting it to an
apparently meaningless Iorm beIore transmission. The data is
encrypted by one side (the client or the server), transmitted, decrypted
by the other side, then processed.
Source authentication is a method oI veriIying the data sender's
identity. The Iirst time a browser or other client attempts to
communicate with a Web server over a secure connection, the server
presents the client with a set oI credentials in the Iorm oI a .ertifi.ate.
CertiIicates are issued and validated by trusted authorities known
as .ertifi.ation authorities (CAs). A certiIicate represents the public-
key identity oI a person. It is a signed document that says: certify
that the public key in this document belongs to the entity named in this
document. Signed (certificate authority). Well-known CAs
include Verisign, Entrust, and Thawte. Note that the certiIicates used
with SSL/TLS today are X.509 certiIicates.
Data integrity reIers to means oI ensuring that data has not been
modiIied in transit.
SSL and the TCP/IP Proto.ol Sta.
As the name Secure Sockets Layer indicates, SSL connections act like
sockets connected by TCP. ThereIore, you can think oI SSL
connections as secure TCP connections since the place Ior SSL in the
protocol stack is right above TCP and below the application layer as
shown in Figure 1. It is important to note, however, that SSL doesn't
support some oI the TCP Ieatures such as out-oI-band data.

igure 1. SSL and the TCP/P protocol stack
egotiable En.ryption
Among the Ieatures oI SSL that have made it the de Iacto standard
vehicle Ior secure e-commerce transactions is its support Ior
negotiable encryption and authentication algorithms. The designers oI
SSL realized that not all parties will use the same client soItware and
consequently not all clients will include any particular encryption
algorithm. The same is true Ior servers. The client and server at the
two ends oI a connection negotiate the encryption and decryption
algorithms (cipher suites) during their initial handshake. It may turn
out that they do not have suIIicient algorithms in common, in which
case the connection attempt will Iail.
Note that while SSL allows both the client and the server to
authenticate each other, typically only the server is authenticated in
the SSL layer. Clients are customarily authenticated in the application
layer, through the use oI passwords sent over an SSL-protected
channel. This pattern is common in banking, stock trading, and other
secure Web applications.
The SSL full handshake protocol is illustrated in Figure 2. It shows the
sequences oI messages exchanged during the SSL handshake.

igure 2. SSL handshake protocol
These messages mean:
1. ClientHello: The client sends the server inIormation such as SSL
protocol version, session id, and cipher suites inIormation such
cryptographic algorithms and key sizes supported.
2. ServerHello: The server chooses the best cipher suite that both the
client and server support and sends this inIormation to the client.
3. Certificate: The server sends the client its certiIicate which
contains the server's public key. While this message is optional, it
is used when server authentication is required. In other words, it is
used to conIirm the server's identity to the client.
4. Certificate Request: This message is sent only iI the server
requires the client to authenticate itselI. Most e-commerce
applications do not require the client to authenticate itselI.
5. Server Key Exchange: This message is sent iI the certiIicate,
which contains the server's public key, is not suIIicient Ior key
exchange.
6. ServerHelloDone: This message inIorms the client that the server
Iinished the initial negotiation process.
7. Certificate: This message is sent only iI the server requested the
client to authenticate itselI.
8. Client Key Exchange: The client generates a secret key to be
shared between the client and server. II the Rivest-Shamir-
Adelman (RSA) encryption algorithm is used, the client encrypts
the key using the server's public key and sends it to the server. The
server uses its private or secret key to decrypt the message and
retrieves the shared secret key. Now, client and server share a
secret key that has been distributed securely.
9. Certificate Jerify: II the server requested to authenticate the client,
this message allows the server to complete the authentication
process.
10. Change Cipher Spec: The client asks the server to change to
encrypted mode.
11. inished: The client tells the server it is ready Ior secure
communication.
12. Change Cipher Spec: The server asks the client to change to
encrypted mode.
13. inished: The server tells the client it is ready Ior secure
communication. This marks the end oI the SSL handshake.
14. Encrypted Data: The client and server can now start exchanging
encrypted messages over a secure communication channel.
SSE
The Java Secure Socket Extension (JSSE) provides a Iramework and a
100 Pure Java implementation oI the SSL and TLS protocols. It
provides mechanisms Ior data encryption, server authentication,
message integrity, and optional client authentication. What is
Iascinating about JSSE is that is abstracts the complex underlying
cryptographic algorithms and thus minimizes the risk oI creating
subtle and dangerous security vulnerabilities. In addition, it makes the
development oI secure applications quite simple by allowing you to
seamlessly integrate SSL into your applications. The JSSE Iramework
is capable oI supporting many diIIerent secure communication
protocols such as SSL 2.0 and 3.0 and TLS 1.0, but the J2SE v1.4.1
implements SSL 3.0 and TLS 1.0.
Programming with SSE
The JSSE APIs supplement the java.security and java.net packages by
providing extended networking socket classes, trust and key managers,
and a socket Iactory Iramework Ior encapsulating socket creation
behavior. These classes are included in the
packages javax.net and javax.net.ssl.
SSLSo.et and SSLServerSo.et
The javax.net.ssl.SSLSocket is a subclass oI the java.net.Socket class.
ThereIore, it supports all the standard Socket methods and adds
additional methods speciIic to secure sockets.
Thejavax.net.ssl.SSLServerSocket class is analogous to
the SSLSocket class except that it is used to create server sockets.
Creating an instance oI SSLSocket can be done in two ways:
1. As an instance oI SSLSocketFactory by invoking one oI
the createSocket methods on that class.
2. Through the accept method on the SSLServerSocket.
SSLSo.etFa.tory and SSLServerSo.etFa.tory
The javax.net.ssl.SSLSocketFactory class is an object Iactory Ior
creating secure sockets, and the javax.net.ssl.SSLServerSocketFactory is
an object Iactory Ior creating server sockets.
An SSLSocketFactory instance can be obtained in two ways:
1. Get the deIault Iactory by calling SSLSocketFactory.getDefault.
2. Construct a new Iactory with speciIied conIigured behavior.
Note that the deIault Iactory is conIigured to enable server
authentication only.
aing Existing Client/Server Appli.ations Se.ure
Incorporating SSL into existing client/server applications to make
them secure can be easily done using a Iew lines oI JSSE code. The
lines highlighted in bold in the Iollowing example show the code
necessary to make a server secure:
import java.io.*;
import javax.net.ssI.*;

public class Server {
int port = portNumber;
SSLServerSocket server;
try {
SSLServerSocketFactory factory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefauIt();
server = (SSLServerSocket)
factory.createServerSocket(portNumber);
SSLSocket cIient = (SSLSocket)
server.accept();

// Create input and output streams as usual
// send secure messages to client through the
// output stream
// receive secure messages from client through
// the input stream
} catch(Exception e) {
}
}

The lines highlighted in bold in the Iollowing example show the code
necessary to make a client secure:
import java.io.*;
import javax.net.ssI.*;

public class Client {
...
try {
SSLSocketFactory factory = (SSLSocketFactory)
SSLSocketFactory.getDefauIt();
server = (SSLServerSocket)
factory.createServerSocket(portNumber);
SSLSocket cIient = (SSLSOcket)
factory.createSocket(serverHost, port);

// Create input and output streams as usual
// send secure messages to server through the
// output stream receive secure
// messages from server through the input stream
} catch(Exception e) {
}
}



SunSSE Provider
The J2SE v1.4.1 release comes with a JSSE provider, SunJSSE, that
comes installed and pre-registered with the Java Cryptography
Architecture. Think oI the SunJSSE provider as the name oI the
implementation. It supplies implementations oI the SSL v3.0 and TLS
v1.0 as well as most common SSL and TLS cipher suites. II you wish
to Iind the list oI cipher suites that are supported by your
implementation oI SSL (SunJSSE in this case), make a call to
the getSupportedCipherSuites method in SSLSocket. Not all oI these
cipher suites, however, might be enabled. To Iind out which ones are
enabled, call the method getEnabledCipherSuites. The list can be
modiIied by calling setEnabledCipherSuites.
A Complete Example
I Iound that the most complex issue when working with JSSE is
related to system conIiguration and managing certiIicates and keys.
Throughout this example, I demonstrate how to develop, conIigure,
and run a complete HTTP server application that supports the GET
request method.
verview of HTTP
The Hypertext TransIer Protocol (HTTP) is a request-reply application
protocol. This protocol supports a Iixed set oI methods such
as ET, POST, PUT, DELETE, etc. The ET method is commonly used
to request resources Irom a Web server. Here are two sample GET
requests:
ET / HTTP/1.0 <empty-line>
ET /names.html HTTP/1.0 <empty-line>
Inse.ure HTTP Server
In order to develop an HTTP server, you need to understand how the
HTTP protocol works. This server, however, is simple since it only
supports the GET request method. A sample implementation is shown
in Code Sample 1. This is a multi-threaded HTTP server where
the ProcessConnection class is used to run each new request in a
diIIerent thread. When the server receives a request Irom the browser,
it parses the request to Iind out which document is being requested. II
the requested document is available on the server,
the shipDocument method is used to send the requested document to
the server. II the document is not Iound, an error message is sent to the
server.
Code Sample 1: HttpServer.java
import java.io.*;
import java.net.*;
import java.util.StringTokenizer;

/**
* This class implements a multithreaded simple HTTP
* server that supports the ET request method.
* t listens on port 44, waits client requests, and
* serves documents.
*/

public class HttpServer {
// The port number which the server
// will be listening on
public static final int HTTP_PORT = 8080;

public ServerSocket getServer() throws Exception {
return new ServerSocket(HTTP_PORT);
}

// multi-threading -- create a new connection
// for each request
public void run() {
ServerSocket listen;
try {
listen = getServer();
while(true) {
Socket client = listen.accept();
ProcessConnection cc = new
ProcessConnection(client);
}
} catch(Exception e) {
System.out.println("Exception:
"+e.getMessage());
}
}

// main program
public static void main(String argv[]) throws
Exception {
HttpServer httpserver = new HttpServer();
httpserver.run();
}
}


class ProcessConnection extends Thread {
Socket client;
BufferedReader is;
DataOutputStream os;

public ProcessConnection(Socket s) { // constructor
client = s;
try {
is = new BufferedReader(new nputStreamReader
(client.getnputStream()));
os = new DataOutputStream(client.getOutputStream());
} catch (OException e) {
System.out.println("Exception: "+e.getMessage());
}
this.start(); // Thread starts here...this start()
will call run()
}

public void run() {
try {
// get a request and parse it.
String request = is.readLine();
System.out.println( "Request: "+request );
StringTokenizer st = new StringTokenizer( request );
if ( (st.countTokens() >= 2) &&
st.nextToken().equals("ET") ) {
if ( (request =
st.nextToken()).startsWith("/") )
request = request.substring( 1 );
if ( request.equals("") )
request = request + "index.html";
File f = new File(request);
shipDocument(os, f);
} else {
os.writeBytes( "400 Bad Request" );
}
client.close();
} catch (Exception e) {
System.out.println("Exception: " +
e.getMessage());
}
}

/**
* Read the requested file and ships it
* to the browser if found.
*/
public static void shipDocument(DataOutputStream out,
File f) throws Exception {
try {
DatanputStream in = new
DatanputStream(new FilenputStream(f));
int len = (int) f.length();
byte[] buf = new byte[len];
in.readFully(buf);
in.close();
out.writeBytes("HTTP/1.0 200 OK\r\n");
out.writeBytes("Content-Length: " +
f.length() +"\r\n");
out.writeBytes("Content-Type:
text/html\r\n\r\n");
out.write(buf);
out.flush();
} catch (Exception e) {
out.writeBytes("<html><head><title>error</title>
</head><body>\r\n\r\n");
out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n");
out.writeBytes("Content-Type: text/html\r\n\r\n");
out.writeBytes("</body></html>");
out.flush();
} finally {
out.close();
}
}
}

To experiment with the HttpServer class:
1. Copy HttpServer and save it in a Iile called HttpServer.java in a
directory oI your choice.
2. Compile the HttpServer.java using javac.
3. Create some sample HTML Iiles including "index.html", which is
the deIault document served in this example
4. Run the HttpServer. The server runs on port 8080.
5. Open a web browser and make a request such as
http://localhost:8080 or http://127.0.0.1:8080/index.html.

ote: Can you think oI any malicious URLs that the HttpServer can
handle? What about something
like http://serverDomainName:8080/../../etc/passwd orhttp://serverDomainN
ame:8080//somefile.txt. As an exercise, modiIy HttpServer so that such
URLs are not allowed. Hint: write your own
customer SecurityManager or usejava.lang.SecurityManager. You can
install this security manager by adding the
statement System.setSecurityManager(new Java.lang.SecurityManager) as
the Iirst line in the main method. Try it!

Extending HttpServer to Handle https:// URLs
Now, let's modiIy the HttpServer class, making it secure. I'd like the
HTTP server to be capable oI handling https:// URLs. As I mentioned
earlier, JSSE allows you to integrate SSL into your applications quite
easily.
Creating a Server Certifi.ate
As I mentioned earlier, SSL uses certiIicates Ior authentication.
CertiIicates must be created Ior clients and servers that need to
communicate securely using SSL. JSSE uses certiIicates created using
the Javakeytool shipped with J2SE. I used the Iollowing command to
create an RSA certiIicate Ior the HTTP server.
prompt> keytool -genkey -keystore serverkeys -keyalg rsa -alias qusay
This command will generate a certiIicate reIerenced by the alias qusay,
and will be stored in a Iile named serverkeys. The tool prompted me
Ior inIormation to generate the certiIicate. The inIormation I entered is
highlighted in bold:
Enter keystore password: heIIothere
What is your first and last name?
[Unknown]: uItra.domain.com
What is the name of your organizational unit?
[Unknown]: Training and ConsuIting
What is the name of your organization?
[Unknown]: javacourses.com
What is the name of your City or Locality?
[Unknown]: Toronto
What is the name of your State or Province?
[Unknown]: Ontario
What is the two-letter country code for this unit?
[Unknown]: CA
s CN=ultra, OU=Training and Consulting,
O=javacourses.com, L=Toronto, ST=Ontario, C=CA correct?
[no]: yes

Enter key password for <qusay>
(RETURN if same as keystore password): hiagain

As you can see, the keytool prompted me to enter a password Ior the
keystore meaning that in order Ior the server to access the keystore it
must know that password. Also, the tool asked me to enter a password
Ior the alias. II you like, such password inIormation can be related on
the keytool command line using the options -storepass and -keypass.
Note that I used the name "ultra.domain.com" Ior the Iirst and last
name. This name is the hypothetical name oI my machine. You should
enter the hostname or the IP address oI the server's machine.
When you run the keytool command, it may take a Iew seconds to
generate the certiIicate depending on the speed oI your machine.
Once a certiIicate Ior my server has been generated, I can revise
my HttpServer to make it secure. II you examine the HttpServer class,
you'll notice that the getServer method is used to return a server socket.
This means, the only method I need to modiIy is the getServer method
so that it returns a secure server socket. The changes are highlighted
in bold in Code Sample 2. Notice that I have changed the port number
to 443. This is the deIault port number Ior HTTPs. It is important to
note that port numbers between 0 and 1023 are reserved. II you
run HttpsServer on a diIIerent port number, the url should
be:https://localhost:portnumber but iI you run it on 443 then the URL
is: https://localhost.
Code Sample 2: HttpsServer.java
import java.io.*;
import java.net.*;
import javax.net.*;
import javax.net.ssI.*;
import java.security.*;
import java.util.StringTokenizer;

/**
* This class implements a multithreaded simple HTTPS
* server that supports the ET request method.
* t listens on port 44, waits client requests
* and serves documents.
*/

public class HttpsServer {

String keystore = "serverkeys";
char keystorepass[] = "heIIothere".toCharArray();
char keypassword[] = "hiagain".toCharArray();

// The port number which the server wiII be Iistening on
pubIic static finaI int HTTPS_PORT = 443;


public ServerSocket getServer() throws Exception {

KeyStore ks = KeyStore.getInstance("JKS");
ks.Ioad(new FiIeInputStream(keystore), keystorepass);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, keypassword);
SSLContext ssIcontext =
SSLContext.getInstance("SSLv3");
ssIcontext.init(kmf.getKeyManagers(), nuII, nuII);
ServerSocketFactory ssf =
ssIcontext.getServerSocketFactory();
SSLServerSocket serversocket = (SSLServerSocket)
ssf.createServerSocket(HTTPS_PORT);
return serversocket;

}


// multi-threading -- create a new connection
// for each request
public void run() {
ServerSocket listen;
try {
listen = getServer();
while(true) {
Socket client = listen.accept();
ProcessConnection cc = new
ProcessConnection(client);
}
} catch(Exception e) {
System.out.println("Exception: "+e.getMessage());
}
}

// main program
public static void main(String argv[]) throws Exception {
HttpsServer https = new HttpsServer();
https.run();
}
}

The lines:
String keystore = "serverkeys";
char keystorepass[] = "hellothere".toCharArray();
char keypassword[] = "hiagain".toCharArray();
speciIy the name oI the keystore, its password, and the key password.
Hardcoding the passwords into the code is not a good idea Ior
production code, however. They can be speciIied on the command line
when running the server.
The rest oI the JSSE related code is in the getServer method:
O It access the serverkeys keystore. The JKS is the Java KeyStore (a
type oI keystore created by keytool).
O The KeyManagerFactory is used to create an X.509 key manager Ior
the keystore.
O An SSLContext is an environment Ior implementing JSSE. It is
used to create a ServerSocketFactory that in turn used to create
a SSLServerSocket. Although we speciIy SSL 3.0, the
implementation that is returned will oIten support other protocol
versions, such as TLS 1.0. Older browsers, however, use SSL 3.0
more widely.
Note that by deIault client authentication is not required. For iI you
wish Ior your server to require client authentication,
use: serversocket.setNeedClientAuth(true).
To experiment with the HttpsServer class:
1. Copy the HttpsServer and ProcessConnection classes into a Iile
named HttpsServer.java
2. Save this Iile in the same directory where the serverkeys Iile was
created by the keytool
3. Compile the HttpsServer.java using javac
4. Run the HttpsServer. By deIault it runs on port 443, but iI you
cannot start it on this port, choose another port number greater
than 1024.
5. Open a web browser and enter the request: https://localhost or
https://127.0.0.1. This assumes the server is running on port 443.
II not, then use: https://localhost:port
When you enter an https:// URL in the browser, you get a security
alert popup window like the one in Figure 3. This is because the HTTP
server certiIicate was selI-generated. In other words, it was generated
by an unknown certiIication authority, one that was not Iound among
the certiIication authorities your browser keeps in its store. You have
the option to view the certiIicate (check whether it is a proper
certiIicate and discover who signed it) and then install it, reject the
certiIicate, or accept the certiIicate.

igure 3. Server certificate issued by an unknown certification
authority

ote: Generating your own certiIicate is Iine Ior internal private
systems. For public systems, however, it is a good idea to get a
certiIicate Irom a well known CertiIication Authority in order to avoid
the browser security alert.

II you accept the certiIicate you will be able to see the page behind the
secure connection, and Iuture access to the same Web site will not
cause the browser to issue a security alert. Note that there are many
Web sites that use HTTPS whose certiIicates were either selI-
generated or generated by unknown CAs. As an example, try to visit:
https://www.jam.ca. II you have never visited this Web site, you will
see a security alert like the one in Figure 3.

ote: When you accept the certiIicate, it is only Ior that session. In
other words, once you completely exit the browser it is Iorgotten. Both
Netscape and MicrosoIt Internet Explorer (MSIE) allow you to install
a certiIicate permanently. To do this in MSIE, select "View
CertiIicate" Irom Figure 3 and Irom the new window select "Install
CertiIicate".

Con.lusion
This article presented a detailed overview oI SSL and described the
JSSE Iramework and implementation. The examples presented in this
article show how easy it is to seamlessly integrate SSL into your
client/server applications. This article presented a secure http server
that you can use as a base Ior experimentation. Stay tuned Ior more
inIormation on the JSSE APIs and a web browser capable oI handling
HTTPS requests.
For More Information
O SSL 3.0
O TLS 1.0
O Download J2SE 1.4.1
O Java Secure Socket Extension (JSSE)
O JSSE ReIerence Guide
O The J2SE 1.4.1 java.net Package
O J2SE 1.4.1 Documentation
O J2SE 1.4.1 Networking Properties
A.nowledgments
Special thanks to Andreas Sterbenz oI Sun Microsystems whose
Ieedback helped me improve the article.
About the Author
Qusay H. Mahmoud provides Java consulting and training services.
He has published dozens oI articles on Java, and is the author
oI Distributed Programming with Java (Manning Publications, 1999)
andLearning Wireless Java (O'Reilly, 2002).
Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's
standard product communication policies. Any resulting features and timing of release of such features as determined
by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether
communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or
functionality, and should not be relied upon in making purchasing decisions. t is intended for information purposes
only, and may not be incorporated into any contract.

You might also like