The Secure Sockets Layer protocol, or SSL, sits between the application-level protocol (in this case HTTP) and the low-level transport protocol (for the Internet, almost exclusively TCP/IP). It handles the details of security management using public key cryptography to encrypt all client/server communication. SSL was introduced by Netscape with Netscape Navigator 1. It has since become the de facto standard for secure online communications and forms the basis of the Transport Layer Security (TLS) protocol currently under development by the Internet Engineering Task Force. For more information on TLS, see http://www.ietf.org/.
SSL Version 2.0, the version first to gain widespread acceptance, includes support for server certificates only. It provides authentication of the server, confidentiality, and integrity. Here's how it works:
A user connects to a secure site using the HTTPS (HTTP plus SSL) protocol. (You can detect sites using the HTTPS protocol because their URLs begin with https: instead of http:.)
The server signs its public key with its private key and sends it back to the browser.
The browser uses the server's public key to verify that the same person who signed the key actually owns it.
The browser checks to see whether a trusted certificate authority signed the key. If one didn't, the browser asks the user if the key can be trusted and proceeds as directed.
The client generates a symmetric ( DES) key for the session, which is encrypted with the server's public key and sent back to the server. This new key is used to encrypt all subsequent transactions. The symmetric key is used because of the high computational cost of public key cryptosystems.
All this is completely transparent to servlets and servlet developers. You just need to obtain an appropriate server certificate, install it, and configure your server appropriately. Information transferred between servlets and clients is now encrypted. Voila, security!
Our security toolbox now includes strong encryption and strong server authentication, but only weak client authentication. Of course, using SSL 2.0 puts us in better shape because SSL-equipped servers can use the basic authentication methods discussed at the beginning of this chapter without concern for eavesdropping. We still don't have proof of client identity, however--after all, anybody could have guessed or gotten a hold of a client username and password.
SSL 3.0 fixes this problem by providing support for client certificates. These are the same type of certificates that servers use, but they are registered to clients instead. As of this writing, VeriSign claims to have distributed more than 750,000 client certificates. SSL 3.0 with client authentication works the same way as SSL 2.0, except that after the client has authenticated the server, the server requests the client's certificate. The client then sends its signed certificate, and the server performs the same authentication process as the client did, comparing the client certificate to a library of existing certificates (or simply storing the certificate to identify the user on a return visit). As a security precaution, many browsers require the client user to enter a password before they will send the certificate.
Once a client has been authenticated, the server can allow access to protected resources such as servlets or files just as with HTTP authentication. The whole process occurs transparently, without inconveniencing the user. It also provides an extra level of authentication because the server knows the client with a John Smith certificate really is John Smith (and it can know which John Smith it is by reading his unique certificate). The disadvantages of client certificates are that users must obtain and install signed certificates, servers must maintain a database of all accepted public keys, and servers must support SSL 3.0 in the first place. As of this writing, most do, including the Java Web Server.
As with basic and digest authentication, all of this communication is transparent to servlets. It is sometimes possible, though, for a servlet to retrieve the relevant SSL authentication information. The java.security package has some basic support for manipulating digital certificates and signatures. To retrieve a client's digital information, however, a servlet has to rely on a server-specific implementation of the request's getAttribute() method. Example 8-6 (reprinted from Chapter 4, "Retrieving Information") shows how to use getAttribute() to fetch the details of a client's certificates. Remember that this works only for the Java Web Server. Other servlet implementations, if they include this functionality at all, are likely to do it in a slightly different way, although we hope that they build on Java's standard signature support.
import javax.security.cert.X509Certificate; out.println("<PRE>"); // Display the cipher suite in use String cipherSuite = (String) req.getAttribute("javax.net.ssl.cipher_suite"); out.println("Cipher Suite: " + cipherSuite); // Display the client's certificates, if there are any if (cipherSuite != null) { X509Certificate certChain[] = (X509Certificate[]) req.getAttribute("javax.net.ssl.peer_certificates"); if (certChain != null) { for (int i = 0; i < certChain.length; i++) { out.println ("Client Certificate [" + i + "] = " + certChain[i].toString()); } } } out.println("</PRE>");
Here's the output we first saw in Chapter 4, "Retrieving Information":
Cipher Suite: SSL_RSA_EXPORT_WITH_RC4_40_MD5 Client Certificate [0] = [ X.509v3 certificate, Subject is OID.1.2.840.113549.1.9.1=#160F6A68756E746572407367692E636F6D, CN=Jason Hunter, OU=Digital ID Class 1 - Netscape, OU="www.verisign.com/repository/CPS Incorp. by Ref.,LIAB.LTD(c)96", OU=VeriSign Class 1 CA - Individual Subscriber, O="VeriSign, Inc.", L=Internet Key: algorithm = [RSA], exponent = 0x 010001, modulus = b35ed5e7 45fc5328 e3f5ce70 838cc25d 0a0efd41 df4d3e1b 64f70617 528546c8 fae46995 9922a093 7a54584d d466bee7 e7b5c259 c7827489 6478e1a9 3a16d45f Validity until Issuer is OU=VeriSign Class 1 CA - Individual Subscriber, O="VeriSign, Inc.", L=Internet Issuer signature used [MD5withRSA] Serial number = 20556dc0 9e31dfa4 ada6e10d 77954704 ] Client Certificate [1] = [ X.509v3 certificate, Subject is OU=VeriSign Class 1 CA - Individual Subscriber, O="VeriSign, Inc.", L=Internet Key: algorithm = [RSA], exponent = 0x 010001, modulus = b614a6cf 4dd0050d d8ca23d0 6faab429 92638e2c f86f96d7 2e9d764b 11b1368d 57c9c3fd 1cc6bafe 1e08ba33 ca95eabe e35bcd06 a8b7791d 442aed73 f2b15283 68107064 91d73e6b f9f75d9d 14439b6e 97459881 47d12dcb ddbb72d7 4c3f71aa e240f254 39bc16ee cf7cecba db3f6c2a b316b186 129dae93 34d5b8d5 d0f73ea9 Validity until Issuer is OU=Class 1 Public Primary Certification Authority, O="VeriSign, Inc.", C=US Issuer signature used [MD2withRSA] Serial number = 521f351d f2707e00 2bbeca59 8704d539 ]
The first certificate is the user's public key. The second is VeriSign's signature that vouches for the authenticity of the first signature. Of course, the information from these certificate chains isn't particularly useful to the application programmer. In some applications, it is safe to simply assume that a user is authorized if she got past the SSL authentication phase. For others, the certificates can be picked apart using the javax.security.cert.X509Certificate class. More commonly, a web server allows you to assign a username to each certificate you tell it to accept. Servlets can then call getRemoteUser() to get a unique username. The latter solution works with almost all web servers.
Copyright © 2001 O'Reilly & Associates. All rights reserved.