JavaTM Secure Socket Extension (JSSE) 1.0.2

API User's Guide


Introduction
Features, Advantages, and Benefits
JSSE 1.0.2 Standard API
JSSE 1.0.2 Reference Implementation API
SunJSSE Provider
What's New in JSSE 1.0.2
Related Documentation

Terms and Definitions

Secure Sockets Layer (SSL) Protocol Overview
Why Use SSL?
How SSL Works

Key Classes
Core Classes and Interfaces
SSLSocket and SSLServerSocket Classes
SocketFactory and ServerSocketFactory Classes
SSLSocketFactory and SSLServerSocketFactory Classes
SSLSession Interface
Support Classes and Interfaces
SSLSessionContext Interface
SSLSessionBindingListener Interface
SSLSessionBindingEvent Class
HandShakeCompletedListener Interface
HandShakeCompletedEvent Class
X509Certificate Class
Reference Implementation Classes and Interfaces
SSLContext Class
TrustManagerFactory Class
X509TrustManager Interface
KeyManagerFactory Class
X509KeyManager Interface

Installing and Customizing JSSE 1.0.2
Installation
Customization

Additional Keystore Formats

Troubleshooting

Code Examples
Converting an Unsecure Socket to a Secure Socket
Running the JSSE 1.0.2 Sample Code


Appendix A: Standard Names

Introduction

Data that travels across a network can easily be accessed by someone who is not the intended recipient. When the data includes private information, such as passwords and credit card numbers, steps must be taken to make the data unintelligible to unauthorized parties. It is also important to ensure the data has not been modified, either intentionally or unintentionally, during transport. The Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols were designed to help protect the privacy and integrity of data while it is transferred across a network.

The Java Secure Socket Extension (JSSE) 1.0.2 enables secure Internet communications. It provides a framework and a reference implementation for a Java version of the SSL and TLS protocols and includes functionality for data encryption, server authentication, message integrity, and optional client authentication. Using JSSE, developers can provide for the secure passage of data between a client and a server running any application protocol, such as Hypertext Transfer Protocol (HTTP), Telnet, or FTP, over TCP/IP. (For an introduction to SSL, see Secure Sockets Layer (SSL) Protocol Overview.)

By abstracting the complex underlying security algorithms and "handshaking" mechanisms, JSSE minimizes the risk of creating subtle, but dangerous security vulnerabilities. Furthermore, it simplifies application development by serving as a building block which developers can integrate directly into their applications.

JSSE 1.0.2 supplements the JavaTM 2 SDK, Standard Edition (J2SDK) by providing extended networking socket classes. It also provides a socket factory framework for encapsulating socket creation behavior and provides a limited public key certificate API that is compatible with JDK1.1-based platforms.

JSSE 1.0.2 provides both an application programming interface (API) framework and a non-commercial reference implementation that demonstrates a working example of the JSSE API. The API is provided in the standard extension (optional package) javax namespace. It is an API for secure sockets, socket factories, and public key certificates. The reference implementation also include some classes which are specific to this implementation and appear in the com.sun.net.ssl package. Difference Between Reference Implementation and Commercial Product describes the differences between a reference implementation and a commercial product.

The JSSE 1.0.2 API is capable of supporting SSL versions 2.0 and 3.0 and Transport Layer Security (TLS) 1.0. These security protocols encapsulate a normal bidirectional stream socket and the JSSE 1.0.2 API adds transparent support for authentication, encryption, and integrity protection. The JSSE reference implementation implements SSL 3.0 and TLS 1.0. It does not implement SSL 2.0.

JSSE 1.0.2 is an optional security component of the Java 2 platform. It builds on the security architecture in the core Java 2 platform. Other security components in the Java 2 platform include the Java Cryptography Extension (JCE), the Java Authentication and Authorization Service (JAAS), and the Java Security Tools. JSSE 1.0.2 encompasses many of the same concepts and algorithms as those in JCE but automatically applies them underneath a simple stream socket API extension.

JSSE 1.0.2 is based on the same design principles found elsewhere in the Java Cryptography Architecture framework utilized by all the cryptography-related security components of the Java 2 platform: implementation independence and, whenever possible, algorithm independence. It uses the same "provider" architecture.

JSSE 1.0.2 is designed to allow other implementations of certain classes to be plugged in seamlessly, thus providing alternate protocol and Public Key Infrastructure (PKI) implementations. (Note: there are currently a number of restrictions on pluggability, especially for non-domestic users. Basically, it is not possible for global users to use SSLSocketFactory, or SSLServerSocketFactory implementations other than the ones supplied by the SunJSSE provider. See Customization.)


Difference Between Reference Implementation and Commercial Product

Sun's JSSE 1.0.2 implementation is a reference implementation. A reference implementation is intended to familiarize developers with the APIs and the technology before developers make their choice on commercial implementations. A reference implementation is similar to a proof-of-concept implementation of a specification. It is used to demonstrate that the specification is implementable and that various compatibility tests can be written against it.

A non-commercial implementation typically lacks the overall "polish" and completeness of a commercial-grade product. While the implementation does meet the API specification, it will be lacking things such as a fully-featured toolkit, sophisticated debugging tools, commercial-grade documentation and regular maintenance updates.


Features, Advantages, and Benefits

JSSE 1.0.2 includes the following important features:


Cryptographic Functionality Available With JSSE 1.0.2

Cryptographic Algorithm

Cryptographic Process

Key Lengths (Bits)

RSA public key

Authentication and key agreement

2048 (authentication)
2048 (key agreement)
  512 (key agreement)

RC4

Bulk encryption

128
128 (40 effective)

DES

Bulk encryption

64 (56 effective)
64 (40 effective)

Triple DES

Bulk encryption

192 (112 effective)

Diffie-Hellman public key

Key agreement

1024
  512

DSA public key

Authentication

2048



JSSE 1.0.2 Standard API

The JSSE 1.0.2 standard API, available in the javax.net, javax.net.ssl and javax.security.cert packages, covers:

JSSE 1.0.2 Reference Implementation API

The JSSE 1.0.2 reference implementation includes a non-standard API in the com.sun.net.ssl package. At this time, this API is implementation-specific and not guaranteed to be available in all implementations of JSSE.

This API contains classes and interfaces related to creating and configuring secure socket factories. These include key and trust manager interfaces (including X.509-specific key and trust managers), factories for creating key and trust managers, a class representing a secure socket protocol implementation that acts as a factory for secure socket factories, and a class for an HTTP URL connection with support for HTTPS-specific features.

SunJSSE Provider

The JSSE 1.0.2 reference implementation release comes standard with a provider named "SunJSSE", which must be installed and registered and which supplies the following cryptographic services:

What's New in JSSE 1.0.2

Here are the differences between JSSE 1.0.1 and JSSE 1.0.2:

Stronger Cryptography in Global Version

Recent changes in U.S. export regulations have enabled inclusion of stronger cryptographic algorithms in the global version of JSSE 1.0.2 than were possible in JSSE 1.0.1. As a matter of fact, the same cryptographic suites are now included in both the domestic and global versions of JSSE 1.0.2. The only difference between the two versions is the pluggability.

Runs on PersonalJavaTM version 3.1

The JSSE 1.0.2 reference implementation was slightly modified to enable it to be run on PersonalJavaTM version 3.1. The modifications do not affect the JSSE 1.0.2 API.

A new SSLPermission class was created, in the com.sun.net.ssl package. In JSSE 1.0.1, there were JSSE-specific permission checks which used java.net.NetPermission, when in fact the checks should have been more specific to JSSE. SSLPermission replaces those NetPermission access control checks (i.e. SSLSession.getSessionContext(), and HttpsURLConnection.setHostnameVerifier()).

One thing to note is that the JSSE 1.0.2 reference implementation code that previously depended on java.net.NetPermission now depends on com.sun.net.ssl.SSLPermission instead. Thus, if you previously granted java.net.NetPermission for any JSSE-specific checks to any application classes (e.g., in a policy file), you now need to grant com.sun.net.ssl.SSLPermission instead.

Bug Fixes

The JSSE 1.0.2 release contains a number of bug fixes, including the ones listed below.

  • An X.509 certificate bug in the releases prior to JDK 1.3 caused SSL negotiations to fail. If a received certificate contained an undefined PathLen in one of its BasicConstraints, an application would report
        javax.net.ssl.SSLException: untrusted server cert chain
    

    In JSSE 1.0.2 the exception is no longer thrown when a certificate has an undefined PathLen in a BasicConstraint.

  • There is enhanced debugging support for the X509KeyManager and X509TrustManager supplied by the "SunJSSE" provider, and for the default SSLContext. See Debugging Utilities for information about dynamic debug tracing support.

  • The certificate for "duke" in the sample code's keystore was reissued. In prior versions of JSSE, the duke certificate was issued using the DSA algorithm, making it difficult for people trying to run the samples with the Netscape Navigator or Internet Explorer browsers as the client, because those browsers expect the server certificates to be RSA-based. In JSSE 1.0.2, the "duke" certificate has been issued using the RSA algorithm.

  • In JSSE 1.0.1, the search for a truststore was handled inconsistently. All searches for a truststore are now handled the same: they check for a file specified by the javax.net.ssl.trustStore system property first, followed by jssecacerts and cacerts, using whichever file is found first.

Documentation Improvements

This JSSE API User's Guide was substantially expanded and clarified.

Related Documentation

Java Secure Socket Extension Documentation

Java 2 Platform Security Documentation

Export Issues Related to Cryptography

For information on U.S. encryption policies, refer to these Web sites:

For more information about other cryptographic issues, refer to these Web sites:

Secure Sockets Layer Documentation

Online resources:

Books:

  • SSL and TLS Essentials: Securing the Web by Stephen Thomas. John Wiley and Sons, Inc., 2000.
  • Java 2 Network Security , Second Edition, by Marco Pistoia, Duane F Reller, Deepak Gupta, Milind Nagnur, and Ashok K Ramani. Prentice Hall, 1999. Copyright 1999 International Business Machines.

Terms and Definitions

There are several terms relating to cryptography that are used within this document. This section defines some of these terms.

Authentication

Authentication is the process of confirming the identity of a party with whom one is communicating.

Cipher Suite

A cipher suite is a combination of cryptographic parameters that define the security algorithms and key sizes used for authentication, key agreement, encryption, and integrity protection.

Certificate

A certificate is a digitally signed statement vouching for the identity and public key of an entity (person, company, etc.). Certificates can either be self-signed or issued by a Certification Authority (CA). Certification Authorities are entities that are trusted to issue valid certificates for other entities. Well-known CAs include VeriSign, Entrust, and GTE CyberTrust. X509 is a common certificate format, and they can be managed by the JDK's keytool.

Cryptographic Hash Function

A cryptographic hash function is similar to a checksum. Data is processed with an algorithm that produces a relatively small string of bits called a hash. A cryptographic hash function has three primary characteristics: it is a one-way function, meaning that it is not possible to produce the original data from the hash; a small change in the original data produces a large change in the resulting hash; and it does not require a cryptographic key.

Cryptographic Service Provider

In the JCA, implementations for various cryptographic algorithms are provided by cryptographic service providers, or "providers" for short. Providers are essentially packages that implement one or more engine classes for specific algorithms. An engine class defines a cryptographic service in an abstract fashion without a concrete implementation.

Digital Signature

A digital signature is the digital equivalent of a handwritten signature. It is used to ensure that data transmitted over a network was sent by whoever claims to have sent it and that the data has not been modified in transit. For example, an RSA-based digital signature is calculated by first computing a cryptographic hash of the data and then encrypting the hash with the sender's private key.

Encryption and Decryption

Encryption is the process of using a complex algorithm to convert an original message, or cleartext, to an encoded message, called ciphertext, that is unintelligible unless it is decrypted. Decryption is the inverse process of producing cleartext from ciphertext. The algorithms used to encrypt and decrypt data typically come in two categories: secret key (symmetric) cryptography and public key (asymmetric) cryptography.

Handshake Protocol

The negotiation phase during which the two socket peers agree to use a new or existing session. The handshake protocol is a series of messages exchanged over the record protocol. At the end of the handshake new connection-specific encryption and integrity protection keys are generated based on the key agreement secrets in the session.

Key Agreement

Key agreement is a protocol by which 2 or more parties can establish the same cryptographic keys, without having to exchange any secret information in the clear. Examples include RSA and Diffie-Hellman.

Key Managers and Trust Managers

Key managers (see KeyManagerFactory) and trust managers (see TrustManagerFactory) use keystores for their key material. A key manager manages a keystore and supplies public keys to others as needed, e.g., for use in authenticating the user to others. A trust manager makes decisions about who to trust based on information in the truststore it manages.

Keystores and Truststores

A keystore is a database of key material. Key material is used for a variety of purposes, including authentication and data integrity. There are various types of keystores available, including "PKCS12" and Sun's "JKS."

Generally speaking, keystore information can be grouped into two different categories: key entries and trusted certificate entries. A key entry consists of an entity's identity and its private key, and can be used for a variety of cryptographic purposes. In contrast, a trusted certificate entry only contains a public key in addition to the entity's identity. Thus, a trusted certificate entry can not be used where a private key is required, such as in a com.sun.net.ssl.KeyManager. In the JDK implementation of "JKS", a keystore may contain both keyEntry's and trustedCertEntry's.

A truststore is a keystore which is used when making decisions about what to trust. If you receive some data from an entity that you already trust, and if you can verify that the entity is the one it claims to be, then you can assume that the data really came from that entity.

An entry should only be added to a truststore if the user makes a decision to trust that entity. By either generating a keypair or by importing a certificate, the user has given trust to that entry, and thus any entry in the keystore is considered a trusted entry.

It may be useful to have two different keystore files: one containing just your key entries, and the other containing your trusted certificate entries, including Certification Authority (CA) certificates. The former contains private information, while the latter does not. Using two different files instead of a single keystore file provides for a cleaner separation of the logical distinction between your own certificates (and corresponding private keys) and others' certificates. You could provide more protection for your private keys if you store them in a keystore with restricted access, while providing the trusted certificates in a more publicly accessible keystore if needed.

Message Authentication Code

A Message Authentication Code (MAC) provides a way to check the integrity of information transmitted over or stored in an unreliable medium, based on a secret key. Typically, MACs are used between two parties that share a secret key in order to validate information transmitted between these parties.

A MAC mechanism that is based on cryptographic hash functions is referred to as HMAC. HMAC can be used with any cryptographic hash function, such as Message Digest 5 (MD5) and Secure Hash Algorithm (SHA), in combination with a secret shared key. HMAC is specified in RFC 2104.

Public Key Cryptography

Public key cryptography uses an encryption algorithm in which two keys are produced. One key is made public while the other is kept private. The public key and the private key are cryptographic inverses; what one key encrypts only the other key can decrypt. Public key cryptography is also called asymmetric cryptography.

Record Protocol

The record protocol packages all data whether application-level or as part of the handshake process into discrete records of data much like a TCP stream socket converts an application byte stream into network packets. The individual records are then protected by the current encryption and integrity protection keys.

Secret Key Cryptography

Secret key cryptography uses an encryption algorithm in which the same key is used both to encrypt and decrypt the data. Secret key cryptography is also called symmetric cryptography.

Session

A session is a named collection of state information including authenticated peer identity, cipher suite, and key agreement secrets which are negotiated through a secure socket handshake and which can be shared among multiple secure socket instances.

Truststore

See Keystores and Truststores.

Secure Sockets Layer (SSL) Protocol Overview

Secure Sockets Layer (SSL) is the most widely used protocol for implementing cryptography on the Web. SSL uses a combination of cryptographic processes to provide secure communication over a network. This section provides an introduction to SSL and the cryptographic processes it uses.

SSL provides a secure enhancement to the standard TCP/IP sockets protocol used for Internet communications. As shown in the "TCP/IP Protocol Stack With SSL" figure below, the secure sockets layer is added between the transport layer and the application layer in the standard TCP/IP protocol stack. The application most commonly used with SSL is Hypertext Transfer Protocol (HTTP), the protocol for Internet Web pages. Other applications, such as Net News Transfer Protocol (NNTP), Telnet, Lightweight Directory Access Protocol (LDAP), Interactive Message Access Protocol (IMAP), and File Transfer Protocol (FTP), can be used with SSL as well.

Note: There is currently no standard for secure FTP.

TCP/IP Protocol Stack With SSL

TCP/IP Layer

Protocol

Application Layer

    HTTP, NNTP, Telnet, FTP, etc.

Secure Sockets Layer

    SSL

Transport Layer

    TCP

Internet Layer

    IP

SSL was developed by Netscape in 1994, and with input from the Internet community, has evolved to become a standard. It is now under the control of the international standards organization, the Internet Engineering Task Force (IETF). The IETF has renamed SSL to Transport Layer Security (TLS), and released the first specification, version 1.0, in January 1999. TLS 1.0 is a modest upgrade to the most recent version of SSL, version 3.0. The differences between SSL 3.0 and TLS 1.0 are minor.

Why Use SSL?

Transferring sensitive information over a network can be risky due to the following three issues:

SSL addresses each of these issues. It addresses the first issue by optionally allowing each of two communicating parties to ensure the identity of the other party in a process called authentication. Once the parties are authenticated, SSL provides an encrypted connection between the two parties for secure message transmission. Encrypting the communication between the two parties provides privacy and therefore addresses the second issue. The encryption algorithms used with SSL include a secure hash function, which is similar to a checksum. This ensures that data is not modified in transit. The secure hash function addresses the third issue of data integrity.

Note, both authentication and encryption are optional, and depend on the the negotiated cipher suites between the two entities.

The most obvious example of when you would use SSL is in an e-commerce transaction. In an e-commerce transaction, it would be foolish to assume that you can guarantee the identity of the server with whom you are communicating. It would be easy enough for someone to create a phony Web site promising great services if only you enter your credit card number. SSL allows you, the client, to authenticate the identity of the server. It also allows the server to authenticate the identity of the client, although in Internet transactions, this is seldom done.

Once the client and the server are comfortable with each other's identity, SSL provides privacy and data integrity through the encryption algorithms it uses. This allows sensitive information, such as credit card numbers, to be transmitted securely over the Internet.

While SSL provides authentication, privacy, and data integrity, it does not provide non-repudiation services. Non-repudiation means that an entity that sends a message cannot later deny that they sent it. When the digital equivalent of a signature is associated with a message, the communication can later be proved. SSL alone does not provide non-repudiation.

How SSL Works

One of the reasons SSL is effective is that it uses several different cryptographic processes. SSL uses public key cryptography to provide authentication, and secret key cryptography and digital signatures to provide for privacy and data integrity. Before you can understand SSL, it is helpful to understand these cryptographic processes.

Cryptographic Processes

The primary purpose of cryptography is to make it difficult for an unauthorized third party to access and understand private communication between two parties. It is not always possible to restrict all unauthorized access to data, but private data can be made unintelligible to unauthorized parties through the process of encryption. Encryption uses complex algorithms to convert the original message, or cleartext, to an encoded message, called ciphertext. The algorithms used to encrypt and decrypt data that is transferred over a network typically come in two categories: secret key cryptography and public key cryptography. These forms of cryptography are explained in the following subsections.

Both secret key cryptography and public key cryptography depend on the use of an agreed-upon cryptographic key or pair of keys. A key is a string of bits that is used by the cryptographic algorithm or algorithms during the process of encrypting and decrypting the data. A cryptographic key is like a key for a lock: only with the right key can you open the lock.

Safely transmitting a key between two communicating parties is not a trivial matter. A public key certificate allows a party to safely transmit its public key, while ensuring the receiver of the authenticity of the public key. Public key certificates are described in a later section.

In the descriptions of the cryptographic processes that follow, we use the conventions used by the security community: we label the two communicating parties with the names Alice and Bob. We call the unauthorized third party, also known as the attacker, Charlie.

Secret Key Cryptography

With secret key cryptography, both communicating parties, Alice and Bob, use the same key to encrypt and decrypt the messages. Before any encrypted data can be sent over the network, both Alice and Bob must have the key and must agree on the cryptographic algorithm that they will use for encryption and decryption.

One of the major problems with secret key cryptography is the logistical issue of how to get the key from one party to the other without allowing access to an attacker. If Alice and Bob are securing their data with secret key cryptography, and if Charlie gains access to their key, Charlie can understand any secret messages he intercepts between Alice and Bob. Not only can Charlie decrypt Alice's and Bob's messages, but he can also pretend that he is Alice and send encrypted data to Bob. Bob will not know that the message came from Charlie, not Alice.

Once the problem of secret key distribution is solved, secret key cryptography can be a valuable tool. The algorithms provide excellent security and encrypt data relatively quickly. The majority of the sensitive data sent in an SSL session is sent using secret key cryptography.

Secret key cryptography is also called symmetric cryptography because the same key is used to both encrypt and decrypt the data. Well-known secret key cryptographic algorithms include the Data Encryption Standard (DES), triple-strength DES (3DES), Rivest Cipher 2 (RC2), and Rivest Cipher 4 (RC4).

Public Key Cryptography

Public key cryptography solves the logistical problem of key distribution by using both a public key and a private key. The public key can be sent openly through the network while the private key is kept private by one of the communicating parties. The public and the private keys are cryptographic inverses of each other; what one key encrypts, the other key will decrypt.

Let's assume that Bob wants to send a secret message to Alice using public key cryptography. Alice has both a public key and a private key, so she keeps her private key in a safe place and sends her public key to Bob. Bob encrypts the secret message to Alice using Alice's public key. Alice can later decrypt the message with her private key.

If Alice encrypts a message using her private key and sends the encrypted message to Bob, Bob can be sure that the data he receives comes from Alice; if Bob can decrypt the data with Alice's public key, the message must have been encrypted by Alice with her private key, and only Alice has Alice's private key. The problem is that anybody else can read the message as well because Alice's public key is public. While this scenario does not allow for secure data communication, it does provide the basis for digital signatures. A digital signature is one of the components of a public key certificate, and is used in SSL to authenticate a client or a server. Public key certificates and digital signatures are described in later sections.

Public key cryptography is also called asymmetric cryptography because different keys are used to encrypt and decrypt the data. A well known public key cryptographic algorithm often used with SSL is the Rivest Shamir Adleman (RSA) algorithm. Another public key algorithm used with SSL that is designed specifically for secret key exchange is the Diffie-Hellman (DH) algorithm. Public key cryptography requires extensive computations, making it very slow. It is therefore typically used only for encrypting small pieces of data, such as secret keys, rather than for the bulk of encrypted data communications.

A Comparison Between Secret Key and Public Key Cryptography

Both secret key cryptography and public key cryptography have strengths and weaknesses. With secret key cryptography, data can be encrypted and decrypted quickly, but since both communicating parties mush share the same secret key information, the logistics of exchanging the key can be a problem. With public key cryptography, key exchange is not a problem since the public key does not need to be kept secret, but the algorithms used to encrypt and decrypt data require extensive computations, and are therefore very slow.

Public Key Certificates

A public key certificate provides a safe way for an entity to pass on its public key to be used in asymmetric cryptography. The public key certificate avoids the following situation: if Charlie creates his own public key and private key, he can claim that he is Alice and send his public key to Bob. Bob will be able to communicate with Charlie, but Bob will think that he is sending his data to Alice.

A public key certificate can be thought of as the digital equivalent of a passport. It is issued by a trusted organization and provides identification for the bearer. A trusted organization that issues public key certificates is known as a certificate authority (CA). The CA can be likened to a notary public. To obtain a certificate from a CA, one must provide proof of identity. Once the CA is confident that the applicant represents the organization it says it represents, the CA signs the certificate attesting to the validity of the information contained within the certificate.

A public key certificate contains several fields, including:

  • Issuer - The issuer is the CA that issued the certificate. If a user trusts the CA that issues a certificate, and if the certificate is valid, the user can trust the certificate.

  • Period of validity - A certificate has an expiration date, and this date is one piece of information that should be checked when verifying the validity of a certificate.

  • Subject - The subject field includes information about the entity that the certificate represents.

  • Subject's public key - The primary piece of information that the certificate provides is the subject's public key. All the other fields are provided to ensure the validity of this key.

  • Signature - The certificate is digitally signed by the CA that issued the certificate. The signature is created using the CA's private key and ensures the validity of the certificate. Because only the certificate is signed, not the data sent in the SSL transaction, SSL does not provide for non-repudiation.

If Bob only accepts Alice's public key as valid when she sends it in a public key certificate, Bob will not be fooled into sending secret information to Charlie when Charlie masquerades as Alice.

Multiple certificates may be linked in a certificate chain. When a certificate chain is used, the first certificate is always that of the sender. The next is the certificate of the entity that issued the sender's certificate. If there are more certificates in the chain, each is that of the authority that issued the previous certificate. The final certificate in the chain is the certificate for a root CA. A root CA is a public certificate authority that is widely trusted. Information for several root CAs is typically stored in the client's Internet browser. This information includes the CA's public key. Well-known CAs include VeriSign, Entrust, and GTE CyberTrust.

Cryptographic Hash Functions

When sending encrypted data, SSL typically uses a cryptographic hash function to ensure data integrity. The hash function prevents Charlie from tampering with data that Alice sends to Bob.

A cryptographic hash function is similar to a checksum. The main difference is that while a checksum is designed to detect accidental alterations in data, a cryptographic hash function is designed to detect deliberate alterations. When data is processed by a cryptographic hash function, a small string of bits, known as a hash, is generated. The slightest change to the message typically makes a large change in the resulting hash. A cryptographic hash function does not require a cryptographic key. Two hash functions often used with SSL are Message Digest 5 (MD5) and Secure Hash Algorithm (SHA). SHA was proposed by the US National Institute of Science and Technology (NIST).

Message Authentication Code

A message authentication code (MAC) is similar to a cryptographic hash, except that it is based on a secret key. When secret key information is included with the data that is processed by a cryptographic hash function, the resulting hash is known as an HMAC.

If Alice wants to be sure that Charlie does not tamper with her message to Bob, she can calculate an HMAC for her message and append the HMAC to her original message. She can then encrypt the message plus the HMAC using a secret key she shares with Bob. When Bob decrypts the message and calculates the HMAC, he will be able to tell if the message was modified in transit. With SSL, an HMAC is used with the transmission of secure data.

Digital Signatures

Once a cryptographic hash is created for a message, the hash is encrypted with the sender's private key. This encrypted hash is called a digital signature.

The SSL Process

Communication using SSL begins with an exchange of information between the client and the server. This exchange of information is called the SSL handshake.

The three main purposes of the SSL handshake are:

  • Negotiate the cipher suite

  • Authenticate identity (optional)

  • Establish information security by agreeing on encryption mechanisms

Negotiating the Cipher Suite

The SSL session begins with a negotiation between the client and the server as to which cipher suite they will use. A cipher suite is a set of cryptographic algorithms and key sizes that a computer can use to encrypt data. The cipher suite includes information about available public key exchange algorithms, secret key encryption algorithms, and cryptographic hash functions. The client tells the server which cipher suites it has available, and the server chooses the best mutually acceptable cipher suite.

Authenticating the Server

In SSL, the authentication step is optional, but in the example of an e-commerce transaction over the Web, the client will generally want to authenticate the server. Authenticating the server allows the client to be sure that the server represents the entity that the client believes the server represents.

To prove that a server belongs to the organization that it claims to represent, the server presents its public key certificate to the client. If this certificate is valid, the client can be sure of the identity of the server.

The client and server exchange information that allows them to agree on the same secret key. For example, with RSA, the client uses the server's public key, obtained from the public key certificate, to encrypt the secret key information. The client sends the encrypted secret key information to the server. Only the server can decrypt this message since the server's private key is required for this decryption.

Sending the Encrypted Data

Both the client and the server now have access to the same secret key. With each message, they use the cryptographic hash function, chosen in the first step of this process, and shared secret information, to compute an HMAC that they append to the message. They then use the secret key and the secret key algorithm negotiated in the first step of this process to encrypt the secure data and the HMAC. The client and server can now communicate securely using their encrypted and hashed data.

The SSL Protocol

The previous section provides a high-level description of the SSL handshake, which is the exchange of information between the client and the server prior to sending the encrypted message. This section provides more detail.

The "SSL Messages" figure below shows the sequence of messages that are exchanged in the SSL handshake. Messages that are only sent in certain situations are noted as optional. Each of the SSL messages is described in the following figure:

SSL Messages

Client

 

Server

1. Client hello

----->        

<-----

2. Server hello

<-----  

3. Certificate (Optional)

<-----

4. Certificate request (Optional)

<-----

5. Server key exchange (Optional)

<-----

6. Server hello done

7. Certificate (Optional)

----->

8. Client key exchange

----->

9. Certificate verify (Optional)

----->

10. Change cipher spec

----->

11. Finished

----->

<-----

12. Change cipher spec

<-----

13. Finished

14. Encrypted data

<-----

14. Encrypted data

The SSL messages are sent in the following order:

  1. Client hello - The client sends the server information including the highest version of SSL it supports and a list of the cipher suites it supports. (TLS 1.0 is indicated as SSL 3.1.) The cipher suite information includes cryptographic algorithms and key sizes.

  2. Server hello - The server chooses the highest version of SSL and 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 a certificate or a certificate chain. A certificate chain typically begins with the server's public key certificate and ends with the certificate authority's root certificate. This message is optional, but is used whenever server authentication is required.

  4. Certificate request - If the server needs to authenticate the client, it sends the client a certificate request. In Internet applications, this message is rarely sent.

  5. Server key exchange - The server sends the client a server key exchange message when the public key information sent in 3) above is not sufficient for key exchange.

  6. Server hello done - The server tells the client that it is finished with its initial negotiation messages.

  7. Certificate - If the server requests a certificate from the client in Message 4, the client sends its certificate chain, just as the server did in Message 3.

    Note: At the time of this writing (May 2000), only a few Internet server applications ask for a certificate from the client. When a certificate is required from the client, the user must obtain their own certificate from a certificate authority.

  8. Client key exchange - The client generates information used to create a key to use for symmetric encryption. For RSA, the client then encrypts this key information with the server's public key and sends it to the server.

  9. Certificate verify - In internet applications, this message is rarely sent. Its purpose is to allow the server to complete the process of authenticating the client. When this message is used, the client sends information that it digitally signs using a cryptographic hash function. When the server decrypts this information with the client's public key, the server is able to authenticate the client.

  10. Change cipher spec - The client sends a message telling the server to change to encrypted mode.

  11. Finished - The client tells the server that it is ready for secure data communication to begin.

  12. Change cipher spec - The server sends a message telling the client to change to encrypted mode.

  13. Finished - The server tells the client that it is ready for secure data communication to begin. This is the end of the SSL handshake.

  14. Encrypted data - The client and the server communicate using the symmetric encryption algorithm and the cryptographic hash function negotiated in Messages 1 and 2, and using the secret key that the client sent to the server in Message 8.

If the parameters generated during an SSL session are saved, these parameters can sometimes be re-used for future SSL sessions. Saving SSL session parameters allows encrypted communication to begin much more quickly.

SSL and TLS References

For a list of resources containing more information about SSL, see Secure Sockets Layer Documentation .


Key Classes

Core Classes and Interfaces

The core JSSE classes are part of the javax.net and javax.net.ssl packages.

SSLSocket and SSLServerSocket Classes

The javax.net.ssl.SSLSocket class is a subclass of the standard Java java.net.Socket class. It supports all of the standard socket methods and adds additional methods specific to secure sockets. Instances of this class encapsulate the SSLContext under which they were created. There are APIs to control the creation of secure socket sessions for a socket instance but trust and key management are not directly exposed.

The javax.net.ssl.SSLServerSocket class is analogous to the SSLSocket class, but is used specifically for creating server sockets.

Obtaining an SSLSocket

Instances of SSLSocket can be obtained in two ways. First, an SSLSocket can be created by an instance of SSLSocketFactory via one of the several createSocket methods on that class. The second way to obtain SSLSockets is through the accept method on the SSLServerSocket class.

SocketFactory and ServerSocketFactory Classes

The abstract javax.net.SocketFactory class is used to create sockets. It must be subclassed by other factories, which create particular subclasses of sockets and thus provide a general framework for the addition of public socket-level functionality. (See, for example, SSLSocketFactory.)

The javax.net.ServerSocketFactory class is analogous to the SocketFactory class, but is used specifically for creating server sockets.

Socket factories are a simple way to capture a variety of policies related to the sockets being constructed, producing such sockets in a way which does not require special configuration of the code which asks for the sockets:

  • Due to polymorphism of both factories and sockets, different kinds of sockets can be used by the same application code just by passing different kinds of factories.

  • Factories can themselves be customized with parameters used in socket construction. So for example, factories could be customized to return sockets with different networking timeouts or security parameters already configured.

  • The sockets returned to the application can be subclasses of java.net.Socket (or javax.net.ssl.SSLSocket), so that they can directly expose new APIs for features such as compression, security, record marking, statistics collection, or firewall tunneling.

SSLSocketFactory and SSLServerSocketFactory Classes

A javax.net.ssl.SSLSocketFactory acts as a factory for creating secure sockets. This class is a concrete implementation of the abstract SocketFactory class provided with JSSE in the javax.net package.

Secure socket factories encapsulate the details of creating and initially configuring secure sockets. This includes authentication keys, peer certificate validation, enabled cipher suites and the like.

The javax.net.ssl.SSLServerSocketFactory class is analogous to the SSLSocketFactory class, but is used specifically for creating server sockets.

Obtaining an SSLSocketFactory

There are three primary ways of obtaining an SSLSocketFactory:

  • Get the default factory by calling the SSLSocketFactory.getDefault static method.

  • Receive a factory as an API parameter. That is, code which needs to create sockets but which doesn't care about the details of how the sockets are configured can include a method with an SSLSocketFactory parameter that can be called by clients to specify which SSLSocketFactory to use when creating sockets. (For example, com.sun.net.ssl.HttpsURLConnection.)

  • Construct a new factory with specifically configured behavior.

The default factory is typically configured to support server authentication only so that sockets created by the default factory do not leak any more information about the client than a normal TCP socket would.

Many classes which create and use sockets do not need to know the details of socket creation behavior. Creating sockets through a socket factory passed in as a parameter is a good way of isolating the details of socket configuration, and increases the reusability of classes which create and use sockets.

You can create new socket factory instances either by implementing your own socket factory subclass or by using another class which acts as a factory for socket factories. One example of such a class is SSLContext, which is provided with the JSSE 1.0.2 reference implementation as a non-standard provider-based configuration class.

SSLSession Interface

A javax.net.ssl.SSLSession represents a security context negotiated between the two peers of an SSLSocket connection. Once a session has been arranged, it can be shared by future SSLSockets connected between the same two peers. The session contains the cipher suite which will be used for communications over a secure socket as well as a non-authoritative hint as to the network address of the remote peer, and management information such as the time of creation and last use. A session also contains a shared master secret negotiated between the peers that is used to create cryptographic keys for encrypting and guaranteeing the integrity of the communications over an SSLSocket. The value of this master secret is known only to the underlying secure socket implementation and is not exposed through the SSLSession API.

Support Classes and Interfaces

These classes are provided as part of the JSSE 1.0.2 API to support the creation, use, and management of secure sockets. They are less likely to be used by secure socket applications than are the core classes. The support classes and interfaces are part of the javax.net.ssl and javax.security.cert packages.

SSLSessionContext Interface

A javax.net.ssl.SSLSessionContext is a grouping of SSLSessions associated with a single entity. For example, it could be associated with a server or client that participates in many sessions concurrently. The methods on this interface enable the enumeration of all sessions in a context and allow lookup of specific sessions via their session ids.

An SSLSessionContext may optionally be obtained from an SSLSession by calling the SSLSession getSessionContext method. The context may be unavailable in some environments, in which case the getSessionContext method returns null.

SSLSessionBindingListener Interface

javax.net.ssl.SSLSessionBindingListener is an interface implemented by objects which want to be notified when they are being bound or unbound from an SSLSession.

SSLSessionBindingEvent Class

A javax.net.ssl.SSLSessionBindingEvent is the event communicated to a SSLSessionBindingListener when it is bound or unbound from an SSLSession.

HandShakeCompletedListener Interface

javax.net.ssl.HandShakeCompletedListener is an interface implemented by any class which wants to receive notification of the completion of an SSL protocol handshake on a given SSLSocket connection.

HandShakeCompletedEvent Class

A javax.net.ssl.HandShakeCompletedEvent is the event communicated to a HandShakeCompletedListener upon completion of an SSL protocol handshake on a given SSLSocket connection.

X509Certificate Class

Many secure socket protocols perform authentication using public key certificates, also called X.509 certificates. This is the default authentication mechanism for the SSL and TLS protocols.

The javax.security.cert.X509Certificate abstract class provides a standard way to access the attributes of X.509 certificates.

This javax.security.cert.X509Certificate class is similar to java.security.cert.X509Certificate, and is currently implemented as a wrapper around java.security.cert.X509Certificate.

Reference Implementation Classes and Interfaces

These classes and interfaces are provided with the JSSE reference implementation, in the com.sun.net.ssl package. They are not part of the JSSE 1.0.2 standard API, and thus may not be available in other implementations.

Three of the classes described in this section (SSLContext, KeyManagerFactory, and TrustManagerFactory) are engine classes. An engine class is an API class for specific algorithms (or protocols, in the case of SSLContext), for which implementations may be provided in one or more Cryptographic Service Provider (provider) packages. For more information on providers and engine classes, see the "Design Principles" and "Concepts" sections of the JavaTM Cryptography Architecture API Specification & Reference.

The SunJSSE provider that comes standard with JSSE 1.0.2 provides SSLContext, KeyManagerFactory, and TrustManagerFactory implementations, as well as implementations for engine classes in the standard Java security (java.security) API. The implementations supplied by SunJSSE are:

Engine Class        Algorithm or 
Implemented           Protocol

KeyFactory            RSA

KeyPairGenerator      RSA

KeyStore              PKCS12

Signature             MD2withRSA
Signature             MD5withRSA
Signature             SHA1withRSA

KeyManagerFactory     SunX509
TrustManagerFactory   SunX509

SSLContext            SSL
SSLContext            SSLv3
SSLContext            TLS
SSLContext            TLSv1

SSLContext Class

com.sun.net.ssl.SSLContext is an engine class for an implementation of a secure socket protocol. An instance of this class acts as a factory for SSL socket factories. An SSLContext holds all of the state information shared across all sockets created under that context. For example, session state is associated with the SSLContext when it is negotiated through the handshake protocol by sockets created by socket factories provided by the context. These cached sessions can be reused and shared by other sockets created under the same context.

Each instance is configured through its init method with the keys, certificate chains, and trusted root CA certificates that it needs to perform authentication. This configuration is provided in the form of key and trust managers. These managers provide support for the authentication and key agreement aspects of the cipher suites supported by the context.

Currently, only X.509-based managers are supported.

Creating an SSLContext Object

Like other JCA provider-based "engine" classes, SSLContext objects are created using the getInstance factory methods of the SSLContext class. These static methods each return an instance that implements a requested secure socket protocol.

Note: An SSLContext object is automatically created and initialized when you call SSLSocketFactory.getDefault, if one hasn't already been assigned to that SSLSocketFactory. Thus, you don't have to directly create and initialize an SSLContext object, but you can if you want to override the default behavior.

To create an SSLContext object by calling a getInstance factory method, you must specify the protocol name. You may also specify which provider you want to supply the implementation of the requested protocol:

public static SSLContext getInstance(String protocol);

public static SSLContext getInstance(String protocol,
                                     String provider);

public static SSLContext getInstance(String protocol,
                                     Provider provider);

If just a protocol name is specified, the system will determine if there is an implementation of the requested protocol available in the environment, and if there is more than one, if there is a preferred one.

If both a protocol name and a provider are specified, the system will determine if there is an implementation of the requested protocol in the provider requested, and throw an exception if there is not.

A protocol is a string (such as "SSL") that describes the secure socket protocol desired. Common protocol names for SSLContext objects are defined in Appendix A.

Here is an example of obtaining an SSLContext:

SSLContext sc = SSLContext.getInstance("SSL");

A newly-created SSLContext should be initialized by calling the init method:

public void init(KeyManager[] km, TrustManager[] tm,
                   SecureRandom random);

If the KeyManager[] paramater is null, then an empty KeyManager will be defined for this context. If the TrustManager[] parameter is null, the installed security providers will be searched for the highest-priority implementation of the TrustManagerFactory), from which an appropriate TrustManager will be obtained. Likewise, the secure random parameter may be null, in which case a default implementation will be used.

If the internal default context is used, (e.g. a SSLContext is created in the internals of JSSE 1.0.2), a default KeyManager and a TrustManager are created. The default SecureRandom implementation is also chosen.

TrustManagerFactory Class

To be able to authenticate the remote identity of a secure socket peer, you need to initialize an SSLContext object with one or more TrustManagers. You need to pass one TrustManager for each authentication mechanism that is supported. If null is passed into the SSLContext initialization, a trust manager will be created for you. Typically, there is a single trust manager that supports authentication based on X.509 public key certificates. Some secure socket implementations may also support authentication based on shared secret keys, Kerberos, or other mechanisms.

The com.sun.net.ssl.TrustManagerFactory is an engine class for a provider-based service that acts as a factory for one or more types of TrustManager objects. The SunJSSE provider implements a factory which can return a basic X.509 trust manager. Because it is provider-based, additional factories can be implemented and configured that provide additional or alternate trust managers that provide more sophisticated services or that implement installation-specific authentication policies.

Creating a TrustManagerFactory

You create an instance of this class in a similar manner to SSLContext, except for passing an algorithm name string instead of a protocol name to the getInstance method:
public static TrustManagerFactory
                  getInstance(String algorithm);

public static TrustManagerFactory
                  getInstance(String algorithm,
                              String provider);

public static TrustManagerFactory
                  getInstance(String algorithm,
                              Provider provider);

A sample algorithm name string is:

"SunX509"

A sample call is the following:

TrustManagerFactory tmf =
    TrustManagerFactory.getInstance("SunX509", "SunJSSE");

The above call will create an instance of the SunJSSE provider's default trust manager factory, which provides basic X.509-based certification path validity checking. In the 1.0.2 release, this performs a subset of the rules specified in RFC 2459.

A newly-created factory should be initialized by calling the init method:

public void init(KeyStore ks);
You may pass a KeyStore object, which the factory will query for information on which remote certificates should be trusted during authorization checks.

Some factories are capable of making trust decisions without having to be initialized with a KeyStore object. For example, they may access trust material from a local directory service via LDAP, may use a remote online certificate status checking server, or may access default trust material from a standard local location. For instance, if no KeyStore parameter is passed to the SunJSSE default SunX509 TrustManager factory, the factory uses the following steps to try to find trust material:

  1. If the system property:
    javax.net.ssl.trustStore
    
    defined, then the TrustManagerFactory attempts to find a file using the filename specified by that system property, and uses that file for the KeyStore. If that file does not exist, then a default TrustManager using an empty keystore is created.

  2. If that system property was not specified, then if the file
    <java-home>/lib/security/jssecacerts
    
    exists, that file is used. (See The Installation Directory <java-home> for information about what <java-home> refers to.) Otherwise,

  3. if the file
    <java-home>/lib/security/cacerts
    
    exists, that file is used.

(If none of these files exists, that may be okay because there are SSL cipher suites which are anonymous, that is, which don't do any authentication and thus don't need a truststore.)

The factory looks for a file specified via the security property javax.net.ssl.trustStore or for the jssecacerts file before checking for a cacerts file so that you can provide a JSSE-specific set of trusted root certificates separate from ones that might be present in cacerts for code-signing purposes.

X509TrustManager Interface

The com.sun.net.ssl.X509TrustManager interface extends the general TrustManager interface. It must be implemented by a trust manager for X.509-based authentication.

In order to support X.509 authentication of remote socket peers through JSSE, an instance of this interface must be passed to the init method of an SSLContext object.

Creating an X509TrustManager

You can either implement this interface directly yourself or obtain one from a provider-based TrustManagerFactory (such as that supplied by the SunJSSE provider). You could also implement your own that delegates to a factory-generated trust manager. For example, you might do this in order to filter the resulting trust decisions and query an end-user through a graphical user interface.

KeyManagerFactory Class

To be able to authenticate yourself (a local secure socket peer) to a remote secure socket peer, you need to initialize an SSLContext object with one or more KeyManagers. You need to pass one KeyManager for each different authentication mechanism that will be supported. If null is passed into the SSLContext initialization, no KeyManager will be available. If the internal default context is used, a default KeyManager is created.

Typically, there is a single key manager that supports authentication based on X.509 public key certificates. Some secure socket implementations may also support authentication based on shared secret keys, Kerberos, or other mechanisms.

com.sun.net.ssl.KeyManagerFactory is an engine class for a provider-based service that acts as a factory for one or more types of KeyManager objects. The SunJSSE provider implements a factory which can return a basic X.509 key manager. Because it is provider-based, additional factories can be implemented and configured to provide additional or alternate key managers.

Creating a KeyManagerFactory

You create an instance of this class in a similar manner to SSLContext, except for passing an algorithm name string instead of a protocol name to the getInstance method:
public static KeyManagerFactory
                  getInstance(String algorithm);

public static KeyManagerFactory
                  getInstance(String algorithm,
                              String provider);

public static KeyManagerFactory
                  getInstance(String algorithm,
                              Provider provider);

A sample algorithm name string is:

"SunX509"

A sample call is the following:

KeyManagerFactory kmf =
    KeyManagerFactory.getInstance("SunX509", "SunJSSE");

The above call will create an instance of the SunJSSE provider's default key manager factory, which provides basic X.509-based authentication keys.

A newly-created factory should be initialized by calling the init method:

public void init(KeyStore ks, char[] password);
You may pass a KeyStore object, which the factory will query for information on which private key and matching public key certificates should be used for authenticating to a remote socket peer. In addition to the KeyStore object, you must also provide a second parameter which gives the password that will be used with the methods for accessing keys from the KeyStore. All keys in the KeyStore must be protected by the same password.

Some factories are capable of providing access to authentication material without having to be initialized with a KeyStore object. For example, they may access key material as part of a login mechanism such as one based on JAAS, the Java Authentication and Authorization Service.

The SunJSSE provider supports a "SunX509" factory that must be initialized with a KeyStore parameter.

X509KeyManager Interface

The com.sun.net.ssl.X509KeyManager interface extends the general KeyManager interface. It must be implemented by a key manager for X.509-based authentication. In order to support X.509 authentication to remote socket peers through JSSE, an instance of this interface must be passed to the init method of an SSLContext object.

Creating an X509KeyManager

You can either implement this interface directly yourself or obtain one from a provider-based KeyManagerFactory (such as that supplied by the SunJSSE provider). You could also implement your own that delegates to a factory-generated key manager. For example, you might do this in order to filter the resulting keys and query an end-user through a graphical user interface.

Installing and Customizing JSSE 1.0.2

Installation

Instructions for installing JSSE 1.0.2 are provided at http://java.sun.com/products/jsse/install.html and will not be repeated here. A brief summary of the steps to install JSSE 1.0.2 is:

The following sections provide some additional installation-specific information and guidance, followed by information about how to do optional customizations.

The Installation Directory <java-home>

The term <java-home> is used throughout this document to refer to the directory where the JRE is installed. It is determined based on whether you are running JSSE 1.0.2 on a JRE with or without the JavaTM 2 SDK installed. Java 2 SDK includes the JRE, but it is located in a different level in the file hierarchy.

The following are some examples of which directories <java-home> refers to:

  • On Solaris, if Java 2 SDK is installed in /home/user1/jdk1.2.2, then <java-home> is
    /home/user1/jdk1.2.2/jre
    

  • On Solaris, if JRE is installed in /home/user1/jre1.2.2 and Java 2 SDK is not installed, then <java-home> is
    /home/user1/jre1.2.2
    

  • On Win32 platforms, if Java 2 SDK is installed in C:\jdk1.2.2, then <java-home> is
    C:\jdk1.2.2\jre
    

  • On Win32 platforms, if JRE is installed in C:\jre1.2.2 and Java 2 SDK is not installed, then <java-home> is
    C:\jre1.2.2
    

Note: When using a different Java 2 version (e.g., 1.3), replace jdk1.2.2 with the other Java 2 SDK version name (e.g., jdk1.3) and jre1.2.2 with the other JRE version name (e.g., jre1.3) in the above examples.

Creating a Certificates File to Use With Navigator or Internet Explorer

When creating a certificates file to interact with Netscape Navigator or Microsoft Internet Explorer (IE), there is a common source of confusion. By default, keytool issues DSA public keys, but Navigator and IE do not recognize DSA public keys as part of their authentication procedures.

If you wish to interact with Navigator or IE, you will want to issue RSA keys. To do this, you need to specify the -keyalg RSA option when using keytool. For example:

keytool -genkey -alias duke -keystore testkeys -keyalg rsa

Special Considerations for Bundled Extensions

The preferred method of installing JSSE 1.0.2 is as an "installed" extension, but it is possible to make it "bundled" instead. If you install the JSSE JAR files as bundled extensions, there are a few special considerations noted here. For more information about bundled extensions, see Bundled Extensions.

  • If you bundle the JSSE JAR files with your application or applet, you must specify the relative URL to the JAR files in the Class-Path header of the manifest for the app.

  • It is also possible to instead make the JAR files available by placing them in a directory on the class path. Ensure the CLASSPATH environment variable includes the directory containing the files.

  • Permissions do not need to be granted to installed extensions, since the default system policy file grants all permissions to installed extensions. But if you install the JSSE 1.0.2 JAR files as bundled extensions, and applets or applications using JSSE 1.0.2 will be run while a security manager is installed, you will need to grant the JSSE JAR files appropriate permissions. (Note: There is typically a security manager installed whenever an applet is running, and a security manager may be installed for an application either via code in the application itself or via a command-line argument.)

    One way of finding out what permissions are needed is simply by trying to run the app and seeing which "inadequate permissions" errors you get.

    For your initial app testing, you can grant java.security.AllPermission. Here is an example of a statement granting AllPermission to the the jsse.jar file:

    grant codeBase "jsse.jar" {
        permission java.security.AllPermission;
    };
    

Testing the Installation

To test the installation, try compiling and running a simple program that uses the JSSE 1.0.2 API. For example, the sample JSSE_install_check program that follows sets up an SSLServerSocket and gets a list of the cipher suites that are available for the socket. If you can compile and run JSSE_install_check, JSSE is installed properly. Please note: This program may take a little while to complete execution.

import java.net.*;
import javax.net.ssl.*;

public class JSSE_install_check {

    public static void main(String[] args) throws Exception {

	SSLServerSocketFactory factory =
	    (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();

	SSLServerSocket sslSocket =
	    (SSLServerSocket)factory.createServerSocket(5757);

	String [] cipherSuites = sslSocket.getEnabledCipherSuites();

	for (int i = 0; i < cipherSuites.length; i++) {
	    System.out.println("Cipher Suite " + i +
		" = " + cipherSuites[i]);
	}
    }
}

Customization

JSSE 1.0.2 includes a reference implementation that all users can utilize. If desired, it is also possible to customize a number of aspects of JSSE 1.0.2, plugging in different implementations or specifying the default keystore, etc. The table below summarizes which aspects can be customized, what the defaults are, which mechanisms are used to provide customization, and which users (domestic only, or all) can do the specified customizations. The first column of the table provides links to more detailed descriptions of each designated aspect and how to customize it.

Some of the customizations are done by setting system property or security property values. Sections following the table explain how to set such property values.


IMPORTANT NOTE: Many of the properties shown in this table are currently utilized by the JSSE 1.0.2 reference implementation, but there is no guarantee that they will continue to have the same names and types (system or security) or even that they will exist at all in future releases. All such properties are flagged with an "*". They are documented here for your convenience for use with the JSSE 1.0.2 reference implementation.


JSSE 1.0.2 Customization

Customizable Item

Default

How Customize

Which Users Can Customize

X509Certificate implementation

Implementation from JSSE reference implementation

cert.provider.x509v1security property

All

HTTPS protocol implementation

None.

java.protocol.handler.pkgs system property

All

provider implementation

SunJSSE

A security.provider.n= line in security properties file. See description.

See description

default SSLSocketFactory implementation

Implementation from JSSE reference implementation

ssl.SocketFactory.provider security property

Domestic only

default SSLServerSocketFactory implementation

Implementation from JSSE reference implementation

ssl.ServerSocketFactory.provider security property

Domestic only

default keystore

None.

* javax.net.ssl.keyStore system property

All

default keystore type

KeyStore.getDefaultType()

* javax.net.ssl.keyStoreType system property

All

default keystore password

None.

* javax.net.ssl.keyStorePassword system property

All

default truststore

jssecacerts, if it exists. Otherwise, cacerts

* javax.net.ssl.trustStore system property

All

default truststore type

KeyStore.getDefaultType()

* javax.net.ssl.trustStoreType system property

All

default truststore password

None.

* javax.net.ssl.trustStorePassword system property

All

default key manager algorithm name

"SunX509"

* sun.ssl.keymanager.type security property

All

default trust manager algorithm name

"SunX509"

* sun.ssl.trustmanager.type security property

All

* This property is currently used by the JSSE 1.0.2 reference implementation. It is not guaranteed to be examined and used by other implementations. If it is examined by an implementation in JSSE 1.0.2, that implementation should handle it in the same manner as the JSSE 1.0.2 reference implementation does. There is no guarantee the property will continue to exist or be of the same type (system or security) in future releases.

How to Specify a System Property

Some aspects of JSSE 1.0.2 may be customized by setting system properties. You can set a system property either statically or dynamically:

How to Specify a Security Property

Some aspects of JSSE 1.0.2 may be customized by setting security properties. You can set a security property either statically or dynamically:

Customizing the X509Certificate Implementation

The X509Certificate implementation returned by the X509Certificate.getInstance method is by default the implementation from the JSSE 1.0.2 reference implementation.

You can optionally cause a different implementation to be returned. To do so, specify the name (and package) of the alternate implementation's class as the value of a security property named cert.provider.x509v1. For example, if the class is called MyX509CertificateImpl and it appears in the com.cryptox package, you should place the following in the security properties file:

cert.provider.x509v1=com.cryptox.MyX509CertificateImpl

Specifying an HTTPS Protocol Implementation

It is possible to access secure communications through the standard Java URL API. That is, you can communicate securely with an SSL-enabled web server by using the "https" URL protocol or scheme using the java.net.URL class.

In order to be able to do this, you need to have an "https" URLStreamHandler implementation and you must add the handler's implementation package name to the list of packages which are searched by the Java URL class. This is configured via the java.protocol.handler.pkgs system property. See the java.net.URL class documentation for details.

The JSSE 1.0.2 reference implementation provides an "https" URLStreamHandler implementation. Here is an example of how you would set the java.protocol.handler.pkgs property on the command line to indicate the JSSE 1.0.2 reference implementation's "https" URLStreamHandler:

java -Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol
  myApp
Note: This should all be typed on one line. It appears here on multiple lines only for legibility purposes.

Customizing the Provider Implementation

JSSE 1.0.2 comes standard with a Cryptographic Service Provider, or provider for short, named "SunJSSE". Providers are essentially packages that implement one or more engine classes for specific cryptographic algorithms. The JSSE 1.0.2 engine classes are SSLContext, KeyManagerFactory, and TrustManagerFactory. For more information on providers and engine classes, see the "Design Principles" and "Concepts" sections of the JavaTM Cryptography Architecture API Specification & Reference.

In order to be used, a provider must be registered, either statically or dynamically.

Registering the Cryptographic Service Provider Statically

You register a provider statically by adding a line of the following form to the security properties file:
security.provider.n=providerClassName

This declares a provider, and specifies its preference order "n". The preference order is the order in which providers are searched for requested algorithms (when no specific provider is requested). The order is 1-based; 1 is the most preferred, followed by 2, and so on.

The providerClassName is the fully qualified name of the provider class. You get this name from the provider vendor.

To register SunJSSE you add the above line to the security properties file, replacing providerClassName with com.sun.net.ssl.internal.ssl.Provider, and substituting n with the priority that you would like to assign to the "SunJSSE" provider. For example, to keep the standard provider shipped with the Java 2 platform and give it preference order 1, and add SunJSSE as the second preferred provider, the following two lines should appear in the security properties file:

security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider

To utilize another JSSE 1.0.2 provider, add a line registering the alternate provider, giving it whatever preference order you prefer.

You can have more than one JSSE 1.0.2 provider registered at the same time. They may include different implementations for different algorithms for different engine classes, or they may have support for some or all of the same types of algorithms and engine classes. When a particular engine class implementation for a particular algorithm is searched for, if no specific provider is specified for the search, the providers are searched in preference order and the implementation from the first provider that supplies an implementation for the specified algorithm is used.

Registering the Cryptographic Service Provider Dynamically

Instead of registering a provider statically, you can add the provider dynamically at runtime by calling the Security.addProvider method at the beginning of your program. For example, to add the SunJSSE provider dynamically, you would call:

Security.addProvider(
  new com.sun.net.ssl.internal.ssl.Provider());

The Security.addProvider method adds the specified provider to the next available preference position.

This type of registration is not persistent and can only be done by a program with sufficient permissions.

Customizing the Default SSLSocketFactory Implementation

The SSLSocketFactory implementation returned by the SSLSocketFactory.getDefault method is by default the implementation from the JSSE 1.0.2 reference implementation.

If you are a domestic user (in the U.S. or Canada), you can optionally cause a different implementation to be returned. To do so, specify the name (and package) of the alternate implementation's class as the value of a security property named ssl.SocketFactory.provider in the security properties file. For example, if the class is called MySSLSocketFactoryImpl and it appears in the com.cryptox package, you should place the following in the security properties file:

ssl.SocketFactory.provider=com.cryptox.MySSLSocketFactoryImpl

Note: If you are global (non-domestic) user, you cannot replace the default SSLSocketFactory implementation. If you try (by putting a line in the security properties file such as the one shown above), the implementation you specify will not be used and you will get a message like "SSL implementation not available" whenever you try to use the SSLSocketFactory returned by SSLSocketFactory.getDefault. Similarly, if you are a global user and you get an SSLContext from a JSSE 1.0.2 provider other than SunJSSE, that provider's SSLContext implementation should not return an SSLSocketFactory implementation other than the SunJSSE one when you call SSLContext.getSocketFactory. If the provider returns a non-SunJSSE implementation, you will get a runtime exception.

Customizing the Default SSLServerSocketFactory Implementation

The SSLServerSocketFactory implementation returned by the SSLServerSocketFactory.getDefault method is by default the implementation from the JSSE 1.0.2 reference implementation.

If you are a domestic user (in the U.S. or Canada), you can optionally cause a different implementation to be returned. To do so, specify the name (and package) of the alternate implementation's class as the value of a security property named ssl.ServerSocketFactory.provider in the security properties file. For example, if the class is called MySSLServerSocketFactoryImpl and it appears in the com.cryptox package, you should place the following in the security properties file:

  ssl.ServerSocketFactory.provider=com.cryptox.MySSLServerSocketFactoryImpl

Note: If you are a global (non-domestic) user, you cannot replace the default SSLServerSocketFactory implementation. If you try (by putting a line in the security properties file such as the one shown above), the implementation you specify will not be used and you will get a message like "SSL implementation not available" whenever you try to use the SSLServerSocketFactory returned by SSLServerSocketFactory.getDefault. Similarly, if you are a global user and you get an SSLContext from a JSSE 1.0.2 provider other than SunJSSE, that provider's SSLContext implementation should not return an SSLServerSocketFactory implementation other than the SunJSSE one when you call SSLContext.getSocketFactory. If the provider returns a non-SunJSSE implementation, you will get a runtime exception.

Customizing the Default Key and Trust Stores, Store Types, and Store Passwords

Whenever a default SSLSocketFactory or SSLServerSocketFactory is created (via a call to SSLSocketFactory.getDefault or SSLServerSocketFactory.getDefault), and this default SSLSocketFactory (or SSLServerSocketFactory) comes from the JSSE reference implementation, a default SSLContext is associated with the socket factory. (The default socket factory will come from the JSSE reference implementation unless a security property specifies a different implementation, as described in Customizing the Default SSLSocketFactory Implementation and Customizing the Default SSLServerSocketFactory Implementation.)

This default SSLContext is initialized with a KeyManager and a TrustManager. If a keystore is specified by the javax.net.ssl.keyStore system property, then the KeyManager created by the default SSLContext will be a KeyManager implementation for managing the specified keystore. (The actual implementation will be as specified in Customizing the Default Key and Trust Managers.) If no such system property is specified, then the keystore managed by the KeyManager will be a new empty keystore.

Similarly, if a truststore is specified by the javax.net.ssl.trustStore system property, then the TrustManager created by the default SSLContext will be a TrustManager implementation for managing the specified truststore. In this case, if such a property exists but the file it specifies doesn't, then no truststore is utilized. If no javax.net.ssl.trustStore property exists, then a default truststore is searched for. If a truststore named <java-home>/lib/security/jssecacerts is found, it is used. If not, then a truststore named <java-home>/lib/security/cacerts is searched for and used (if it exists). See The Installation Directory <java-home> for information as to what <java-home> refers to. Finally, if a truststore is still not found, then the truststore managed by the TrustManager will be a new empty truststore.

If system properties javax.net.ssl.keyStoreType and/or javax.net.ssl.keyStorePassword are also specified, they are treated as the default KeyManager keystore type and password, respectively. If there is no type specified, the default type is that returned by KeyStore.getDefaultType(), which is the value of the keystore.type security property, or "jks" if no such security property is specified. If there is no keystore password specified, it is assumed to be "".

Similarly, if system properties javax.net.ssl.trustStoreType and/or javax.net.ssl.trustStorePassword are also specified, they are treated as the default truststore type and password, respectively. If there is no type specified, the default type is that returned by KeyStore.getDefaultType(). If there is no truststore password specified, it is assumed to be "".

Important Note: This section describes the current JSSE 1.0.2 reference implementation behavior. The system properties described in this section are not guaranteed to continue to have the same names and types (system or security) or even to exist at all in future releases. They are also not guaranteed to be examined and used by any other JSSE 1.0.2 implementations. If they are examined by an implementation, that implementation should handle them in the same manner as the JSSE 1.0.2 reference implementation does, as described herein.

Customizing the Default Key and Trust Managers

As noted in Customizing the Default Key and Trust Stores, Store Types, and Store Passwords, whenever a default SSLSocketFactory or SSLServerSocketFactory is created, and this default SSLSocketFactory (or SSLServerSocketFactory) comes from the JSSE reference implementation, a default SSLContext is associated with the socket factory.

This default SSLContext is initialized with a KeyManager and a TrustManager. The KeyManager and/or TrustManager supplied to the default SSLContext will be a KeyManager/TrustManager implementation for managing the specified keystore/truststore, as described in the aforementioned section.

The KeyManager implementation chosen is determined by first examining the

sun.SSL.keymanager.type
security property. If such a property value is specified, a KeyManagerFactory implementation for the specified algorithm is searched for. The implementation from the first provider that supplies an implementation is used. Its getKeyManagers method is called to determine the KeyManager to supply to the default SSLContext. (Technically, getKeyManagers returns an array of KeyManagers, one KeyManager for each type of key material.) If there is no such security property value specified, the default value of "SunX509" is used to perform the search. Note: A KeyManagerFactory implementation for the "SunX509" algorithm is supplied by the SunJSSE provider. The KeyManager it specifies is a com.sun.net.ssl.X509KeyManager implementation.

Similarly, the TrustManager implementation chosen is determined by first examining the

sun.SSL.trustmanager.type
security property. If such a property value is specified, a TrustManagerFactory implementation for the specified algorithm is searched for. The implementation from the first provider that supplies an implementation is used. Its getTrustManagers method is called to determine the TrustManager to supply to the default SSLContext. (Technically, getTrustManagers returns an array of TrustManagers, one TrustManager for each type of trust material.) If there is no such security property value specified, the default value of "SunX509" is used to perform the search. Note: A TrustManagerFactory implementation for the "SunX509" algorithm is supplied by the SunJSSE provider. The TrustManager it specifies is a com.sun.net.ssl.X509TrustManager implementation.

Important Note: This section describes the current JSSE 1.0.2 reference implementation behavior. The system properties described in this section are not guaranteed to continue to have the same names and types (system or security) or even to exist at all in future releases. They are also not guaranteed to be examined and used by any other JSSE 1.0.2 implementations. If they are examined by an implementation, that implementation should handle them in the same manner as the JSSE 1.0.2 reference implementation does, as described herein.

Additional Keystore Formats

The JSSE 1.0.2 SunJSSE provider supplies an implementation of the PKCS12 java.security.KeyStore format. This format is also supported by other toolkits and applications for importing and exporting keys and certificates. For example, Netscape 4.x (versions 4.04 and later) can export client certificates and keys into a file using the ".p12" filename extension in PKCS12 format.

With the SunJSSE provider installed, you can access PKCS12 keys through the KeyStore API with a keystore type of "pkcs12" (or "PKCS12", the name is case-insensitive). In addition, you can list the installed keys using the keytool command with the -storetype option set to pkcs12. (See http://java.sun.com/j2se/1.3/docs/tooldocs/tools.html#security for information about keytool.)

The 1.0.2 release of JSSE has limitations on its implementation but can read and use PKCS12 keystore files exported by Netscape Navigator. Future releases will also support and be tested with Internet Explorer and other applications. See the README file for the release you are using for information as to its PKCS12-handling capabilities.

Troubleshooting

Installation and Configuration Problems

JSSE Package Not Found During Compilation

Problem: When compiling a program that uses the JSSE 1.0.2 packages, one of the following errors occur:

    Package com.sun.net.ssl not found in import.

    Package javax.net not found in import.

    Package javax.net.ssl not found in import.

    Package javax.security.cert not found in import.

Cause: The JSSE JAR files are not installed properly.

Solution: JSSE 1.0.2 is supplied as an extension to the Java 2 platform. Its JAR files can be installed either as "installed" extensions (recommended) or as "bundled" extensions. A JAR file is considered an "installed" extension if it is stored in a particular directory established for all installed extensions, as described in http://java.sun.com/products/jsse/install.html, and no class path modifications are needed. "Bundled" extensions may be bundled with applications or made available in a separate directory. If they are bundled with an application, be sure to specify them in the Class-Path attribute in the application's manifest file. Otherwise, be sure to set the Java CLASSPATH variable correctly so the JSSE JAR files can be found. For more information about bundled extensions, see Bundled Extensions.

Runtime Exception: SSL Service Not Available

Problem: When running a program that uses JSSE 1.0.2, an exception occurs indicating that an SSL service is not available. For example, an exception similar to one of the following occurs:

    Exception in thread "main"
        java.net.SocketException: no SSL Server Sockets

    Exception in thread "main":
        SSL implementation not available

Cause 1: The cryptographic service provider is not registered properly.

Solution 1: Before using JSSE 1.0.2, you must register the SunJSSE provider, either statically by modifying the java.security file or dynamically by calling the Security.addProvider method, as described in http://java.sun.com/products/jsse/install.html.

Cause 2: There was a problem with SSLContext initialization, for example due to a corrupted keystore. (Note: One vendor has shipped a keystore in an unknown format, and that may cause this type of error.)

Solution 2: Check initialization parameters. Ensure any keystores specified are valid (e.g., by trying to use the keytool to examine them).

Runtime Exception: untrusted cert chains

Problem: When negotiating an SSL connection, the client or server throws one of the following exceptions:

    javax.net.ssl.SSLException: untrusted server cert chain
    javax.net.ssl.SSLException: untrusted client cert chain

Cause 1: This is generally caused by the remote side sending a certificate that is unknown to the local side.

Solution 1: The best way to debug this type of problem is to turn on debugging (see Debugging Utilities) and watch as certificates are loaded and when certificates are received via the network connection. Most likely, the received certificate is unknown to the trust mechanism because the wrong trust file was loaded.

Cause 2: The system clock is not set correctly.

Solution 2: If the clock is not set correctly, the perceived time may be outside the validity period on one of the certificates, and unless the certificate can be replaced with a valid one from a truststore, the system must assume that the certificate is invalid, and therefore throw the exception.

Cause 3: Older versions of Java 2 Enterprise Edition use earlier versions of JSSE. In particular, some previous versions of J2EE shipped with JSSE 1.0, which couldn't replace received expired certificates with current ones from a truststore.

Solution 3: Be sure that the new JSSE jar files occur in the class path(s) ahead of any older J2EE jar files.

Runtime Exception: Class Definition Not Found

Problem: When running a program that uses JSSE 1.0.2, an exception occurs indicating that a JSSE class definition cannot be found. For example, an exception similar to the following occurs:

    Exception in thread "main" java.lang.NoClassDefFoundError:
        javax/net/ssl/SSLServerSocketFactory

Cause: The JSSE JAR files are not installed properly.

Solution: JSSE must be installed as an extension to the Java 2 Platform. Install the JSSE JAR files as discussed in the Solution to the JSSE Package Not Found During Compilation problem shown above.

Runtime Exception: No Cipher Suites in Common

Problem: When using Netscape Navigator or Microsoft Internet Explorer (IE) to access files on a server that only has DSA-based certificates, a runtime exception occurs indicating that there are no cipher suites in common.

Cause: By default, certificates created with keytool use DSA public keys. Navigator and IE do not use DSA public keys in their enabled cipher suites.

Solution: To interact with Navigator or IE, you should create certificates that use RSA-based keys. To do this, you need to specify the -keyalg RSA option when using keytool. For example:

    keytool -genkey -alias duke -keystore testkeys -keyalg rsa

Debugging Utilities

JSSE provides dynamic debug tracing support. This is similar to the support used for debugging access control failures in the Java 2 platform. The generic Java dynamic debug tracing support is accessed with the system property java.security.debug, while the JSSE-specific dynamic debug tracing support is accessed with the system property javax.net.debug.

Note: The debug utility is not an officially supported feature of JSSE.

To view the options of either dynamic debug utility, set the value of the appropriate system property to help. For example, to get the options of the generic Java dynamic debug utility, use the following command-line option on the java command:

    -Djava.security.debug=help

To get the options of the JSSE dynamic debug utility, use the following command-line option on the java command:

    -Djavax.net.debug=help

Note: If you specify the value help with either dynamic debug utility when running a program that does not use any classes that the utility was designed to debug, you will not get the debugging options.

Here is a complete example of how to get a list of the debug options:

    java -Djavax.net.debug=help MyApp

where MyApp is an application that uses some of the JSSE classes. MyApp will not run after the debug help information is printed, as the help code causes the application to exit.

Here are the current options:

all        turn on all debugging
ssl        turn on ssl debugging

The following can be used with ssl:
        record          enable per-record tracing
        handshake       print each handshake message
        keygen          print key generation data
        session         print session activity
        defaultctx      print default SSL initialization
        sslctx          print SSLContext tracing
        sessioncache    print session cache tracing
        keymanager      print key manager tracing
        trustmanager    print trust manager tracing

handshake debugging can be widened with:
        data            hex dump of each handshake message
        verbose         verbose handshake message printing

record debugging can be widened with:
        plaintext       hex dump of record plaintext

The javax.net.debug property value must specify either all or ssl, optionally followed by debug specifiers. You can use one or more options. You do not have to have a separator between options, although a separator such as ":" or "," helps readability. It doesn't matter what separators you use, and the ordering of the option keywords is also not important.

Examples

Code Examples

The sections below describe the following code examples:

Converting an Unsecure Socket to a Secure Socket

This section provides examples of source code that illustrate how to use JSSE to convert an unsecure socket connection to a secure socket connection. The code in this section is excerpted from the book Java 2 Network Security by Marco Pistoia, et. al.

First, "Socket Example Without SSL" shows sample code that can be used to set up communication between a client and a server using unsecure sockets. This code is then modified in "Socket Example With SSL" to use JSSE to set up secure socket communication.

Socket Example Without SSL

Server Code for Unsecure Socket Communications

When writing a Java program that acts as a server and communicates with a client using sockets, the socket communication is set up with code similar to the following:

import java.io.*;
import java.net.*;

. . .

int port = availablePortNumber;

ServerSocket s;

try {
    s = new ServerSocket(port);
    Socket c = s.accept();

    OutputStream out = c.getOutputStream();
    InputStream in = c.getInputStream();

    // Send messages to the client through
    // the OutputStream
    // Receive messages from the client
    // through the InputStream
}

catch(IOException e) {
}

Client Code for Unsecure Socket Communications

The client code to set up communication with a server using sockets is similar to the following:

import java.io.*;
import java.net.*;

. . .

int port = availablePortNumber;
String host = "hostname";

try {
    s = new Socket(host, port);

    OutputStream out = s.getOutputStream();
    InputStream in = s.getInputStream();

    // Send messages to the server through
    // the OutputStream
    // Receive messages from the server
    // through the InputStream
}

catch(IOException e) {
}

Socket Example With SSL

Server Code for Secure Socket Communications

When writing a Java program that acts as a server and communicates with a client using secure sockets, the socket communication is set up with code similar to the following. Differences between this program and the one for communication using unsecure sockets are highlighted in bold.

import java.io.*;
import javax.net.ssl.*;

. . .

int port = availablePortNumber;

SSLServerSocket s;

try {
    SSLServerSocketFactory sslSrvFact =
        (SSLServerSocketFactory)
        SSLServerSocketFactory.getDefault();
    s =(SSLServerSocket)sslSrvFact.createServerSocket(port);

    SSLSocket c = (SSLSocket)s.accept();

    OutputStream out = c.getOutputStream();
    InputStream in = c.getInputStream();

    // Send messages to the client through
    // the OutputStream
    // Receive messages from the client
    // through the InputStream
}

catch(IOException e) {
}

Client Code for Secure Socket Communications

The client code to set up communication with a server using secure sockets is similar to the following, where differences with the unsecure version are highlighted in bold:

import java.io.*;
import javax.net.ssl.*;

. . .

int port = availablePortNumber;
String host = "hostname";

try {
    SLSocketFactory sslFact =
      (SSLSocketFactory)SSLSocketFactory.getDefault();
    SSLSocket s =
      (SSLSocket)sslFact.createSocket(host, port);

    OutputStream out = s.getOutputStream();
    InputStream in = s.getInputStream();

    // Send messages to the server through
    // the OutputStream
    // Receive messages from the server
    // through the InputStream
}

catch(IOException e) {
}

Running the JSSE 1.0.2 Sample Code

The sample programs provided with the JSSE 1.0.2 download illustrate how to use JSSE to:

When using the sample code, be aware that the sample programs are designed to illustrate how to use JSSE. They are not designed to be robust applications.

Note: Setting up secure communications involves complex algorithms. The sample programs provide no feedback during the setup process. When running the programs, be patient: you may not see any output for a while. If you run the programs with the system property javax.net.debug set to all, you will see more feedback.

All of the sample code is available in the directory <ExtractDir>/samples, where <ExtractDir> is the directory where you extracted the downloaded sample files. See the README.txt file for more information on using these applications.

Sample Code Illustrating a Secure Socket Connection Between a Client and a Server

The sample programs in the directory <ExtractDir>/samples/sockets illustrate how to set up a secure socket connection between a client and a server.

When running the sample client programs, you can communicate with an existing server, such as a commercial Web server, or you can communicate with the sample server program, ClassFileServer. You can run the sample client and the sample server programs on different machines connected to the same network, or you can run them both on one machine but from different terminal windows.

All the sample SSLSocketClient* programs (and URLReader* programs described in Sample Code Illustrating HTTPS Connections) can be run with the ClassFileServer sample server program. An example of how to do this is shown in Running SSLSocketClientWithClientAuth with ClassFileServer. You can make similar changes in order to run URLReader, SSLSocketClient or SSLSocketClientWithTunneling with ClassFileServer.

On some slower machines or in environments with slow network connections, it may take a while to establish a connection. The client programs, when not communicating with ClassFileServer, attempt to access the file http://www.verisign.com/index.html. In the past, attempts to access this file would timeout. The reason is that a socket would be opened to www.verisign.com, then the JSSE would begin calculating random number information it would need for the SSL negotiations. www.verisign.com would see that there was no traffic for a while, and therefore would close the connection.

At the present time, this is no longer happening. If it begins to happen again, you could connect to other SSL servers, such as www.sun.com. An example of making such a change is shown in Running SSLSocketClientWithTunneling.

(Note: There are a couple possible workarounds to a timeout problem. One is to preseed the random number generator. The other is to specify an alternate random number generator to the SSLContext object.)

If an authentication error occurs while attempting to send messages between the client and the server (whether using a web server or ClassFileServer), it is most likely because the necessary keys are not in the truststore (trust key database). For example, the ClassFileServer uses a keystore called "testkeys" containing the private key for "duke" as needed during the SSL handshake. ("testkeys" is included in the same directory as the ClassFileServer source.) If the client cannot find a certificate for the corresponding public key of "duke" in the truststore it consults, an authentication error will occur. Be sure to use the samplecacerts truststore (which contains "duke"s public key), as described in the next section.

Configuration Requirements

When running the sample programs that create a secure socket connection between a client and a server, you will need to make the appropriate certificates file (truststore) available. For both the client and the server programs, you should use the certificates file samplecacerts, located in the directory <ExtractDir>/samples. Using this certificates file will allow the client to authenticate the server. The file contains all the common Certification Authority certificates shipped with J2SDK (in the cacerts file), plus a certificate for "duke" needed by the client to authenticate "duke" when communicating with the sample server ClassFileServer. (ClassFileServer uses a keystore containing the private key for "duke" which corresponds to the public key in samplecacerts. )

To make the samplecacerts file available to both the client and the server, you can either copy it to the file <java-home>/lib/security/jssecacerts, rename it cacerts and use it to replace the <java-home>/lib/security/cacerts file, or add the following option to the command line when running the java command for both the client and the server:

-Djavax.net.ssl.trustStore=path_to_samplecacerts_file

The password for the samplecacerts truststore is changeit. You can substitute your own certificates in the samples, using keytool.

If you use a browser, such as Netscape Navigator or Microsoft's Internet Explorer, to access the sample SSL server provided in the ClassFileServer example, a dialog box may pop up with the message that it does not recognize the certificate. This is normal because the certificate used with the sample programs is self-signed and is for testing only. You can accept the certificate for the current session. After testing the SSL server, you should exit the browser, which deletes the test certificate from the browser's namespace.

Note: The "duke" certificate in the samples directory is different from the "duke" certificate available from the security example provided on http://java.sun.com/security/signExample12/. If you have both "duke" certificates installed, the sample code will not work properly. To view the certificates available in your certificate file, use the keytool command.

Running SSLSocketClient

This example demonstrates how to create a client to use an SSLSocket to send an HTTP request and to get a response from an HTTPS server. The output of this program is the HTML source for http://www.verisign.com/index.html.

You must not be behind a firewall to run this program as shipped. If you run it from behind a firewall, you will get an UnknownHostException because JSSE can't find a path through your firewall to www.verisign.com. To create an equivalent client that can run from behind a firewall, set up proxy tunneling as illustrated in the sample program SSLSocketClientWithTunneling.

Running SSLSocketClientWithTunneling

This example illustrates how to do proxy tunneling to access a secure web server from behind a firewall. To run this program, you must set the following Java system properties to the appropriate values:

https.proxyHost = <secure proxy server hostname>

https.proxyPort = <secure proxy server port>

If you run this program and experience a time-out problem, try changing the application to access Sun instead of VeriSign. To make this change, do the following:

  1. In a text editor, open the file SSLSocketClientWithTunneling.java.

  2. Replace all occurrences of verisign with sun.

  3. Recompile SSLSocketClientWithTunneling.java.

  4. Run SSLSocketClientWithTunneling with the following command (all on one line):
    java -Dhttps.proxyHost=webproxy
        -Dhttps.proxyPort=ProxyPortNumber
        SSLSocketClientWithTunneling
    

    Note: Be sure to replace webproxy with the name of your proxy host and ProxyPortNumber with the appropriate port number.

The program will return the HTML source file from http://www.sun.com/index.html.

Running SSLSocketClientWithClientAuth

This example shows how to set up a key manager to do client authentication if required by a server. This program also assumes that the client is not outside a firewall. You can modify the program to connect from inside a firewall by following the example in SSLSocketClientWithTunneling.

To run this program, you must specify three parameters: host, port, and requested file path. To mirror the previous examples, you can run this program without client authentication by setting the host to www.verisign.com, the port to 443, and the requested file path to http://www.verisign.com/index.html. The output when using these parameters is the HTML for the Web site http://www.verisign.com/index.html.

To run SSLSocketClientWithClientAuth to do client authentication, you must access a server that requests client authentication. You can use the sample program ClassFileServer as this server. This is described in the following section.

Running SSLSocketClientWithClientAuth With ClassFileServer

You can use the sample programs SSLSocketClientWithClientAuth and ClassFileServer to set up authenticated communication, where the client and server are authenticated to each other. You can run both sample programs on different machines connected to the same network, or you can run them both on one machine but from different terminal windows or command prompt windows. To set up both the client and the server, do the following:

  1. Run the program ClassFileServer from one machine or terminal window. ClassFileServer requires the following parameters:

    • port - The port parameter can be any available unused port number, for example, you can use the number 2001.

    • docroot - This parameter indicates the directory on the server that contains the file you wish to retrieve. For example, on Solaris, you can use /home/userid/ on Windows, you can use c:\.

    • TLS - This is an optional parameter. When used, it indicates that the server is to use SSL or TLS.

    • true - This is an optional parameter. When used, client authentication is required. This parameter is only consulted if the TLS parameter is set.

    Note 1: The TLS and true parameters are optional. If you leave them off, indicating that just an ordinary (not TLS) file server should be used, without authentication, nothing happens. This is because one side (the client) is trying to negotiate with TLS, while the other (the server) isn't, so they can't communicate.

    Note 2: The server expects GET requests in the form "GET /...", where "..." is the path to the file.

  2. Run the program SSLSocketClientWithClientAuth on another machine or terminal window. SSLSocketClientWithClientAuth requires the following parameters:

    • host - This is the hostname of the machine you are using to run ClassFileServer.

    • port - This is the same port you specified for ClassFileServer.

    • requestedfilepath - This parameter indicates the path to the file you want to retrieve from the server. You must give this parameter as /filepath. Forward slashes are required in the file path because it is used as part of a GET statement, which requires forward slashes regardless of what type of operating system you are running. The statement is formed as
      "GET " + requestedfilepath + " HTTP/1.1"
      
NOTE: you can modify the other SSLClient* application's "GET" commands to connect to a local machine running ClassFileServer.

Sample Code Illustrating HTTPS Connections

There are two primary APIs for accessing secure communications through JSSE. One way is through a socket-level API which can be used for arbitrary secure communications, as illustrated by the SSLSocketClient, SSLSocketClientWithTunneling, and SSLSocketClientWithClientAuth (with and without ClassFileServer) sample programs.

A second, and often simpler way, is through the standard Java URL API. You can communicate securely with an SSL-enabled web server by using the "https" URL protocol or scheme using the java.net.URL class.

Support for "https" URL schemes is implemented in many of the common browsers, which allows access to secured communications without requiring the socket-level API provided with JSSE.

An example URL might be:

"https://www.sun.com"

The trust and key management for the "https" URL implementation is environment-specific.

The JSSE reference implementation provides an "https" URLStreamHandler implementation. In order to use this handler, you must add the handler's implementation package name to the list of packages which are searched by the Java URL class. This is configured via the java.protocol.handler.pkgs system property. See the java.net.URL class documentation for details. System properties can be set via the command line or at runtime through the java.lang.System class. Here is an example of the option you would give to the java command on the command line to indicate the JSSE reference implementation's "https" URLStreamHandler:

-Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol

The samples that you can download with JSSE 1.0.2 include two sample programs that illustrate how to create an HTTPS connection. Both of these sample programs are in the directory <ExtractDir>/samples/urls.

Running URLReader

This program illustrates using the URL class to access a secure site. The output of this program is the HTML source for http://www.verisign.com/.

To run this code, you must specify an implementation of the HTTPS protocol by setting the system property java.protocol.handler.pkgs. Set it as described above to use Sun's reference implementation.

If you are running the sample code behind a firewall, you must also set the system properties https.proxyHost and https.proxyPort. For example, to use the proxy host "webproxy" on port 8080, you can use the following options to the java command:

-Dhttps.proxyHost=webproxy

-Dhttps.proxyPort=8080

Alternatively, you can set the system properties within the source code with the java.lang.System method setProperty. For example, instead of using the command line options, you can include the following lines in your program:

System.setProperty("java.protocol.handler.pkgs",
    "com.sun.net.ssl.internal.www.protocol");

System.setProperty("https.proxyHost",
    "webproxy");

System.setProperty("https.proxyPort",
    "8080");

Note: When running on Windows 95 or Windows 98, the maximum number of characters allowed in an MS-DOS prompt may not be enough to include all the command-line options. If you encounter this problem, either create a .bat file with the entire command or add the system properties to the source code and recompile the source code.

Running URLReaderWithOptions

This program is essentially the same as URLReader, except that it allows you to optionally input any or all of the following system properties as arguments to the program when you run it:

  • java.protocol.handler.pkgs

  • https.proxyHost

  • https.proxyPort

  • https.cipherSuites

To run URLReaderWithOptions, type the following command (all on one line):

java URLReaderWithOptions
     [-h proxyhost -p proxyport]
     [-k protocolhandlerpkgs]
     [-c ciphersarray]
     myApp

Note: Multiple protocol handlers can be included in the protocolhandlerpkgs in a list with items separated by vertical bars. Multiple SSL cipher suite names can be included in the ciphersarray in a list with items separated by commas. The possible cipher suite names are the same as those returned by the call SSLSocket.getSupportedCipherSuites(). The suite names are taken from the SSL and TLS protocol specifications.

You must include the argument for java.protocol.handler.pkgs. To run the program classfile with this argument only, using Sun's reference implementation of the HTTPS protocol, type the following command (all on one line):

java URLReaderWithOptions
    -k com.sun.net.ssl.internal.www.protocol classfile

If you are running behind a firewall, you must also include arguments for the proxy host and the proxy port. Additionally, you can include a list of cipher suites to enable.

Sample Code Illustrating a Secure RMI Connection

The sample code in the directory <ExtractDir>/samples/rmi illustrates how to create a secure RMI connection. The sample code is based on the online RMI example in http://java.sun.com/products/jdk/1.2/docs/guide/rmi/installedCsfHowTo.doc.html . For more information about how to run this program, please see the sample code's README.

For more information about RMI, see the online Java RMI documentation at http://java.sun.com/products/jdk/1.2/docs/guide/rmi/. This Web page points to RMI tutorials and other information about RMI.


Appendix A: Standard Names

The protocol name parameter field passed to the getInstance method of SSLContext supports a named secure socket protocol and optionally a named purpose separated from the protocol name by a '/' character. The table below lists some common standard protocol names.
Protocol Comment
SSL Supports some version of SSL; may support other versions
SSLv2 Supports SSL version 2 or higher
SSLv3 Supports SSL version 3; may support other versions
TLS Supports some version of TLS; may support other versions
TLSv1 Supports TLS version 1; may support other versions