2. Overview of SSL

advertisement
Secure Internet Programming
We demonstrate how to build secure Internet applications based on. The first part is concerned
with the server-side and the next part will be concerned with the client-side.
Table of contents
1.
Introduction .............................................................................................................3
2.
Overview of SSL .......................................................................................................4
2.1. SSL and the TCP/IP Protocol Stack ..........................................................................4
2.2. Negotiable Encryption............................................................................................5
3.
JSSE........................................................................................................................8
3.1. Programming with JSSE .........................................................................................8
4.
3.1.1.
SSLSocket and SSLServerSocket ......................................................................8
3.1.2.
SSLSocketFactory and SSLServerSocketFactory .................................................9
3.1.3.
Making Existing Client/Server Applications Secure ..............................................9
Example: HTTP Server ............................................................................................. 12
4.1. Overview of HTTP ............................................................................................... 12
4.2. Insecure HTTP Server .......................................................................................... 13
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
1/26
4.3. Extending HttpServer to Handle https:// URLs ........................................................ 20
4.4. Links ................................................................................................................. 26
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
2/26
1.
Introduction
Any information transmitted over computer networks, or the Internet, is subject to interception.
Some of that information could be sensitive, such as credit card numbers and other personal
data. To make the Internet more useful in an enterprise setting and for e-commerce, applications must protect their users' information, using encryption, authentication, and secure communications protocols. The secure Hypertext Transfer Protocol (HTTPS), which is HTTP over the
Secure Sockets Layer (SSL), is already being used successfully for e-commerce applications.
The Java Secure Socket Extension (JSSE), which is a set of Java packages that enable secure
Internet communications, is a framework and 100% Pure Java implementation of the Secure
Socket Layer (SSL). These packages enable a Java developer to develop secure network applications that feature the secure passage of data between a client and a server running any application protocol, such as HTTP, FTP, Telnet, or NTTP, over TCP/IP.
TM
JSSE has been integrated into the Java 2 SDK, Standard Edition, version 1.4 (J2SE 1.4). Here
we start by presenting a detailed overview of SSL, then shows you how to:
TM
 Use the JSSE APIs
 Integrate SSL into your existing client-server applications
 Develop a simple HTTP server
 Revise the HTTP server to handle HTTPS requests
 Generate your own certificates using the
keytool
delivered with J2SE
 Develop, configure, and run a secure HTTP server
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
3/26
2.
Overview 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 offers encryption,
source authentication, and data integrity as means to protect information exchanged over insecure, public networks. There are several versions of SSL: SSL 2.0 has security weaknesses and
is hardly used today; SSL 3.0 is universally supported; and finally 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 software.
Encryption protects data from unauthorized use by converting it to an apparently meaningless
form before 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 of verifying the data sender's identity. The first 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 of credentials in the form of a certificate.
Certificates are issued and validated by trusted authorities known as certification authorities
(CAs). A certificate represents the public-key identity of a person. It is a signed document that
says: I certify that the public key in this document belongs to the entity named in this document. Well-known CAs include Verisign, Entrust, and Thawte.
Data integrity refers to means of ensuring that data has not been modified in transit.
2.1. SSL and the TCP/IP Protocol Stack
As the name Secure Sockets Layer indicates, SSL connections act like sockets connected by
TCP. Therefore, you can think of SSL connections as secure TCP connections since the place for
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
4/26
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 of the TCP features such as
out-of-band data.
Figure 1: SSL and the TCP/IP protocol stack
2.2. Negotiable Encryption
Among the features of SSL that have made it the de facto standard vehicle for secure ecommerce transactions is its support for negotiable encryption and authentication algorithms.
The designers of SSL realized that not all parties will use the same client software and consequently not all clients will include any particular encryption algorithm. The same is true for
servers. The client and server at the two ends of a connection negotiate the encryption and decryption algorithms (cipher suites) during their initial handshake. It may turn out that they do
not have sufficient algorithms in common, in which case the connection attempt will fail.
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 of passwords sent over an SSL-protected channel. This
pattern is common in banking, stock trading, and other secure Web applications.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
5/26
The SSL full handshake protocol is illustrated next. It shows the sequences of messages exchanged during the SSL handshake.
1. ClientHello: The client sends the server infor-
mation such as SSL protocol version, session id,
and cipher suites information 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 information to the client.
3. Certificate: The server sends the client its cer-
tificate 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 confirm the server's identity
to the client.
4. Certificate Request: This message is sent only if
the server requires the client to authenticate itself. Most e-commerce applications do not require the client to authenticate itself.
5. Server Key Exchange: This message is sent if
the certificate, which contains the server's public key, is not sufficient for key exchange.
6. ServerHelloDone: This message informs the cli-
ent that the server finished the initial negotia-
tion process.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
6/26
7. Certificate: This message is sent only if the server requested the client to authenticate itself.
8. Client Key Exchange: The client generates a secret
key to be shared between the client and server. If
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 Verify: If the server requested to authen-
ticate the client, this message allows the server to
complete the authentication process.
Change Cipher Spec: The client asks the server
to change to encrypted mode.
10.
Finished: The client tells the server it is ready
for secure communication.
11.
Change Cipher Spec: The server asks the client
to change to encrypted mode.
12.
Finished: The server tells the client it is ready
for secure communication. This marks the end of
the SSL handshake.
13.
Encrypted Data: The client and server can now start exchanging encrypted messages over a secure
communication channel.
14.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
7/26
3.
JSSE
The Java Secure Socket Extension (JSSE) provides a framework and a 100% Pure Java implementation of the SSL and TLS protocols. It provides mechanisms for data encryption, server
authentication, message integrity, and optional client authentication.
The JSSE framework is capable of supporting many different 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.
3.1. Programming with JSSE
The JSSE APIs supplement the java.security and java.net packages by providing extended
networking socket classes, trust and key managers, and a socket factory framework for encapsulating socket creation behaviour. These classes are included in the packages javax.net and
javax.net.ssl.
3.1.1.
SSLSocket and SSLServerSocket
The javax.net.ssl.SSLSocket is a subclass of the java.net.Socket class. Therefore, it supports all the standard Socket methods and adds additional methods specific to secure sockets.
The javax.net.ssl.SSLServerSocket class is analogous to the SSLSocket class except that it
is used to create server sockets.
Creating an instance of SSLSocket can be done in two ways:
 As an instance of SSLSocketFactory by invoking one of the createSocket methods on
that class.
 Through the accept method on the SSLServerSocket.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
8/26
3.1.2.
SSLSocketFactory and SSLServerSocketFactory
The javax.net.ssl.SSLSocketFactory class is an object factory for creating secure sockets,
and the javax.net.ssl.SSLServerSocketFactory is an object factory for creating server
sockets.
An SSLSocketFactory instance can be obtained in two ways:
 Get the default factory by calling SSLSocketFactory.getDefault.
 Construct a new factory with specified configured behavior.
Note that the default factory is configured to enable server authentication only.
3.1.3.
Making Existing Client/Server Applications Secure
Incorporating SSL into existing client/server applications to make them secure can be easily
done using a few lines of JSSE code. The lines highlighted in yellow in the following example
show the code necessary to make a server secure:
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
9/26
import java.io.*;
import javax.net.ssl.*;
public class Server {
int port = portNumber;
SSLServerSocket server;
try {
SSLServerSocketFactory factory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
server = (SSLServerSocket)
factory.createServerSocket(portNumber);
SSLSocket client = (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) {
}
}
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
10/26
The lines highlighted in yellow in the following example show the code necessary to make a client secure:
import java.io.*;
import javax.net.ssl.*;
public class Client {
...
try {
SSLSocketFactory factory = (SSLSocketFactory)
SSLSocketFactory.getDefault();
SSLSocket client = (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) {
}
}
…
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
11/26
4.
Example: HTTP Server
We demonstrate how to develop, configure, and run a complete HTTP server application that
supports the GET request method.
First, we build a HTTP server, next we make it secure, implementing SSL capabilities.
4.1. Overview of HTTP
The Hypertext Transfer Protocol (HTTP) is a request-reply application protocol.
This protocol supports a fixed set of methods such as GET, POST, PUT, DELETE, etc. The GET method is
commonly used to request resources from a Web server. Here are two sample GET requests:
GET / HTTP/1.0 <empty-line>
GET /names.html HTTP/1.0 <empty-line>
The server we consider is simple since it only supports the GET request method.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
12/26
GET /index.html HTTP/1.1
client
HTTP/1.0 200 OK
…
server
<HTML>
…
4.2. Insecure HTTP Server
Our implementation is a multi-threaded HTTP server where the ProcessConnection class is
used to run each new request in a different thread.
When the server receives a request from the client, it parses the request to find out which document is being requested. If the requested document is available on the server, the shipDocument method is used to send the requested document to the server. If the document is not
found, an error message is sent to the server.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
13/26
$ cat HttpServer.java
import java.io.*;
import java.net.*;
import java.util.StringTokenizer;
/**
* This class implements a multithreaded simple HTTP
* server that supports the GET request method.
* It listens on port 9999, 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 = 9999;
public ServerSocket getServer() throws Exception {
return new ServerSocket(HTTP_PORT);
}
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
14/26
// 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();
}
}
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
15/26
class ProcessConnection extends Thread {
Socket client;
BufferedReader is;
DataOutputStream os;
public ProcessConnection(Socket s) { // constructor
client = s;
try {
is = new BufferedReader(new InputStreamReader
(client.getInputStream()));
os = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
System.out.println("Exception: "+e.getMessage());
}
this.start(); // Thread starts here...this start() will call run()
}
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
16/26
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("GET") ) {
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());
}
}
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
17/26
// Read the requested file and ships it to the browser if found.
public static void shipDocument(DataOutputStream out,
File f) throws Exception {
try {
DataInputStream in = new DataInputStream(new FileInputStream(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();
}
}
} // ProcessConnection
$
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
18/26
The server listens on port 9999, thus we have to use the following URL in a browser:
http://localhost:9999/index.html
To visualise the data, transferred between client and server, we use the TCP/IP monitor tcpmon
out of the Axis project.
$ java org.apache.axis.utils.tcpmon 9998 localhost 9999
tcpmon listens to port 9998, tunnelling the data further to port 9999 on localhost.
Therefore, we use the URL
http://localhost:9998/index.html
and see that we have readable text.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
19/26
4.3. Extending HttpServer to Handle https:// URLs
Now, let's modify the HttpServer class, making it secure.
As mentioned earlier, SSL uses certificates for authentication. Certificates must be created for
clients and servers that need to communicate securely using SSL.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
20/26
JSSE uses certificates created using the Java keytool shipped with J2SE. We used the following
command to create an RSA certificate for the HTTP server.
$ keytool -genkey -keystore serverkeys -keyalg rsa -alias as
Geben Sie das Keystore-Passwort ein: pwd123
Wie lautet Ihr Vor- und Nachname?
[Unknown]: Alois Schuette
Wie lautet der Name Ihrer organisatorischen Einheit?
[Unknown]: FHD
Wie lautet der Name Ihrer Organisation?
[Unknown]: Informatik
Wie lautet der Name Ihrer Stadt oder Gemeinde?
[Unknown]: Darmstadt
Wie lautet der Name Ihres Bundeslandes oder Ihrer Provinz?
[Unknown]: Hessen
Wie lautet der Landescode (zwei Buchstaben) für diese Einheit?
[Unknown]: de
Ist CN=Alois Schuette, OU=FHD, O=Informatik, L=Darmstadt, ST=Hessen, C=de richtig?
[Nein]: ja
Geben Sie das Passwort für <as> ein.
(EINGABETASTE, wenn Passwort dasselbe wie für Keystore):
$
Now, we have a file „serverkeys“ holding our certificate for the server.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
21/26
Once a certificate for the server has been generated, we can revise my HttpServer to make it
secure. If 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 modify is the getServer
method so that it returns a secure server socket.
The changes are highlighted in yellow.
The lines:
String keystore = "serverkeys";
char keystorepass[] = "pwd123".toCharArray();
char keypassword[] = "pwd123".toCharArray();
specify the name of the keystore, its password, and the key password. Hardcoding the passwords into the code is not a good idea for production code, however. They can be specified on
the command line when running the server.
The rest of the JSSE related code is in the getServer method:
It access the serverkeys keystore. The JKS is the Java KeyStore (a type of keystore created by
keytool).
The KeyManagerFactory is used to create an X.509 key manager for the keystore.
An SSLContext is an environment for implementing JSSE. It is used to create a ServerSocketFactory that in turn used to create a SSLServerSocket. Although we specify SSL 3.0, the implementation that is returned will often support other protocol versions, such as TLS 1.0. Older
browsers, however, use SSL 3.0 more widely.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
22/26
Note that by default client authentication is not required. For if you wish for your server to require client authentication, use: serversocket.setNeedClientAuth(true).
$ cat HttpsServer.java
import java.io.*;
import java.net.*;
import javax.net.*;
import javax.net.ssl.*;
import java.security.*;
import java.util.StringTokenizer;
/**
* This class implements a multithreaded simple HTTPS
* server that supports the GET request method.
* It listens on port 44, waits client requests
* and serves documents.
*/
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
23/26
public class HttpsServer {
String keystore = "serverkeys";
char keystorepass[] = "pwd123".toCharArray();
char keypassword[] = "pwd123".toCharArray();
// The port number which the server will be listening on
public static final int HTTPS_PORT = 9999;
public ServerSocket getServer() throws Exception {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(keystore), keystorepass);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, keypassword);
SSLContext sslcontext = SSLContext.getInstance("SSLv3");
sslcontext.init(kmf.getKeyManagers(), null, null);
ServerSocketFactory ssf = sslcontext.getServerSocketFactory();
SSLServerSocket serversocket = (SSLServerSocket)
ssf.createServerSocket(HTTPS_PORT);
return serversocket;
}
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
24/26
// multi-threading -- create a new connection for each request
public void run() {
…
}
// main program
public static void main(String argv[]) throws Exception {
HttpsServer https = new HttpsServer();
https.run();
}
}
class ProcessConnection extends Thread {
…
} // ProcessConnection
$
When you enter an https:// URL in the browser, you get a security alert popup window. This
is because the HTTP server certificate was self-generated. In other words, it was generated by
an unknown certification authority, one that was not found among the certification authorities
your browser keeps in its store. You have the option to view the certificate (check whether it is
a proper certificate and discover who signed it) and then install it, reject the certificate, or accept the certificate.
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
25/26
Generating your own certificate is fine for internal private systems. For public systems, however, it is a good idea to get a certificate from a well known Certification Authority in order to
avoid the browser security alert.
If you accept the certificate you will be able to see the page behind the secure connection, and
future access to the same Web site will not cause the browser to issue a security alert. When
you accept the certificate, it is only for that session.
Using tcpmon with proxy enabled demonstrate that we have ciphered data over our connection.
4.4. Links
 SSL 3.0
 Java Secure Socket Extension (JSSE)
 JSSE Reference Guide
 tcpmon
 keytool
Distributed Programming in Java: 106744054
Prof. Dr. Alois Schütte
26/26
Download