Beta Draft: 2017-03-27

3 Java Secure Socket Extension (JSSE) Reference Guide

The Java Secure Socket Extension (JSSE) enables secure Internet communications. It provides a framework and an implementation for a Java version of the SSL, TLS, and DTLS protocols and includes functionality for data encryption, server authentication, message integrity, and optional client authentication.

Introduction to Java Secure Socket Extension (JSSE)

The Java Secure Socket Extension (JSSE) enables secure Internet communications. It provides a framework and an implementation for a Java version of the Secure Sockets Layer (SSL), Transport Layer Security (TLS), and Datagram Transport Layer Security (DTLS) protocols and includes functionality for data encryption, server authentication, message integrity, and optional client authentication.

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’s also important to ensure that the data has not been modified, either intentionally or unintentionally, during transport. The SSL/TLS/DTLS protocols were designed to help protect the privacy and integrity of data while it is being transferred across a network.

Using JSSE, developers can provide for the secure passage of data between a client and a server running any application protocol (such as HTTP, Telnet, or FTP) over TCP/IP and protocols (such as SIP, CoAP, or SRTP) over UDP/IP. For an introduction to SSL or DTLS, see Secure Sockets Layer (SSL) Protocol Overview Datagram Transport Layer Security (DTLS).

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 that developers can integrate directly into their applications.

JSSE provides both an application programming interface (API) framework and an implementation of that API. The JSSE API supplements the core network and cryptographic services defined by the java.security and java.net packages by providing extended networking socket classes, trust managers, key managers, SSL contexts, and a socket factory framework for encapsulating socket creation behavior. Because the SSLSocket class is based on a blocking I/O model, the Java Development Kit (JDK) includes a nonblocking SSLEngine class to enable implementations to choose their own I/O methods.

The JSSE API is capable of supporting SSL (version 2.0 and 3.0), TLS (version 1.0, 1.1, and 1.2) and DTLS (version 1.0 and 1.2). These security protocols encapsulate a normal bidirectional transport mode, and the JSSE API adds transparent support for authentication, encryption, and integrity protection. The JSSE implementation shipped with the JDK supports SSL 3.0, TLS (1.0, 1.1, and 1.2) and DTLS (version 1.0 and 1.2). It doesn’t implement SSL 2.0.

JSSE is a security component of the Java SE platform, and is based on the same design principles found elsewhere in the Java Cryptography Architecture (JCA) framework. The JCA framework for cryptography-related security components allows them to have implementation independence and, whenever possible, algorithm independence. JSSE uses the cryptographic service providers defined by the JCA framework.

Other security components in the Java SE platform include the Java Authentication and Authorization Service (JAAS) and the Java Security Tools. JSSE encompasses many of the same concepts and algorithms as those in JCA but automatically applies them underneath a simple network transport API.

The JSSE API was designed to allow other SSL/TLS/DTLS protocol and Public Key Infrastructure (PKI) implementations to be plugged in seamlessly. Developers can also provide alternative logic to determine if remote hosts should be trusted or what authentication key material should be sent to a remote host.

Features and Benefits

JSSE includes the following important benefits and features:

  • Included as a standard component of the JDK
  • Extensible, provider-based architecture
  • Implemented in 100% pure Java
  • Provides API support for SSL (versions 2.0 and 3.0), TLS 1.0 and later, and an implementation of SSL 3.0 and TLS (versions 1.0, 1.1, and 1.2)
  • Provides API support for DTLS versions 1.0 and 1.2
  • Includes classes that can be instantiated to create secure channels (SSLSocket, SSLServerSocket, and SSLEngine)
  • Provides support for cipher suite negotiation, which is part of the SSL/TLS/DTLS handshaking used to initiate or verify secure communications
  • Provides support for client and server authentication, which is part of the normal SSL/TLS handshaking
  • Provides support for HTTP encapsulated in the SSL/TLS protocol, which allows access to data such as web pages using HTTPS
  • Provides server session management APIs to manage memory-resident SSL sessions
  • Provides support for server name indication extension, which facilitates secure connections to virtual servers.
  • Provides support for certificate status request extension (OCSP stapling), which saves client certificate validation round-trips and resources.
  • Provides support for endpoint identification during handshaking, which prevents man-in-the-middle attacks.
  • Provides support for cryptographic algorithm constraints, which controls the secure strength of the transport fine granulated.
  • Provides support for several cryptographic algorithms commonly used in cipher suites, including those listed in Table 3-1

Table 3-1 Cryptographic Functionality Available in JSSE

Cryptographic Algorithm 1 Cryptographic Process Key Lengths (Bits)3
Rivest-Shamir-Adleman (RSA) Authentication and key exchange 512 and larger
Rivest Cipher 4 (RC4) Bulk encryption 128

128 (40 effective)

Data Encryption Standard (DES) Bulk encryption 64 (56 effective)

64 (40 effective)

Elliptic curve Diffie-Hellman (ECDH) Key exchange 160 through 512
Elliptic Curve Diffie-Hellman Exchange (ECDHE) Key exchange 160 through 512
Elliptic Curve Digital Signature Algorithm (ECDSA) Authentication 160 through 512
Message Digest Algorithm (MD5) Hash algorithm 128
Secure Hash Algorithm 1 (SHA1) Hash algorithm 160
Secure Hash Algorithm 224 (SHA224) Hash algorithm 224
Secure Hash Algorithm 256 (SHA256) Hash algorithm 256
Secure Hash Algorithm 384 (SHA384) Hash algorithm 384
Secure Hash Algorithm 512 (SHA512) Hash algorithm 512
Triple DES (3DES) Bulk encryption 192 (112 effective)
Advanced Encryption Standard (AES) Bulk encryption 256 2

128

Diffie-Hellman (DH) Key agreement 512, 768, 1024, 2048
Digital Signature Algorithm (DSA) Authentication 1024, 2048

Footnote 1 The SunJSSE implementation uses the Java Cryptography Architecture (JCA) for all its cryptographic algorithms.

Footnote 2 Cipher suites that use AES_256 require installation of the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files. See Java SE Download Page.

Footnote 3 A JSSE provider may disable or deactivate weak algorithms and weak keys.

JSSE Standard API

The JSSE standard API, available in the javax.net and javax.net.ssl packages, provides:

  • Secure sockets and server sockets.
  • A nonblocking engine for producing and consuming streams of SSL/TLS/DTLS data (SSLEngine).
  • Factories for creating sockets, server sockets, SSL sockets, and SSL server sockets. By using socket factories, you can encapsulate socket creation and configuration behavior.
  • A class representing a secure socket context that acts as a factory for secure socket factories and engines.
  • Key and trust manager interfaces (including X.509-specific key and trust managers), and factories that can be used for creating them.
  • A class for secure HTTP URL connections (HTTPS).

SunJSSE Provider

Oracle's implementation of Java SE includes a JSSE provider named SunJSSE, which comes preinstalled and preregistered with the JCA. This provider supplies the following cryptographic services:

  • An implementation of the SSL 3.0, TLS (versions 1.0, 1.1, and 1.2), and DTLS (versions 1.0 and 1.2) security protocols.
  • An implementation of the most common SSL, TLS, and DTLS cipher suites. This implementation encompasses a combination of authentication, key agreement, encryption, and integrity protection.
  • An implementation of an X.509-based key manager that chooses appropriate authentication keys from a standard JCA keystore.
  • An implementation of an X.509-based trust manager that implements rules for certificate chain path validation.
  • An implementation of PKCS12 as JCA keystore type "pkcs12". Storing trust anchors in PKCS12 is not supported. Users should store trust anchors in the Java keystore (JKS) format and save private keys in PKCS12 format.

See The SunJSSE Provider.

Related Documentation

The following list contains links to online documentation and names of books about related subjects:

Terms and Definitions

Alphabetic listing contains commonly used cryptography terms and their definitions.

authentication

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

certificate

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

cipher suite

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

cryptographic hash function

An algorithm that is used to produce a relatively small fixed-size string of bits (called a hash) from an arbitrary block of data. A cryptographic hash function is similar to a checksum and has three primary characteristics: it’s 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 doesn’t require a cryptographic key.

Cryptographic Service Provider

Sometimes referred to simply as providers for short, the Java Cryptography Architecture (JCA) defines it as a package (or set of packages) that implements one or more engine classes for specific cryptographic algorithms. An engine class defines a cryptographic service in an abstract fashion without a concrete implementation.

Datagram Transport Layer Security (DTLS) Protocol

A protocol that manages client and server authentication, data integrity, and encrypted communication between the client and server based on an unreliable transport channel such as UDP.

decryption

See encryption/decryption.

digital signature

A 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/decryption

Encryption is the process of using a complex algorithm to convert an original message (cleartext) to an encoded message (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.

endpoint identification

An IPv4 or IPv6 address used to identify an endpoint on the network.

Endpoint identification procedures are handled during SSL/TLS handshake.

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.

java-home

Variable placeholder used throughout this document to refer to the directory where the Java Development Kit (JDK) is installed.

key agreement

A method by which two parties cooperate to establish a common key. Each side generates some data, which is exchanged. These two pieces of data are then combined to generate a key. Only those holding the proper private initialization data can obtain the final key. Diffie-Hellman (DH) is the most common example of a key agreement algorithm.

key exchange

A method by which keys are exchanged. One side generates a private key and encrypts it using the peer's public key (typically RSA). The data is transmitted to the peer, who decrypts the key using the corresponding private key.

key manager/trust manager

Key managers and trust managers use keystores for their key material. A key manager manages a keystore and supplies public keys to others as needed (for example, for use in authenticating the user to others). A trust manager decides who to trust based on information in the truststore it manages.

keystore/truststore

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

Generally speaking, keystore information can be grouped into two 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 contains only a public key in addition to the entity's identity. Thus, a trusted certificate entry can’t be used where a private key is required, such as in a javax.net.ssl.KeyManager. In the JDK implementation of JKS, a keystore may contain both key entries and trusted certificate entries.

A truststore is a keystore that is used when making decisions about what to trust. If you receive data from an entity that you already trust, and if you can verify that the entity is the one that 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 trusts that entity. By either generating a key pair or by importing a certificate, the user gives trust to that entry. Any entry in the truststore 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 CA certificates. The former contains private information, whereas the latter does not. Using two files instead of a single keystore file provides a cleaner separation of the logical distinction between your own certificates (and corresponding private keys) and others' certificates. To provide more protection for your private keys, store them in a keystore with restricted access, and provide the trusted certificates in a more publicly accessible keystore if needed.

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

A cryptographic system that uses an encryption algorithm in which two keys are produced. One key is made public, whereas 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

A protocol that 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

A cryptographic system that 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.

Secure Sockets Layer (SSL) Protocol

A protocol that manages client and server authentication, data integrity, and encrypted communication between the client and server.

session

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

Transport Layer Security (TLS) Protocol

A protocol that manages client and server authentication, data integrity, and encrypted communication between the client and server based on a reliable transport channel such as TCP.

TLS is based on the SSL 3.0 protocol.

trust manager

See key manager/trust manager.

truststore

See keystore/truststore.

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 table 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.

Table 3-2 TCP/IP Protocol Stack with SSL

TCP/IP Layer Protocol
Application Layer HTTP, NNTP, Telnet, FTP, and so on
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 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. TLS 1.1 was released in April 2006, and TLS 1.2 in August 2008.

Why Use SSL?

SSL allows two communicating parties to ensure the identity of the other party in a process called authentication. After the parties are authenticated, SSL provides an encrypted connection between the two parties for secure message transmission.

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

  • You can’t always be sure that the entity with whom you are communicating is really who you think it is.
  • Network data can be intercepted, so it’s possible that it can be read by an unauthorized third party, sometimes known as an attacker.
  • An attacker who intercepts data may be able to modify it before sending it on to the receiver.

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. After 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 isn’t 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 negotiated cipher suites between the two entities.

An e-commerce transaction is an obvious example of when to use SSL. 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 website 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.

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

Although SSL provides authentication, privacy, and data integrity, it doesn’t provide nonrepudiation services. Nonrepudiation means that an entity that sends a message can’t later deny sending it. When the digital equivalent of a signature is associated with a message, the communication can later be proved. SSL alone does not provide nonrepudiation.

How SSL Works

One of the reasons that SSL is effective is that it uses several different cryptographic processes. SSL uses public-key cryptography to provide authentication, and secret-key cryptography with hash functions to provide for privacy and data integrity. Before you can understand SSL, it’s 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 (cleartext) to an encoded message (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.

Safely transmitting a key between two communicating parties is not a trivial matter. A public key certificate enables a party to safely transmit its public key, while ensuring the receiver of the authenticity of the public key. See Public Key Certificates.

The descriptions of the cryptographic processes in Secret-Key Cryptography and Public- Key Cryptography follow conventions widely used by the security community: the two communicating parties are labeled with the names Alice and Bob. The unauthorized third party, also known as the attacker, is named 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, then 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 won’t know that the message came from Charlie, not Alice.

After 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 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.

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, then 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. Although 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.

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 because both communicating parties must 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 because 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 the following fields:

Issuer
The CA that issued the certificate. If a user trusts the CA that issued the certificate, and if the certificate is valid, then the user can trust the certificate.
Period of validity
A certificate has an expiration date. This date should be checked when verifying the validity of a certificate.
Subject
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 nonrepudiation.

If Bob only accepts Alice's public key as valid when she sends it in a public key certificate, then Bob won’t 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 more certificates are in the chain, then 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 whereas 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 U.S. National Institute of Standards and Technology (NIST).

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.

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, then the resulting hash is known as an HMAC.

If Alice wants to be sure that Charlie does not tamper with her message to Bob, then 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 that 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.

The SSL Handshake

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 SSL handshake includes the following stages:

  1. 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 the public key exchange algorithms or key agreement 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.

  2. Authenticating the server's identity (optional)

    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, then 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 because the server's private key is required for this decryption.

  3. Agreeing on encryption mechanisms

    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 the handshake, 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 the handshake 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.

Figure 3-1 The SSL/TLS Handshake

Description of Figure 3-1 follows
Description of "Figure 3-1 The SSL/TLS Handshake"
Each of the SSL messages is described below the figure.

The SSL messages are sent in the following order:

  1. Client hello: The client sends the server information including the highest version of SSL that it supports and a list of the cipher suites that 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. (Optional) 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. (Optional)Certificate request: If the server must authenticate the client, then it sends the client a certificate request. In Internet applications, this message is rarely sent.
  5. (Optional)Server key exchange: The server sends the client a server key exchange message if the public key information from the Certificate is not sufficient for key exchange. For example, in cipher suites based on Diffie-Hellman (DH), this message contains the server's DH public key.
  6. Server hello done: The server tells the client that it is finished with its initial negotiation messages.
  7. (Optional)Certificate: If the server Certificate request from the client, the client sends its certificate chain, just as the server did previously.

    Note:

    Only a few Internet server applications ask for a certificate from the client.
  8. (Optional)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. For cipher suites based on DH, this message contains the client's DH public key.
  9. (Optional)Certificate verify: This message is sent by the client when the client presents a certificate as previously explained. 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 during the client hello and server hello, and using the secret key that the client sent to the server during the client key exchange. The handshake can be renegotiated at this time. See Handshaking Again (Renegotiation).
  15. Close Messages:At the end of the connection, each side sends a close_notify message to inform the peer that the connection is closed.

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

Handshaking Again (Renegotiation)

Once the initial handshake is finished and application data is flowing, either side is free to initiate a new handshake at any time. An application might like to use a stronger cipher suite for especially critical operations, or a server application might want to require client authentication.

Regardless of the reason, the new handshake takes place over the existing encrypted session, and application data and handshake messages are interleaved until a new session is established.

Your application can initiate a new handshake by using one of the following methods:

  • SSLSocket.startHandshake()
  • SSLEngine.beginHandshake()

Note:

a protocol flaw related to renegotiation was found in 2009. The protocol and the Java SE implementation have both been fixed. See Transport Layer Security (TLS) Renegotiation Issue.

Cipher Suite Choice and Remote Entity Verification

The choice of cipher suite directly affects the type of security that the connection enjoys.

The SSL/TLS Protocols define a specific series of steps to ensure a protected connection. However, the choice of cipher suite directly affects the type of security that the connection enjoys. For example, if an anonymous cipher suite is selected, then the application has no way to verify the remote peer's identity. If a suite with no encryption is selected, then the privacy of the data cannot be protected. Additionally, the SSL/TLS protocols do not specify that the credentials received must match those that peer might be expected to send. If the connection were somehow redirected to a rogue peer, but the rogue's credentials were acceptable based on the current trust material, then the connection would be considered valid.

When using raw SSLSocket and SSLEngine classes, you should always check the peer's credentials before sending any data. The SSLSocket and SSLEngine classes do not automatically verify that the host name in a URL matches the host name in the peer's credentials. An application could be exploited with URL spoofing if the host name is not verified. Since JDK 7, endpoint identification/verification procedures can be handled during SSL/TLS handshaking. See SSLParameters.getEndpointIdentificationAlgorithm.

Protocols such as HTTPS (HTTP Over TLS) do require host name verification. Since JDK 7, the HTTPS endpoint identification is enforced during handshaking for HttpsURLConnection by default. See SSLParameters.getEndpointIdentificationAlgorithm. Alternatively, applications can use The HostnameVerifier Interface to override the default HTTPS host name rules. See HttpsURLConnection Class.

Datagram Transport Layer Security (DTLS)

Datagram Transport Layer Security (DTLS) protocol is designed to construct “TLS over datagram” traffic that doesn't require or provide reliable or in-order delivery of data. Java Secure Socket Extension (JSSE) API and the SunJSSE security provider support the DTLS protocol.

Because the TLS requires a transparent reliable transport channel such as TCP it can’t be used to secure unreliable datagram traffic. DTLS is a datagram-compatible variant of TLS.

The JSSE API now supports DTLS Version 1.0 and DTLS Version 1.2 along with Secure Socket Layer (SSL) and Transport Layer Security (TLS) protocols.

The javax.net.ssl.SSLEngine programming model is used by the JSSE API for DTLS.

Topics

See also:

Creating an SSLEngine Object
Creating an SSLEngine Client / Server object for a DTLS connection.
Generating and Processing DTLS Data
Using wrap() and unwrap() methods to process DTLS datagram packets.
Shutting Down a SSL/TLS/DTLS Connection
Shutting down a DTLS connection.
Server Name Indication (SNI) Extension
Using the SNI extension for DTLS client or server connection
How the JCA Might be Used in a DTLS Implementation
Using Java Cryptography Architecture (JCA) classes in a DTLS implementation.
Configuring the Maximum and Minimum Packet Size
Setting the maximum expected network packet size in bytes for a DTLS connection.

The DTLS Handshake

Before application data can be sent or received, the DTLS protocol requires a handshake to establish cryptographic parameters. This handshake requires a series of back-and-forth messages between the client and server by the SSLEngine object.

The DTLS Handshake

DTLS handshake requires all messages be received properly. Thus, in unreliable datagram traffic, missing or delayed packets must be retransmitted. Since javax.net.ssl.SSLEngine is not responsible for I/O operations, it is up to the application to provide timers and signal the SSLEngine when a retransmission is needed. It is important that you implement a timer and retransmission strategy for your application. See Handling Retransmissions in DTLS Connections.

The DTLS handshake includes the following stages:

  1. Negotiating the cipher suite

    The DTLS 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 the public key exchange algorithms or key agreement 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.

    A cookie is exchanged between the client and server along with the cipher suite in order to prevent denial of service attacks (DoS).

  2. (Optional)Authenticating the server's identity (optional)

    The authentication step is optional, but in the example of an e-commerce transaction over the web, the client chooses 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, then 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 because the server's private key is required for this decryption.

  3. Agreeing on encryption mechanisms

    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 the handshake, 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 the handshake to encrypt the secure data and the HMAC. The client and server can now communicate securely using their encrypted and hashed data.

The DTLS Handshake Message Exchange

In a DTLS handshake, series of back-and-forth messages are exchanged between the client and server by the SSLEngine object.

Figure 3-2 shows the sequence of messages that are exchanged in the DTLS handshake. Messages that are sent only in certain situations are noted as optional. Each message is described following the figure.

To know more about DTLS handshake messages, see DTLS Version 1.0 and DTLS Version 1.2.

The following handshake messages are exchanged between the client and server during DTLS handshake:

  1. ClientHello:

    The client sends the server information including the highest version of DTLS that it supports and a list of the cipher suites that it supports. The cipher suite information includes cryptographic algorithms and key sizes.

  2. HelloVerifyRequest:

    The server responds to the ClientHello message from the client with a cookie.

  3. ClientHello:

    The client sends a second ClientHello message to the server with highest version of DTLS that it supports and a list of the cipher suites that it supports. The cookie received in the HelloVerifyRequest is sent back to the server.

  4. ServerHello:

    The server chooses the highest version of DTLS and the best cipher suite that both the client and server support and sends this information to the client.

  5. (Optional)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

  6. (Optional)CertificateRequest:

    If the server must authenticate the client, then it sends the client a certificate request. In Internet applications, this message is rarely sent.

  7. (Optional)ServerKeyExchange:

    The server sends the client a server key exchange message if the public key information from the Certificate is not sufficient for key exchange. For example, in cipher suites based on Diffie-Hellman (DH), this message contains the server's DH public key.

  8. ServerHelloDone:

    The server tells the client that it is finished with its initial negotiation messages.

  9. (Optional)Certificate:

    If the server Certificate request from the client, the client sends its certificate chain, just as the server did previously.

    Note:

    Only a few Internet server applications ask for a certificate from the client.
  10. ClientKeyExchange:

    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. For cipher suites based on DH, this message contains the client's DH public key.

  11. (Optional)CertificateVerify:

    This message is sent by the client when the client presents a certificate as previously explained. 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.

  12. ChangeCipherSpec:

    The client sends a message telling the server that subsequent data will be protected under the newly negotiated CipherSpec and keys and the data is encrypted

  13. Finished:

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

  14. ChangeCipherSpec:

    The server sends a message telling the client that subsequent data will be protected under the newly negotiated CipherSpec and keys and the data is encrypted.

  15. Finished:

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

Handshaking Again (Renegotiation)

Once the initial handshake is finished and application data is flowing, either side is free to initiate a new handshake at any time. An application might like to use a stronger cipher suite for especially critical operations, or a server application might want to require client authentication.

Regardless of the reason, the new handshake takes place over the existing encrypted session, and application data and handshake messages are interleaved until a new session is established.

Your application can initiate a new handshake by using the SSLEngine.beginHandshake() method.

Note:

A protocol flaw related to renegotiation was found in 2009. The protocol and the Java SE implementation have both been fixed. See Transport Layer Security (TLS) Renegotiation Issue.

Example 3-1 Sample Code for Handling DTLS handshake Status and Overall Status

void handshake(SSLEngine engine, DatagramSocket socket,
            SocketAddress peerAddr) throws Exception {

  boolean endLoops = false;

// private static int MAX_HANDSHAKE_LOOPS = 60;  
 
  int loops = MAX_HANDSHAKE_LOOPS;

  engine.beginHandshake();

  while (!endLoops && (serverException == null) && (clientException == null)) {

    if (--loops < 0) {
                throw new RuntimeException("Too many loops to produce handshake packets");
            }

    SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();

    if (hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ||
        hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) {

      ByteBuffer iNet;
      ByteBuffer iApp;

     if (hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {

     // receive ClientHello request and other SSL/TLS/DTLS records

     byte[] buf = new byte[1024];

     DatagramPacket packet = new DatagramPacket(buf, buf.length);

     try {

        socket.receive(packet);

     } catch (SocketTimeoutException ste) {
 
      // retransmit the packet if timeout

        List <Datagrampacket> packets =
                    onReceiveTimeout(engine, peerAddr);
        for (DatagramPacket p : packets) {

           socket.send(p);

        }

              continue;

    }
      iNet = ByteBuffer.wrap(buf, 0, packet.getLength());

      iApp = ByteBuffer.allocate(1024);

    } else {

      iNet = ByteBuffer.allocate(0);

      iApp = ByteBuffer.allocate(1024);

    }

    SSLEngineResult r = engine.unwrap(iNet, iApp);

    SSLEngineResult.Status rs = r.getStatus();

    hs = r.getHandshakeStatus();

    if (rs == SSLEngineResult.Status.BUFFER_OVERFLOW) {

    // the client maximum fragment size config does not work?

    throw new Exception("Buffer overflow: " +

          "incorrect client maximum fragment size");

    } else if (rs == SSLEngineResult.Status.BUFFER_UNDERFLOW) {

      // bad packet, or the client maximum fragment size

      // config does not work?

      if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {

       throw new Exception("Buffer underflow: " +

             "incorrect client maximum fragment size");

      } // otherwise, ignore this packet

    } else if (rs == SSLEngineResult.Status.CLOSED) {

                    endLoops = true;

    }   // otherwise, SSLEngineResult.Status.OK:


      if (rs != SSLEngineResult.Status.OK) {

          continue;

      }

    } else if (hs == SSLEngineResult.HandshakeStatus.NEED_WRAP) {

         List <DatagramPacket> packets =

             // Call a function to produce handshake packets
             produceHandshakePackets(engine, peerAddr);

         for (DatagramPacket p : packets) {

             socket.send(p);

        }

    } else if (hs == SSLEngineResult.HandshakeStatus.NEED_TASK) {

                runDelegatedTasks(engine);

    } else if (hs == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {

                // OK, time to do application data exchange.

                endLoops = true;

    } else if (hs == SSLEngineResult.HandshakeStatus.FINISHED) {

                endLoops = true;

    }

  }

   SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();

   if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {

            throw new Exception("Not ready for application data yet");

        }

}

Handling Retransmissions in DTLS Connections

In SSL/TLS over a reliable connection, data is guaranteed to arrive in the proper order, and retransmission is unnecessary. However, for DTLS, which often works over unreliable media, missing or delayed handshake messages must be retransmitted.

The SSLEngine operates in a completely transport-neutral manner, and all I/O is to be done by the application layer. Because SSLEngine isn’t responsible for I/O, the application to provide timers, and signal the SSLEngine when a retransmission is needed. In networking components, routines manage read timeouts effectively. The application layer must determine the right timeout value and when to trigger the timeout event. During handshaking, if an SSLEngine object is in HandshakeStatus.NEED_UNWRAP state, a call to SSLEngine.wrap() means that the previous packets were lost, and must be retransmitted. For such cases, the DTLS implementation of SSLEngine takes the responsibility to wrap the previous necessary handshaking messages again if necessary.

Note:

In a DTLS engine, only handshake messages must be properly exchanged. Application data can handle packet loss without the need for timers.

Handling Retransmission in an Application

SSLEngine.unwrap() and SSLEngine.wrap() can be used together to handle retransmission in an application.

Figure 3-3 shows a typical scenario for handling DTLS handshaking retransmission:

Figure 3-3 DTLS Handshake Retransmission State Flow

Description of Figure 3-3 follows
Description of "Figure 3-3 DTLS Handshake Retransmission State Flow"
  1. Create and initialize an instance of DTLS SSLEngine.
    See Creating an SSLEngine Object. The DTLS handshake process begins. See The DTLS Handshake.
  2. If the handshake status is HandshakeStatus.NEED_UNWRAP, wait for data from network.
  3. If the timer times out, it indicates that the previous delivered handshake messages may have been lost.

    Note:

    In DTLS handshaking retransmission, the determined handshake status isn’t necessarily HandshakeStatus.NEED_WRAP for the call to SSLEngine.wrap().
  4. Call SSLEngine.wrap().
  5. The wrapped packets are delivered.

Handling a Buffered Handshake Message in an Application

Datagram transport does’nt require or provide reliable or in-order delivery of data. Handshake messages may be lost or need to be reordered. In the DTLS implementation, a handshake message may need to be buffered for future handling before all previous messages have been received.

The DTLS implementation of SSLEngine takes the responsibility to reorder handshake messages. Handshake message buffering and reordering are transparent to applications.

However, applications must manage HandshakeStatus.NEED_UNWRAP_AGAIN status. This status indicates that for the next SSLEngine.unwrap()operation no additional data from the remote side is required.

Figure 3-4 shows a typical scenario for using the HandshakeStatus.NEED_UNWRAP_AGAIN.

Figure 3-4 State Machine of DTLS Buffered Handshake with NEED_UNWRAP_AGAIN

Description of Figure 3-4 follows
Description of "Figure 3-4 State Machine of DTLS Buffered Handshake with NEED_UNWRAP_AGAIN"
  1. Create and initialize an instance of DTLS SSLEngine.
    See Creating an SSLEngine Object. The DTLS handshake process begins, see The DTLS Handshake.
  2. Optional: If the handshake status is HandshakeStatus.NEED_UNWRAP, wait for data from network.
  3. Optional: If you received the network data, call SSLEngine.unwrap().
  4. Determine the handshake status for next processing. The handshake status can be HandshakeStatus.NEED_UNWRAP_AGAIN, HandshakeStatus.NEED_UNWRAP, or HandshakeStatus.NEED_WRAP.
    • If the handshake status is HandshakeStatus.NEED_UNWRAP_AGAIN, call SSLEngine.unwrap().

    Note:

    For HandshakeStatus.NEED_UNWRAP_AGAIN status, no additional data from the network is required for an SSLEngine.unwrap() operation.
  5. Determine the handshake status for further processing. The handshake status can be HandshakeStatus.NEED_UNWRAP_AGAIN, HandshakeStatus.NEED_UNWRAP, or HandshakeStatus.NEED_WRAP.

TLS Application Layer Protocol Negotiation

Negotiate an application protocol for a TLS connection with Application Layer Protocol Negotiation (APLN).

Why Would You Use ALPN?

Application-layer protocols can be encapsulated in the TLS protocol, as in the case of HTTP/2.

ALPN enables you to negotiate the application layer protocol before the connection has been negotiated, and it does this without adding network round-trips between the client and the server. In the case of HTTP/2 the protocol must be established before the connection is negotiated, as client and server need to know what version of HTTP to use before they start communicating. Without ALPN it would not be possible to have application protocols HTTP/1 and HTTP/2 on the same port.

How Does ALPN Work?

With ALPN, the client sends a list of supported application protocols to the server as part of the TLS ClientHello message. The server chooses a protocol and sends the selected protocol to the client as part of the TLS ServerHello message. The application protocol negotiation can thus be accomplished within the TLS handshake, without adding network round-trips, and allows the server to associate a different certificate with each application protocol, if desired.

ALPN is described in the RFC Application Layer Protocol Negotiation (ALPN) Extension.

Unlike many other TLS extensions, this extension does not establish properties of the session, only of the connection. That's why you'll find the negotiated values in the SSLSocket/SSLEngine, not the SSLSession. When session resumption or session tickets are used (see TLS Session Resumption without Server-Side State), the previous contents of this extension are irrelevant, and only the values in the new handshake messages are considered.

TLS Handshake and Application Layer Protocol Negotiation

Both client and server in a TLS connection use the ALPN extension to determine the application protocol.

The client uses the ALPN extension at the beginning of the TLS handshake to send a list of supported application protocols to the server as part of the ClientHello. The server reads the list of supported application protocols in the ClientHello, and determines which of the supported protocols it prefers. It then sends a ServerHello message back to the client. The message may contain either:
  • The name of the protocol that has been chosen

  • The information that no protocol has been chosen

Client Side Protocol Negotiation

For the client, use the SSLParameters.setApplicationProtocols(String[]) method, followed by the setSSLParameters method of either SSLSocket or SSLEngine to set up the application protocols to be sent to the server.

See Setting up ALPN on the Client.

Server Side Protocol Negotiation

For the server, use either of these two mechanisms.
  • Default Negotiation

    For default negotiation on the server, use the SSLParameters.setApplicationProtocols(String[]) method followed by the setSSLParameters method of either SSLSocket or SSLEngine to set up a list of application protocols that are acceptable to the server. The server reads the client's application protocol list and matches this list against its own list, choosing the protocol that appears earliest in the server list and that also appears somewhere in the client list. For example, if the client's list is "two", "three", and the server's list is "three", "two", "one", the ALPN value chosen will be "three".

    See Setting up Default ALPN on the Server.

  • Custom Negotiation

    If you do not want to use the server’s default negotiation, use the setHandshakeApplicationProtocolSelector method of SSLEngine or SSLSocket to register a BiFunction (lambda) callback that can examine the handshake state so far and then make your selection based on the client’s list of application protocols and any other relevant information. For example, you may consider using the cipher suite suggested, or the Server Name Indication (SNI) or any other data you require in making the choice. If custom negotiation is used, the values set by the setApplicationProtocols method (default negotiation) will be ignored.

    See Setting up Custom ALPN on the Server

    Note that it is also possible to read the client’s list plus any other necessary information in the plaintext that precedes the handshake without using the setHandshakeApplicationProtocolSelector method.

If either of these approaches is unsuccessful and does not produce a negotiated ALPN value, the server may:

  • Decide there is no mutually acceptable protocol and take appropriate action, for example throwing an exception or terminating the connection

  • Ignore the ALPN values transmitted by the client

Setting up ALPN on the Client

Set the Application Layer Protocol Negotiation (ALPN) values supported by the client. During the handshake with the server, the server will read the client’s list of application protocols and will determine which is most suitable.

  1. Set up a String array with the ALPN values.
    The order is unimportant on the client side (though it does matter on the server side.
  2. Obtain an SSLParameters object from the SSLSocket object or the SSLEngine object.
  3. Set the ALPN values on the SSLParameters object.
  4. Populate either the SSLSocket or the SSLEngine object with the SSLParameters object.
  5. After handshaking completes on both client and server, check the result of the negotiation by calling the getApplicationProtocol method on the SSLSocket object or the SSLEngine object. See The SSL Handshake for further details on handshaking.
    It is also possible to check the results of the negotiation during handshaking. See Determining Negotiated ALPN Value during Handshaking.

Example 3-2 Sample Code for Setting and Getting ALPN Values in a Java Client

For example, here are the steps to set ALPN values of "three" and "two", on the client. In this example, assume an SSLSocket object, and that the reference to the SSLSocket object is sslSocket.

To run the code the property javax.net.ssl.trustStore must be set to a valid root certificate. (This can be done on the command line).

import java.io.*; import java.util.*;
import javax.net.ssl.*; 
public class SSLClient {
    public static void main(String[] args) throws Exception {

        // Code for creating a client side SSLSocket
        SSLSocketFactory sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault();
        SSLSocket sslSocket = (SSLSocket) sslsf.createSocket("localhost", 9999);

        // Get an SSLParameters object from the SSLSocket
        SSLParameters sslp = sslSocket.getSSLParameters();

        // Populate SSLParameters with the ALPN values
        // Here on the client side the order doesn't matter
        String[] clientAPs ={"three","two"};
        sslp.setApplicationProtocols(clientAPs);

        // Populate the SSLSocket object with the ALPN values
        sslSocket.setSSLParameters(sslp);


        sslSocket.startHandshake();

        // After the handshake, get the application protocol that has been negotiated
        // The server has "one" as first preference, but this client doesn't support that value
        // The server's second value is "two", and, as this value is supported by this client, "two" will be chosen.
        String ap = sslSocket.getApplicationProtocol();
        System.out.println("Application Protocol client side: \"" + ap + "\"");

        // Continue with the client
        InputStream sslIS = sslSocket.getInputStream();
        OutputStream sslOS = sslSocket.getOutputStream();
        sslOS.write(280);
        sslOS.flush();
        sslIS.read();
        sslSocket.close();
    }
}
When this code is run and sends a ClientHello to a Java server that has set the ALPN values one, two, three, the output will be:
Application Protocol client side: two

Setting up Default ALPN on the Server

Use the default ALPN mechanism to determine a suitable application protocol by setting ALPN values on the server.

To use the default mechanism for ALPN on the server, set the ALPN values by populating an SSLParameters object with the ALPN values you wish to set, and using this SSLParameters object to populate either the SSLSocket object or the SSLEngine object with these parameters. The first value of the ALPN values set on the server that matches any of the ALPN values contained in the ClientHello will be chosen and returned to the client as part of the ServerHello.
  1. Set up a String array with the ALPN values.
    These should be in preferred order (on the client side the order is unimportant).
  2. Obtain an SSLParameters object from the SSLSocket object or the SSLEngine object.
  3. Set the ALPN values on the SSLParameters object.
  4. Populate either the SSLEngine or the SSLSocket object with the SSLParameters object.
  5. After handshaking completes on both client and server, check the result of the negotiation by calling the getApplicationProtocol method on either the SSLSocket object or the SSLEngine object. See The SSL Handshake for further details on handshaking.
    It is also possible to check the results of the negotiation during handshaking. See Determining Negotiated ALPN Value during Handshaking.

Example 3-3 Sample Code for Default ALPN Value Negotiation on the Server

Here is the code for a Java server that uses the default approach for protocol negotiation. To run the code the property javax.net.ssl.keyStore must be set to a valid certificate. (This can be done on the command line, see Creating a Keystore to Use with JSSE).

import java.util.*; 
import javax.net.ssl.*; 
public class SSLServer {
    public static void main(String[] args) throws Exception {

        // Code for creating a server side SSLSocket
        SSLServerSocketFactory sslssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
        SSLServerSocket sslServerSocket = (SSLServerSocket) sslssf.createServerSocket(9999);
        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();

                        
                        // Get an SSLParameters object from the SSLSocket
        SSLParameters sslp = sslSocket.getSSLParameters();
        // Populate SSLParameters with the ALPN values
        // As this is server side, put them in the array in order of preference
        String[] serverAPs ={"one","two","three"};
        sslp.setApplicationProtocols(serverAPs);

        // If necessary at any time, get the ALPN values set on the SSLParameters object with:
        // String serverAPs = sslp.setApplicationProtocols();

        // Populate the SSLSocket object with the ALPN values
        sslSocket.setSSLParameters(sslp);

        sslSocket.startHandshake();

        // After the handshake, get the application protocol that has been negotiated

        // This server has "one" as first preference, but the client doesn't support that value
        // The second value is "two", and, as that is supported by the client, "two" will be chosen.
        String ap = sslSocket.getApplicationProtocol();
        System.out.println("Application Protocol server side: \"" + ap + "\"");

                        // Continue with the work of the server
        InputStream sslIS = sslSocket.getInputStream();
        OutputStream sslOS = sslSocket.getOutputStream();
        sslIS.read();
        sslOS.write(85);
        sslOS.flush();
        sslSocket.close();
      }
}
When this code is run and a Java client sends a ClientHello with ALPN values three, two, the output is:
Application Protocol server side: two

Setting up Custom ALPN on the Server

Use the custom ALPN mechanism to determine a suitable application protocol by setting up a callback method.

Set the ALPN value to return to the client using the setHandshakeApplicationProtocolSelector method of SSLSocket or SSLEngine a BiFunction (lambda) callback to examine the handshake state and determine an appropriate application protocol.
  1. Call the setHandshakeApplicationProtocolSelector method of SSLSocket or SSLEngine and pass in a BiFunction object that supports the following parameters:
    • SSLSocket The function's first argument allows the current SSLSocket to be inspected, including the handshake session and configuration settings

    • List<String> The function's second argument lists the application protocol names advertised by the TLS peer

    • String The function's result is the application protocol name to return to the client

    The function's result is an application protocol name, or null to indicate that none of the advertised names are acceptable. If the return value is an empty String then application protocol indications will not be used. If the return value is null (no value chosen) or is a value that was not advertised by the peer, the underlying protocol will determine what action to take. (For example, ALPN will send a "no_application_protocol" alert and terminate the connection.)
  2. Code the callback method. It is this method that will examine the handshake status and make the determination regarding the application protocol to use.
  3. After handshaking completes on both client and server, you can check the result of the negotiation by calling the getApplicationProtocol method on either the SSLSocket object or the SSLEngine object. See The SSL Handshake for further details on handshaking.

Example 3-4 Sample Code for Custom ALPN Value Negotiation on the Server

Here is the code for a Java server that uses the custom approach for protocol negotiation. To run the code the property javax.net.ssl.keyStore must be set to a valid certificate. (This can be done on the command line, see Creating a Keystore to Use with JSSE).

import java.util.*; 
import javax.net.ssl.*; 
public class SSLServer {
    public static void main(String[] args) throws Exception {

        // Code for creating a server side SSLSocket
        SSLServerSocketFactory sslssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
        SSLServerSocket sslServerSocket = (SSLServerSocket) sslssf.createServerSocket(9999);
        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();

        // Code to set up a callback function
                         sslSocket.setHandshakeApplicationProtocolSelector(
            // current SSLSocket to be inspected and client AP values passed into the function
            (serverSocket, clientProtocols) -> {
            SSLSession session = serverSocket.getHandshakeSession();
            // callback function called with current SSLSocket and client AP values
            // plus any other useful information to help determine appropriate
            // application protocol. Here the protocol and cipher suite are also
            // passed to the callback function.
            return chooseApplicationProtocol(
               serverSocket,
               clientProtocols,
               session.getProtocol(),
               session.getCipherSuite());
         });

        sslSocket.startHandshake();

        // After the handshake, get the application protocol that has been returned from
        // the callback method.

        String ap = sslSocket.getApplicationProtocol();
        System.out.println("Application Protocol server side: \"" + ap + "\"");

                        // Continue with the work of the server
        InputStream sslIS = sslSocket.getInputStream();
        OutputStream sslOS = sslSocket.getOutputStream();
        sslIS.read();
        sslOS.write(85);
        sslOS.flush();
        sslSocket.close();
    }

    // The callback method. Note how the parameters match the call within 
    // the setHandshakeApplicationProtocolSelector method above.
    public static String chooseApplicationProtocol(
       SSLSocket serverSocket ,
       List<String> clientProtocols,
                  String protocol,
                  String cipherSuite ) {
       // For example, check the cipher suite and return an application protocol
       // value based on that.
                  if (cipherSuite.equals("<--a_particular_cipher_suite-->")) { 
                           return "three";
                  }
                  else return "";
    } 
}

When this code is run and the cipher suite matches the one you specify in the conditional, the value "three" will be returned. Otherwise an empty string will be returned.

Determining Negotiated ALPN Value during Handshaking

To determine the ALPN value that has been negotiated during the handshaking, create a custom KeyManager or TrustManager, and include in this custom class a call togetHandshakeApplicationProtocol .

The steps and examples here illustrate how to call the getHandshakeApplicationProtocol method from within a custom X509ExtendedKeyManager you create and register as the KeyManager object.
  1. Create a new custom KeyManager that extends the class X509ExtendedKeyManager.
    X509ExtendedKeyManager is an abstract class so your new class needs to implement all the abstract methods in this class. The easiest way to do this is to wrap an existing KeyManager and call its methods for each of the methods you need to implement.
    1. Create a new X509ExtendedKeyManager class that extends X509ExtendedKeyManager.
      public class MyX509ExtendedKeyManager extends X509ExtendedKeyManager {
      }
      
    2. Create a variable to hold the KeyManager that is being wrapped by this class.
      X509ExtendedKeyManager akm;
      
    3. Create a constructor that declares(?) an X509ExtendedKeyManager type and stores it on akm.
      public MyX509ExtendedKeyManager(X509ExtendedKeyManager akm,) {
          this.akm = akm;
      }
      
    4. Implement each of the abstract methods, by calling the same method on the wrapped X509ExtendedKeyManager and returning the value obtained. For example, implement the getClientAliases method:
      @Override
      public String[] getClientAliases(String keyType, Principal[] issuers) {
      return keyManager.getClientAliases(keyType, issuers);
      }
      
    5. Any methods that have access to a Socket object can now process a call to the getHandshakeApplicationProtocol method. (But you need to cast the Socket to an SSLSocket). For example, modify the chooseServerAlias method to call the getHandshakeApplicationProtocol method.
      @Override
      public String chooseServerAlias(String[] keyType, Principal[] issuers, Socket socket) {
          String currentALPNvalue = ((SSLSocket) socket).getHandshakeApplicationProtocol();
          System.out.println("In chooseClientAlias, currentALPNvalue is: " + currentALPNvalue);
          return keyManager.chooseClientAlias(keyType, issuers, socket);
      }
      
  2. Set up the Java client or Java server to use the custom KeyManager (MyX509ExtendedKeyManager in the example used here) instead of the default one.
    To do this, after creating a KeyManagerFactory, get the current X509ExtendedKeyManager, then use it to instantiate the new custom X509ExtendedKeyManager(called MyX509ExtendedKeyManager in the example used here).
    1. Get the current KeyManagers from the KeyManagerFactory. If your previous code in the class sets up an X509ExtendedKeyManager as the KeyManager, it will be returned in index zero of the KeyManager kms array.
      KeyManager[] kms = kmf.getKeyManagers();
      if (!(kms[0] instanceof X509ExtendedKeyManager)) {
          throw new Exception("kms[0] not X509ExtendedKeyManager");
      }
      
    2. Create a new KeyManager based on your custom X509ExtendedKeyManager. You pass in the current KeyManager to its constructor, and replace the existing KeyManager in kms with the new one.
      kms = new KeyManager[] { new MyX509ExtendedKeyManager(
              (X509ExtendedKeyManager) kms[0], expectedAP) };
      
    3. Get an array of TrustManager objects. You’ll need the current TrustManager to create the SSLContext.
      TrustManager[] tms = tmf.getTrustManagers();
      
    4. Create an SSLContext that uses the custom X509ExtendedKeyManager.
      SSLContext ctx = SSLContext.getInstance("TLS");
      ctx.init(kms, tms, null);
      
With this custom X509ExtendedKeyManager in place, starting handshaking will cause the getHandshakeApplicationProtocol method to be called during handshaking. In this example, it will be called when the chooseServerAlias method is called.

Example 3-5 Sample Code for Extending an X509ExtendedKeyManager

This example shows the entire code for a custom KeyManager that extends X509ExtendedKeyManager. The chooseServerAlias method calls the getHandshakeApplicationProtocol on the SSLSocket object.

import java.net.Socket;
import java.security.*;
import javax.net.ssl.*; 
public class MyX509ExtendedKeyManager extends X509ExtendedKeyManager {
    X509ExtendedKeyManager akm;
    public MyX509ExtendedKeyManager(X509ExtendedKeyManager akm) {
        this.akm = akm;
    }
    @Override
    public String[] getClientAliases(String keyType, Principal[] issuers) {
        return akm.getClientAliases(keyType, issuers);
    }
    @Override     public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
        return akm.chooseClientAlias(keyType, issuers, socket);
    }
    @Override
    public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
        
        // This method has access to a Socket, so it is possible to call the
        // getHandshakeApplicationProtocol method here. Note the cast from 
        // a Socket to an SSLSocket
        String nap = ((SSLSocket) socket).getHandshakeApplicationProtocol();
        System.out.println("In chooseServerAlias, nap is: " + nap);
        return akm.chooseServerAlias(keyType, issuers, socket);
    }
    @Override     public String[] getServerAliases(String keyType, Principal[] issuers) {
        return akm.getServerAliases(keyType, issuers);
    }
    @Override
    public X509Certificate[] getCertificateChain(String alias) {
        return akm.getCertificateChain(alias);
    }
    @Override
    public PrivateKey getPrivateKey(String alias) {
        return akm.getPrivateKey(alias);
    }
}
When this code is registered as the KeyManager for a Java server and a Java client sends a ClientHello with ALPN values, the output will be:
In chooseServerAlias, nap is: <negotiated value>

Example 3-6 Sample Code for Using a Custom KeyManager in a Java Server

This example show a simple Java server that uses a custom KeyManager. Note the differences between the code here and the sample code given in the Getting and Setting ALPN values. topic that uses the default KeyManager .

import java.io.*;
import java.util.*;
import javax.net.ssl.*;
import java.security.KeyStore;
public class SSLServerHandshake {
    public static void main(String[] args) throws Exception {
        SSLContext ctx = SSLContext.getInstance("TLS");

        // You need to explicity create a KeyManager so you cannot simply specify
        // the certificate on the command line

        // Keystores
        KeyStore keyKS = KeyStore.getInstance("JKS");
        keyKS.load(new FileInputStream("serverCert.p12"), "password".toCharArray());

        // Generate KeyManager
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(keyKS, "password".toCharArray());
        KeyManager[] kms = kmf.getKeyManagers();

              // Code to substitute MyX509ExtendedKeyManager
        if (!(kms[0] instanceof X509ExtendedKeyManager)) {
            throw new Exception("kms[0] not X509ExtendedKeyManager");
        }

        // Create a new KeyManager array and set the first index of the array to 
        // an instance of custom X509ExtendedKeyManager (MyX509ExtendedKeyManager).
        // Notice how creating this object is done by passing in the existing default 
        // X509ExtendedKeyManager 
        kms = new KeyManager[] { new MyX509ExtendedKeyManager((X509ExtendedKeyManager) kms[0]) };

        // Initialize SSLContext using the new KeyManager
        ctx.init(kms, null, null);

        // Instead of using SSLServerSocketFactory.getDefault(), get a SSLServerSocketFactory
        // based on the SSLContext
        SSLServerSocketFactory sslssf = ctx.getServerSocketFactory();
        SSLServerSocket sslServerSocket = (SSLServerSocket) sslssf.createServerSocket(9999);
        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
        SSLParameters sslp = sslSocket.getSSLParameters();
        String[] serverAPs ={"one","two","three"};
        sslp.setApplicationProtocols(serverAPs);
        sslSocket.setSSLParameters(sslp);

        sslSocket.startHandshake();

        String ap = sslSocket.getApplicationProtocol();
        System.out.println("Application Protocol server side: \"" + ap + "\"");

        InputStream sslIS = sslSocket.getInputStream();
        OutputStream sslOS = sslSocket.getOutputStream();
        sslIS.read();
        sslOS.write(85);
        sslOS.flush();

        sslSocket.close();
    }
}
When this code is run and a Java client sends a ClientHello with ALPN values three, two, the output will be:
Application Protocol server side: two

ALPN Related Classes and Methods

These classes and methods are used when working with Application Layer Protocol Negotiation (ALPN).

Classes and Methods to Use

SSLEngine and SSLSocket contain the same ALPN related methods and they have the same functionality.

Class Method Purpose
SSLParameters public String[] getApplicationProtocols(); Client-side and server-side: use the method to return a String array containing each protocol set.
SSLParameters public void setApplicationProtocols([] protocols); Client-side: use the method to set the protocols that can be chosen by the server.

Server-side: use the method to set the protocols that the server can use. The String array should contain the protocols in rank order.

SSLEngine

SSLSocket

public String getApplicationProtocol(); Client-side and server-side: use the method after protocol negotiation has taken place to return a String containing the protocol that has been chosen for the connection.
SSLEngine

SSLSocket

public String getHandshakeApplicationProtocol(); Client-side and server-side: use the method during handshaking to return a String containing the protocol that has been chosen for the connection. If this method is called before or after handshaking, it will return null. See Determining Negotiated ALPN Value during Handshaking for instructions on how to call this method.
SSLEngine

SSLSocket

public void setHandshakeApplicationProtocolSelector(BiFunction,String> selector) Server-side: use the method to register a callback function. The application protocol value can then be set in the callback based on any information available, for example the protocol or cipher suite. See Setting up Custom ALPN on the Server for instructions on how to use this method.

JSSE Classes and Interfaces

In the JSSE API, the endpoint classes of the connection are SSLSocket and SSLEngine.

In the following figure, the major classes used to create SSLSocket and SSLEngine are laid out in a logical ordering.

To communicate securely, both sides of the connection must be SSL-enabled. The text following the diagram, explains the contents of the illustration:

Figure 3-5 JSSE Classes Used to Create SSLSocket and SSLEngine

Description of Figure 3-5 follows
Description of "Figure 3-5 JSSE Classes Used to Create SSLSocket and SSLEngine"

An SSLSocket is created either by an SSLSocketFactory or by an SSLServerSocket accepting an inbound connection. In turn, an SSLServerSocket is created by an SSLServerSocketFactory. Both SSLSocketFactory and SSLServerSocketFactory objects are created by an SSLContext. An SSLEngine is created directly by an SSLContext, and relies on the application to handle all I/O.

Note:

When using raw SSLSocket or SSLEngine classes, you should always check the peer's credentials before sending any data. Since JDK 7, endpoint identification/verification procedures can be handled during SSL/TLS handshaking. See SSLParameters.getEndpointIdentificationAlgorithm.

For example, the host name in a URL matches the host name in the peer's credentials. An application could be exploited with URL spoofing if the host name is not verified.

Core Classes and Interfaces

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

The SSLContext Class

The SSLContext class is used to create the SSLSocketFactory or SSLServerSocketFactory class.

There are two ways to obtain and initialize an SSLContext:

  • The simplest way is to call the static SSLContext.getDefault method on either the SSLSocketFactory or SSLServerSocketFactory class. This method creates a default SSLContext with a default KeyManager, TrustManager, and SecureRandom (a secure random number generator). A default KeyManagerFactory and TrustManagerFactory are used to create the KeyManager and TrustManager, respectively. The key material used is found in the default keystore and truststore, as determined by system properties described in Customizing the Default Keystores and Truststores, Store Types, and Store Passwords.
  • The approach that gives the caller the most control over the behavior of the created context is to call the static method SSLContext.getDefault on the SSLContext class, and then initialize the context by calling the instance's proper init() method. One variant of the init() method takes three arguments: an array of KeyManager objects, an array of TrustManager objects, and a SecureRandom object. The KeyManager and TrustManager objects are created by either implementing the appropriate interfaces or using the KeyManagerFactory and TrustManagerFactory classes to generate implementations. The KeyManagerFactory and TrustManagerFactory can then each be initialized with key material contained in the KeyStore passed as an argument to the init() method of the TrustManagerFactory or KeyManagerFactory classes. Finally, the getTrustManagers() method (in TrustManagerFactory) and getKeyManagers() method (in KeyManagerFactory) can be called to obtain the array of trust managers or key managers, one for each type of trust or key material.

Once an SSL connection is established, an SSLSession is created which contains various information, such as identities established and cipher suite used. The SSLSession is then used to describe an ongoing relationship and state information between two entities. Each SSL connection involves one session at a time, but that session may be used on many connections between those entities, simultaneously or sequentially.

SocketFactory and ServerSocketFactory Classes

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

Subclasses of javax.net.SocketFactory class are factories that create particular subclasses of sockets and thus provide a general framework for the addition of public socket-level functionality. For example, see SSLSocketFactory and SSLServerSocketFactory Classes.

Socket factories are a simple way to capture a variety of policies related to the sockets being constructed, producing such sockets in a way that does not require special configuration of the code that 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. 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

The javax.net.ssl.SSLSocketFactory class acts as a factory for creating secure sockets. This class is an abstract subclass of javax.net.SocketFactory.

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

The following ways can be used to obtain an SSLSocketFactory:

  • Get the default factory by calling the SSLSocketFactory.getDefault() static method.
  • Receive a factory as an API parameter. That is, code that must create sockets but does not 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, javax.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 that 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 that 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 implementation as a provider-based configuration class.

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 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.

To prevent peer spoofing, you should always verify the credentials presented to an SSLSocket. See Cipher Suite Choice and Remote Entity Verification.

Note:

Due to the complexity of the SSL and TLS protocols, it is difficult to predict whether incoming bytes on a connection are handshake or application data, and how that data might affect the current connection state (even causing the process to block). In the Oracle JSSE implementation, the available() method on the object obtained by SSLSocket.getInputStream() returns a count of the number of application data bytes successfully decrypted from the SSL connection but not yet read by the application.

Obtaining an SSLSocket

Instances of SSLSocket can be obtained in one of the following ways:

  • An SSLSocket can be created by an instance of SSLSocketFactory via one of the several createSocket() methods of that class.
  • An SSLSocket can be created through the accept() method of the SSLServerSocket class.

SSLEngine Class

The use of SSL/TLS/DTLS is becoming increasingly popular. It is being used in a wide variety of applications across a wide range of computing platforms and devices. Along with this popularity come demands to use SSL/TLS/DTLS with different I/O and threading models to satisfy the applications' performance, scalability, footprint, and other requirements.

There are demands to use SSL/TLS/DTLS with blocking and nonblocking I/O channels, asynchronous I/O, arbitrary input and output streams, and byte buffers. There are demands to use it in highly scalable, performance-critical environments, requiring management of thousands of network connections.

Abstraction of the I/O transport mechanism using the SSLEngine class in Java SE allows applications to use the SSL/TLS/DTLS protocols in a transport-independent way, and thus frees application developers to choose transport and computing models that best meet their needs. Not only does this abstraction allow applications to use nonblocking I/O channels and other I/O models, it also accommodates different threading models. This effectively leaves the I/O and threading decisions up to the application developer. Because of this flexibility, the application developer must manage I/O and threading (complex topics in and of themselves), as well as have some understanding of the SSL/TLS/DTLS protocols. The abstraction is therefore an advanced API: beginners should use SSLSocket.

Users of other Java programming language APIs such as the Java Generic Security Services (Java GSS-API) and the Java Simple Authentication Security Layer (Java SASL) will notice similarities in that the application is also responsible for transporting data.

The core class is javax.net.ssl.SSLEngine. It encapsulates an SSL/TLS/DTLS state machine and operates on inbound and outbound byte buffers supplied by the user of the SSLEngine class. The following diagram illustrates the flow of data from the application, through SSLEngine, to the transport mechanism, and back.

Figure 3-6 Flow of data through SSLEngine

Description of Figure 3-6 follows
Description of "Figure 3-6 Flow of data through SSLEngine"

An instance of the SSLEngine class can be in one of the following states:

Creation
The SSLEngine has been created and initialized, but has not yet been used. During this phase, an application may set any SSLEngine-specific settings (enabled cipher suites, whether the SSLEngine should handshake in client or server mode, and so on). Once handshaking has begun, though, any new settings (except client/server mode) will be used for the next handshake.
Initial handshaking
The initial handshake is a procedure by which the two peers exchange communication parameters until an SSLSession is established. Application data can’t be sent during this phase.
Application data
After the communication parameters have been established and the handshake is complete, application data can flow through the SSLEngine. Outbound application messages are encrypted and integrity protected, and inbound messages reverse the process.
Rehandshaking
Either side can request a renegotiation of the session at any time during the Application Data phase. New handshaking data can be intermixed among the application data. Before starting the rehandshake phase, the application may reset the SSL/TLS/DTLS communication parameters such as the list of enabled ciphersuites and whether to use client authentication, but can not change between client/server modes. As before, after handshaking has begun, any new SSLEngine configuration settings won’t be used until the next handshake.
Closure
When the connection is no longer needed, the application should close the SSLEngine and should send/receive any remaining messages to the peer before closing the underlying transport mechanism. Once an engine is closed, it is not reusable: a new SSLEngine must be created.
Creating an SSLEngine Object

Use the SSLContext.createSSLEngine() method to create an SSLEngine object.

Before you create an SSLEngine object, you must configure the engine to act as a client or a server, and set other configuration parameters, such as which cipher suites to use and whether client authentication is required. The SSLContext.createSSLEngine method creates an javax.net.ssl.SSLEngine object.

Note:

The server name and port number are not used for communicating with the server (all transport is the responsibility of the application). They are hints to the JSSE provider to use for SSL session caching, and for Kerberos-based cipher suite implementations to determine which server credentials should be obtained.

The SSLContext object is used to specify the DTLS protocol type. To know more about supported DTLS protocol types, see Oracle Providers.

The following examples illustrates how to create an SSLEngine object for different protocols and keystores:

Note:

The server name and port number are not used for communicating with the server (all transport is the responsibility of the application). They are hints to the JSSE provider to use for DTLS session caching, and for Kerberos-based cipher suite implementations to determine which server credentials should be obtained.

Example 3-7 Sample Code for Creating a SSLEngine Client for DTLS with PKCS12 as Keystore

The following sample code creates a SSLEngine client for DTLS that uses PKCS12 as keystore:

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

// Create and initialize the SSLContext with key material
char[] passphrase = "passphrase".toCharArray();

// First initialize the key and trust material
KeyStore ksKeys = KeyStore.getInstance("PKCS12");
ksKeys.load(new FileInputStream("testKeys"), passphrase);
KeyStore ksTrust = KeyStore.getInstance("PKCS12");
ksTrust.load(new FileInputStream("testTrust"), passphrase);

// KeyManagers decide which key material to use
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ksKeys, passphrase);

// TrustManagers decide whether to allow connections
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ksTrust);

//Get an instance of SSLContext for DTLS protocols
sslContext = SSLContext.getInstance("DTLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

// Create the engine
SSLEngine engine = sslContext.createSSLengine(hostname, port);

// Use engine as client
engine.setUseClientMode(true);

Example 3-8 Sample Code for Creating a SSLEngine Server for DTLS with PKCS12 as Keystore

The following sample code creates a SSLEngine server for DTLS that uses PKCS12 as keystore:
import javax.net.ssl.*;
import java.security.*;

// Create and initialize the SSLContext with key material
char[] passphrase = "passphrase".toCharArray();

// First initialize the key and trust material
KeyStore ksKeys = KeyStore.getInstance("PKCS12");
ksKeys.load(new FileInputStream("testKeys"), passphrase);
KeyStore ksTrust = KeyStore.getInstance("PKCS12");
ksTrust.load(new FileInputStream("testTrust"), passphrase);

// KeyManagers decide which key material to use
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ksKeys, passphrase);

// TrustManagers decide whether to allow connections
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ksTrust);

//Get an SSLContext for DTLS Protocol without authentication
sslContext = SSLContext.getInstance("DTLS");
sslContext.init(null, null, null);

// Create the engine
SSLEngine engine = sslContext.createSSLengine(hostname, port);

// Use the engine as server
engine.setUseClientMode(false);
engine.setNeedClientAuth(true);

Example 3-9 Sample Code for Creating a SSLEngine Client for TLS with JKS as Keystore

The following sample code creates a SSLEngine client for TLS that uses JKS as keystore:
import javax.net.ssl.*;
import java.security.*;

// Create and initialize the SSLContext with key material
char[] passphrase = "passphrase".toCharArray();

// First initialize the key and trust material
KeyStore ksKeys = KeyStore.getInstance("JKS");
ksKeys.load(new FileInputStream("testKeys"), passphrase);
KeyStore ksTrust = KeyStore.getInstance("JKS");
ksTrust.load(new FileInputStream("testTrust"), passphrase);

// KeyManagers decide which key material to use
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ksKeys, passphrase);

// TrustManagers decide whether to allow connections
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ksTrust);

//Get an instance of SSLContext for SSL/TLS protocols
sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

// Create the engine
SSLEngine engine = sslContext.createSSLengine(hostname, port);

// Use as client
engine.setUseClientMode(true);
Generating and Processing SSL/TLS Data

The two main SSLEngine methods are wrap() and unwrap(). They are responsible for generating and consuming network data respectively. Depending on the state of the SSLEngine object, this data might be handshake or application data.

Each SSLEngine object has several phases during its lifetime. Before application data can be sent or received, the SSL/TLS protocol requires a handshake to establish cryptographic parameters. This handshake requires a series of back-and-forth steps by the SSLEngine object. The SSL Handshake section provides more details about the handshake itself.

During the initial handshaking, the wrap() and unwrap() methods generate and consume handshake data, and the application is responsible for transporting the data. The wrap() and unwrap() method sequence is repeated until the handshake is finished. Each SSLEngine operation generates an instance of the SSLEngineResult class, in which the SSLEngineResult.HandshakeStatus field is used to determine what operation must occur next to move the handshake along.

The following table shows the sequence of methods called during a typical handshake, with corresponding messages and statuses.

Table 3-3 Typical Handshake

Client SSL/TLS Message HandshakeStatus
wrap() ClientHello NEED_UNWRAP
unwrap() ServerHello/Cert/ServerHelloDone NEED_WRAP
wrap() ClientKeyExchange NEED_WRAP
wrap() ChangeCipherSpec NEED_WRAP
wrap() Finished NEED_UNWRAP
unwrap() ChangeCipherSpec NEED_UNWRAP
unwrap() Finished FINISHED

When handshaking is complete, further calls to wrap() will attempt to consume application data and package it for transport. The unwrap() method will attempt the opposite.

To send data to the peer, the application first supplies the data that it wants to send via SSLEngine.wrap() to obtain the corresponding SSL/TLS encoded data. The application then sends the encoded data to the peer using its chosen transport mechanism. When the application receives the SSL/TLS encoded data from the peer via the transport mechanism, it supplies this data to the SSLEngine via SSLEngine.unwrap() to obtain the plaintext data sent by the peer.

Note:

The example can be made more robust and scalable by using a Selector with the nonblocking SocketChannel.

Example 3-10 Sample Code for Creating a Nonblocking SocketChannel

In the following example the SSL application is using a non-blocking SocketChannel to communicate with its peer. The following sample code sends the string "hello" to its peer, by encoding it using the SSLEngine created in Example 3-9 . It uses information from the SSLSession to determine how large to make the byte buffers. Each iteration of this code may or may not produce plaintext data, depending on whether handshaking is in progress.
// Create a nonblocking socket channel
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress(hostname, port));

// Complete connection
while (!socketChannel.finishedConnect()) {
    // do something until connect completed
}

//Create byte buffers for holding application and encoded data

SSLSession session = engine.getSession();
ByteBuffer myAppData = ByteBuffer.allocate(session.getApplicationBufferSize());
ByteBuffer myNetData = ByteBuffer.allocate(session.getPacketBufferSize());
ByteBuffer peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize());
ByteBuffer peerNetData = ByteBuffer.allocate(session.getPacketBufferSize());

// Do initial handshake
doHandshake(socketChannel, engine, myNetData, peerNetData);

myAppData.put("hello".getBytes());
myAppData.flip();

while (myAppData.hasRemaining()) {
    // Generate SSL/TLS/DTLS encoded data (handshake or application data)
    SSLEngineResult res = engine.wrap(myAppData, myNetData);

    // Process status of call
    if (res.getStatus() == SSLEngineResult.Status.OK) {
        myAppData.compact();

        // Send SSL/TLS/DTLS encoded data to peer
        while(myNetData.hasRemaining()) {
            int num = socketChannel.write(myNetData);
            if (num == 0) {
                // no bytes written; try again later
            }
        }
    }

    // Handle other status:  BUFFER_OVERFLOW, CLOSED
    ...
}

Example 3-11 Sample Code for Reading Data From Nonblocking SocketChannel

The following sample code illustrates how to read data from the nonblocking SocketChannel and extract the plaintext data from it by using SSLEngine created in Example 3-9:
// Read SSL/TLS/DTLS encoded data from peer
int num = socketChannel.read(peerNetData);
if (num == -1) {
    // The channel has reached end-of-stream
} else if (num == 0) {
    // No bytes read; try again ...
} else {
    // Process incoming data
    peerNetData.flip();
    res = engine.unwrap(peerNetData, peerAppData);

    if (res.getStatus() == SSLEngineResult.Status.OK) {
        peerNetData.compact();

        if (peerAppData.hasRemaining()) {
            // Use peerAppData
        }
    }
    // Handle other status:  BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED
    ...
}

Difference between SSLEngine.wrap() for SSL/TLS engine and DTLS engine

The SSLEngine.wrap() for DTLS is different from SSL/TLS as follows:
  • SSL/TLS implementation of SSLEngine, the output buffer of SSLEngine.wrap() might contain one or more TLS records.

  • DTLS implementation of SSLEngine, the output buffer of SSLEngine.wrap() will contain at most one record, so that every DTLS record can be marshaled and delivered to the datagram layer individually.

Note:

Each record produced by SSLEngine.wrap() should comply to the maximum packet size limitation as specified by SSLParameters.getMaximumPacketSize().
 
Generating and Processing DTLS Data

The two main SSLEngine methods for generating and consuming network data are wrap() and unwrap(). Depending on the state of the SSLEngine object, the network data might be handshake or application data.

Using wrap() and unwrap() Methods During DTLS Handshake

During the initial handshake, the SSLEngine.wrap and SSLEngine.unwrap methods generate and consume handshake data, and the application is responsible for transporting the data.

The wrap() and unwrap() method sequence is repeated until the handshake is finished. Each SSLEngine operation generates an instance of the SSLEngineResult class, in which the SSLEngineResult.HandshakeStatus field is used to determine what operation must occur next to move the handshake along. See The DTLS Handshake.

The following diagram shows the state machine during a typical DTLS handshake, with corresponding messages and statuses:

Figure 3-7 State Machine during DTLS Handshake

Description of Figure 3-7 follows
Description of "Figure 3-7 State Machine during DTLS Handshake"

Using wrap() and unwrap() Methods for DTLS Application Data

When handshaking is complete, further calls to wrap() will attempt to consume application data and package it for transport. The unwrap() method will attempt the opposite.

To send data to the peer, the application first supplies the data that it wants to send via SSLEngine.wrap to obtain the corresponding DTLS encoded data. The application then sends the encoded data to the peer using its chosen transport mechanism.

When the application receives the DTLS encoded data from the peer via the transport mechanism, it supplies this data to the SSLEngine via SSLEngine.unwrap to obtain the plaintext data sent by the peer.

Note:

The example can be made more robust and scalable by using a Selector with the nonblocking SocketChannel.

Example 3-12 Sample Code for Creating a Non-Blocking Socket Channel

In the following example the application is using a non-blocking SocketChannel to communicate with its peer. The following sample code sends the string "hello" to its peer, by encoding it using the SSLEngine created in Example 3-7. It uses information from the SSLSession to determine how large to make the byte buffers. Each iteration of this code may or may not produce plaintext data, depending on whether handshaking is in progress.
// Create a nonblocking socket channel
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress(hostname, port));

// Complete connection
while (!socketChannel.finishedConnect()) {
    // do something until connect completed
}

//Create byte buffers for holding application and encoded data

SSLSession session = engine.getSession();
ByteBuffer myAppData = ByteBuffer.allocate(session.getApplicationBufferSize());
ByteBuffer myNetData = ByteBuffer.allocate(session.getPacketBufferSize());
ByteBuffer peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize());
ByteBuffer peerNetData = ByteBuffer.allocate(session.getPacketBufferSize());

// Do initial handshake
doHandshake(socketChannel, engine, myNetData, peerNetData);

myAppData.put("hello".getBytes());
myAppData.flip();

while (myAppData.hasRemaining()) {
    // Generate SSL/TLS/DTLS encoded data (handshake or application data)
    SSLEngineResult res = engine.wrap(myAppData, myNetData);

    // Process status of call
    if (res.getStatus() == SSLEngineResult.Status.OK) {
        myAppData.compact();

        // Send SSL/TLS/DTLS encoded data to peer
        while(myNetData.hasRemaining()) {
            int num = socketChannel.write(myNetData);
            if (num == 0) {
                // no bytes written; try again later
            }
        }
    }

    // Handle other status:  BUFFER_OVERFLOW, CLOSED
    ...
}

Example 3-13 Sample Code to Read Data from a Non-Blocking Socket Channel

The following sample code illustrates how to read data from the nonblocking SocketChannel and extract the plaintext data from it by using SSLEngine created in Example 3-7:
// Read SSL/TLS/DTLS encoded data from peer
int num = socketChannel.read(peerNetData);
if (num == -1) {
    // The channel has reached end-of-stream
} else if (num == 0) {
    // No bytes read; try again ...
} else {
    // Process incoming data
    peerNetData.flip();
    res = engine.unwrap(peerNetData, peerAppData);

    if (res.getStatus() == SSLEngineResult.Status.OK) {
        peerNetData.compact();

        if (peerAppData.hasRemaining()) {
            // Use peerAppData
        }
    }
    // Handle other status:  BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED
    ...
}

Difference between SSLEngine.wrap() for SSL/TLS engine and DTLS engine

The SSLEngine.wrap() for DTLS is different from SSL/TLS as follows:
  • In the SSL/TLS implementation of SSLEngine, the output buffer of SSLEngine.wrap() contains one or more TLS records (due to the TLSv1 BEAST Cipher Block Chaining vulnerability).

  • In the DTLS implementation of SSLEngine, the output buffer of SSLEngine.wrap() contains at most one record, so that every DTLS record can be marshaled and delivered to the datagram layer individually.

Note:

Each record produced by SSLEngine.wrap() should comply to the maximum packet size limitation as specified by SSLParameters.getMaximumPacketSize().
 
Understanding SSLEngine Operation Statuses

The status of the SSLEngine is represented by SSLEngineResult.Status.

To indicate the status of the engine and what actions the application should take, the SSLEngine.wrap() and SSLEngine.unwrap() methods return an SSLEngineResult instance, as shown in Example 3-10. This SSLEngineResult object contains two pieces of status information: the overall status of the engine and the handshaking status.

The possible overall statuses are represented by the SSLEngineResult.Status enum. The following statuses are available:

CLOSED
The operation closed the SSLEngine or the operation could not be completed because it was already closed.
OK
There was no error.
BUFFER_UNDERFLOW
The input buffer had insufficient data, indicating that the application must obtain more data from the peer (for example, by reading more data from the network).
BUFFER_OVERFLOW
The output buffer had insufficient space to hold the result, indicating that the application must clear or enlarge the destination buffer.

Example 3-14 illustrates how to handle the BUFFER_UNDERFLOW and BUFFER_OVERFLOW statuses of the SSLEngine.unwrap() method. It uses SSLSession.getApplicationBufferSize() and SSLSession.getPacketBufferSize() to determine how large to make the byte buffers.

The possible handshaking statuses are represented by the SSLEngineResult.HandshakeStatus enum. They represent whether handshaking has completed, whether the caller must obtain more handshaking data from the peer or send more handshaking data to the peer, and so on. The following handshake status are available:

FINISHED
The SSLEngine has just finished handshaking.
NEED_TASK
The SSLEngine needs the results of one (or more) delegated tasks before handshaking can continue.
NEED_UNWRAP
The SSLEngine needs to receive data from the remote side before handshaking can continue.
NEED_UNWRAP_AGAIN
The SSLEngine needs to unwrap before handshaking can can continue.
NEED_WRAP
The SSLEngine must send data to the remote side before handshaking can continue, so SSLEngine.wrap() should be called.
NOT_HANDSHAKING
The SSLEngine is not currently handshaking.

Having two statuses per result allows the SSLEngine to indicate that the application must take two actions: one in response to the handshaking and one representing the overall status of the wrap() and unwrap() methods. For example, the engine might, as the result of a single SSLEngine.unwrap() call, return SSLEngineResult.Status.OK to indicate that the input data was processed successfully and SSLEngineResult.HandshakeStatus.NEED_UNWRAP to indicate that the application should obtain more SSL/TLS/DTLS encoded data from the peer and supply it to SSLEngine.unwrap() again so that handshaking can continue. As you can see, the previous examples were greatly simplified; they would need to be expanded significantly to properly handle all of these statuses.

Example 3-16 and Example 3-15 illustrate how to process handshaking data by checking handshaking status and the overall status of the wrap() and unwrap() methods.

Example 3-14 Sample Code for Handling BUFFER_UNDERFLOW and BUFFER_OVERFLOW

The following code sample illustrates how to handle BUFFER_UNDERFLOW and BUFFER_OVERFLOW status:

SSLEngineResult res = engine.unwrap(peerNetData, peerAppData);
switch (res.getStatus()) {

case BUFFER_OVERFLOW:
    // Maybe need to enlarge the peer application data buffer.
    if (engine.getSession().getApplicationBufferSize() > peerAppData.capacity()) {
        // enlarge the peer application data buffer
    } else {
        // compact or clear the buffer
    }
    // retry the operation
    break;

case BUFFER_UNDERFLOW:
    // Maybe need to enlarge the peer network packet buffer
    if (engine.getSession().getPacketBufferSize() > peerNetData.capacity()) {
        // enlarge the peer network packet buffer
    } else {
        // compact or clear the buffer
    }
    // obtain more inbound network data and then retry the operation
    break;

    // Handle other status: CLOSED, OK
    ...
}

Example 3-15 Sample Code for Checking and Processing Handshaking Statuses and Overall Statuses

The following code sample illustrates how to process handshaking data by checking handshaking status and the overall status of the wrap() and unwrap() methods:

void doHandshake(SocketChannel socketChannel, SSLEngine engine,
        ByteBuffer myNetData, ByteBuffer peerNetData) throws Exception {

    // Create byte buffers to use for holding application data
    int appBufferSize = engine.getSession().getApplicationBufferSize();
    ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);
    ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);

    // Begin handshake
    engine.beginHandshake();
    SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();

    // Process handshaking message
    while (hs != SSLEngineResult.HandshakeStatus.FINISHED &&
        hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {

        switch (hs) {

        case NEED_UNWRAP:
                                    // Receive handshaking data from peer
            if (socketChannel.read(peerNetData) < 0) {
                // The channel has reached end-of-stream
            }

            // Process incoming handshaking data
            peerNetData.flip();
            SSLEngineResult res = engine.unwrap(peerNetData, peerAppData);
            peerNetData.compact();
            hs = res.getHandshakeStatus();

            // Check status
            switch (res.getStatus()) {
            case OK :
                // Handle OK status
                break;

            // Handle other status: BUFFER_UNDERFLOW, BUFFER_OVERFLOW, CLOSED
            ...
            }
            break;

                                case NEED_WRAP :
            // Empty the local network packet buffer.
            myNetData.clear();

            // Generate handshaking data
            res = engine.wrap(myAppData, myNetData);
            hs = res.getHandshakeStatus();

            // Check status
            switch (res.getStatus()) {
            case OK :
                myNetData.flip();

                // Send the handshaking data to peer
                while (myNetData.hasRemaining()) {
                    socketChannel.write(myNetData);
                }
                break;

            // Handle other status:  BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED
            ...
            }
            break;

        case NEED_TASK :
            // Handle blocking tasks
            break;

        // Handle other status:  // FINISHED or NOT_HANDSHAKING
        ...
        }
    }

    // Processes after handshaking
    ...
}

Example 3-16 Sample Code for Handling DTLS handshake Status and Overall Status

The following code sample illustrates how to handle DTLS handshake status:

void handshake(SSLEngine engine, DatagramSocket socket,
            SocketAddress peerAddr) throws Exception {

  boolean endLoops = false;

// private static int MAX_HANDSHAKE_LOOPS = 60;  
 
  int loops = MAX_HANDSHAKE_LOOPS;

  engine.beginHandshake();

  while (!endLoops && (serverException == null) && (clientException == null)) {

    if (--loops < 0) {
                throw new RuntimeException("Too many loops to produce handshake packets");
            }

    SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();

    if (hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ||
        hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) {

      ByteBuffer iNet;
      ByteBuffer iApp;

     if (hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {

     // receive ClientHello request and other SSL/TLS/DTLS records

     byte[] buf = new byte[1024];

     DatagramPacket packet = new DatagramPacket(buf, buf.length);

     try {

        socket.receive(packet);

     } catch (SocketTimeoutException ste) {
 
      // retransmit the packet if timeout

        List <Datagrampacket> packets =
                    onReceiveTimeout(engine, peerAddr);
        for (DatagramPacket p : packets) {

           socket.send(p);

        }

              continue;

    }
      iNet = ByteBuffer.wrap(buf, 0, packet.getLength());

      iApp = ByteBuffer.allocate(1024);

    } else {

      iNet = ByteBuffer.allocate(0);

      iApp = ByteBuffer.allocate(1024);

    }

    SSLEngineResult r = engine.unwrap(iNet, iApp);

    SSLEngineResult.Status rs = r.getStatus();

    hs = r.getHandshakeStatus();

    if (rs == SSLEngineResult.Status.BUFFER_OVERFLOW) {

    // the client maximum fragment size config does not work?

    throw new Exception("Buffer overflow: " +

          "incorrect client maximum fragment size");

    } else if (rs == SSLEngineResult.Status.BUFFER_UNDERFLOW) {

      // bad packet, or the client maximum fragment size

      // config does not work?

      if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {

       throw new Exception("Buffer underflow: " +

             "incorrect client maximum fragment size");

      } // otherwise, ignore this packet

    } else if (rs == SSLEngineResult.Status.CLOSED) {

                    endLoops = true;

    }   // otherwise, SSLEngineResult.Status.OK:


      if (rs != SSLEngineResult.Status.OK) {

          continue;

      }

    } else if (hs == SSLEngineResult.HandshakeStatus.NEED_WRAP) {

         List <DatagramPacket> packets =

             // Call a function to produce handshake packets
             produceHandshakePackets(engine, peerAddr);

         for (DatagramPacket p : packets) {

             socket.send(p);

        }

    } else if (hs == SSLEngineResult.HandshakeStatus.NEED_TASK) {

                runDelegatedTasks(engine);

    } else if (hs == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {

                // OK, time to do application data exchange.

                endLoops = true;

    } else if (hs == SSLEngineResult.HandshakeStatus.FINISHED) {

                endLoops = true;

    }

  }

   SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();

   if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {

            throw new Exception("Not ready for application data yet");

        }

}
Dealing With Blocking Tasks

During handshaking, an SSLEngine might encounter tasks that can block or take a long time.

For example, a TrustManager may need to connect to a remote certificate validation service, or a KeyManager might need to prompt a user to determine which certificate to use as part of client authentication. To preserve the nonblocking nature of SSLEngine, when the engine encounters such a task, it will return SSLEngineResult.HandshakeStatus.NEED_TASK. Upon receiving this status, the application should invoke SSLEngine.getDelegatedTask() to get the task, and then, using the threading model appropriate for its requirements, process the task. The application might, for example, obtain threads from a thread pool to process the tasks, while the main thread handles other I/O.

The following code executes each task in a newly created thread:

if (res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) {
    Runnable task;
    while ((task = engine.getDelegatedTask()) != null) {
        new Thread(task).start();
    }
}

The SSLEngine will block future wrap() and unwrap() calls until all of the outstanding tasks are completed.

Shutting Down a SSL/TLS/DTLS Connection

The SSL/TLS/DTLS protocols require transmission of close messages, for an orderly shutdown of an SSL/TLS/DTLS connection.

Therefore, when an application is done with the SSL/TLS/DTLS connection, it should first obtain the close messages from the SSLEngine, then transmit them to the peer using its transport mechanism, and finally shut down the transport mechanism, illustrates this.

In addition to an application explicitly closing the SSLEngine, the SSLEngine might be closed by the peer (via receipt of a close message while it is processing handshake data), or by the SSLEngine encountering an error while processing application or handshake data, indicated by throwing an SSLException. In such cases, the application should invoke SSLEngine.wrap() to get the close message and send it to the peer until SSLEngine.isOutboundDone() returns true (as shown in Example 3-17), or until the SSLEngineResult.getStatus() returns CLOSED.

In addition to orderly shutdowns, there can also be unexpected shutdowns when the transport link is severed before close messages are exchanged. In the previous examples, the application might get -1 or IOException when trying to read from the nonblocking SocketChannel, or get IOException when trying to write to the non-blocking SocketChannel. When you get to the end of your input data, you should call engine.closeInbound(), which will verify with the SSLEngine that the remote peer has closed cleanly from the SSL/TLS/DTLS perspective. Then the application should still try to shut down cleanly by using the procedure in Example 3-17. Obviously, unlike SSLSocket, the application using SSLEngine must deal with more state transitions, statuses, and programming. See Sample Code Illustrating the Use of an SSLEngine.

Example 3-17 Sample Code for Shutting Down a SSL/TLS/DTLS Connection

The following code sample illustrates how to shut down a SSL/TLS/DTLS connection:

// Indicate that application is done with engine
engine.closeOutbound();

while (!engine.isOutboundDone()) {
    // Get close message
    SSLEngineResult res = engine.wrap(empty, myNetData);

    // Check res statuses

    // Send close message to peer
    while(myNetData.hasRemaining()) {
        int num = socketChannel.write(myNetData);
        if (num == 0) {
            // no bytes written; try again later
        }
        myNetData().compact();
    }
}

// Close transport
socketChannel.close();
SSLSession and ExtendedSSLSession

The javax.net.ssl.SSLSession interface represents a security context negotiated between the two peers of an SSLSocket or SSLEngine connection. After a session has been arranged, it can be shared by future SSLSocket or SSLEngine objects connected between the same two peers.

In some cases, parameters negotiated during the handshake are needed later in the handshake to make decisions about trust. For example, the list of valid signature algorithms might restrict the certificate types that can be used for authentication. The SSLSession can be retrieved during the handshake by calling getHandshakeSession() on an SSLSocket or SSLEngine. Implementations of TrustManager or KeyManager can use the getHandshakeSession() method to get information about session parameters to help them make decisions.

A fully initialized SSLSession contains the cipher suite that will be used for communications over a secure socket as well as a nonauthoritative 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 or SSLEngine connection. The value of this master secret is known only to the underlying secure socket implementation and is not exposed through the SSLSession API.

ExtendedSSLSession extends the SSLSession interface to support additional session attributes. The ExtendedSSLSession class adds methods that describe the signature algorithms that are supported by the local implementation and the peer. The getRequestedServerNames() method called on an ExtendedSSLSession instance is used to obtain a list of SNIServerName objects in the requested Server Name Indication (SNI) Extension. The server should use the requested server names to guide its selection of an appropriate authentication certificate, and/or other aspects of the security policy. The client should use the requested server names to guide its endpoint identification of the peer's identity, and/or other aspects of the security policy.

Calls to the getPacketBufferSize() and getApplicationBufferSize() methods on SSLSession are used to determine the appropriate buffer sizes used by SSLEngine.

Note:

The SSL/TLS protocols specify that implementations are to produce packets containing at most 16 kilobytes (KB) of plain text. However, some implementations violate the specification and generate large records up to 32 KB. If the SSLEngine.unwrap() code detects large inbound packets, then the buffer sizes returned by SSLSession will be updated dynamically. Applications should always check the BUFFER_OVERFLOW and BUFFER_UNDERFLOW statuses and enlarge the corresponding buffers if necessary. See Understanding SSLEngine Operation Statuses. SunJSSE will always send standard compliant 16 KB records and allow incoming 32 KB records. For a workaround, see the System property jsse.SSLEngine.acceptLargeFragments in Customizing JSSE.
HttpsURLConnection Class

The javax.net.ssl.HttpsURLConnection class extends the java.net.HttpsURLConnection class and adds support for HTTPS-specific features.

The HTTPS protocol is similar to HTTP, but HTTPS first establishes a secure channel via SSL/TLS sockets and then verifies the identity of the peer before requesting or receiving data. The javax.net.ssl.HttpsURLConnection class extends the java.net.HttpsURLConnection class and adds support for HTTPS-specific features. To know more about how HTTPS URLs are constructed and used, see java.net.URL, java.net.URLConnection, java.net.HttpURLConnection, and javax.net.ssl.HttpsURLConnection classes.

Upon obtaining an HttpsURLConnection instance, you can configure a number of HTTP and HTTPS parameters before actually initiating the network connection via the URLConnection.connect() method. Of particular interest are:

Setting the Assigned SSLSocketFactory

In some situations, it is desirable to specify the SSLSocketFactory that an HttpsURLConnection instance uses.

For example, you might want to tunnel through a proxy type that is not supported by the default implementation. The new SSLSocketFactory could return sockets that have already performed all necessary tunneling, thus allowing HttpsURLConnection to use additional proxies.

The HttpsURLConnection class has a default SSLSocketFactory that is assigned when the class is loaded (this is the factory returned by the SSLSocketFactory.getDefault() method). Future instances of HttpsURLConnection will inherit the current default SSLSocketFactory until a new default SSLSocketFactory is assigned to the class via the static HttpsURLConnection.setDefaultSSLSocketFactory() method. Once an instance of HttpsURLConnection has been created, the inherited SSLSocketFactory on this instance can be overridden with a call to the setSSLSocketFactory() method.

Note:

Changing the default static SSLSocketFactory has no effect on existing instances of HttpsURLConnection. A call to the setSSLSocketFactory() method is necessary to change the existing instances.

You can obtain the per-instance or per-class SSLSocketFactory by making a call to the getSSLSocketFactory() or getDefaultSSLSocketFactory() method, respectively.

Setting the Assigned HostnameVerifier

If the host name of the URL does not match the host name in the credentials received as part of the SSL/TLS handshake, then it is possible that URL spoofing has occurred.

In order to is to prevent man-in-the-middle attacks earlier and effectively, it is recommended to handle the endpoint identification/verification during SSL/TLS handshaking. See SSLParameters.setEndpointIdentificationAlgorithm.

In JDK, the HTTPS endpoint identification algorithms are used for the underlying HttpsURLConnection implementation if no HostnameVerifier is explicitly specified.

Note:

For HttpsURLConnection, when a HostnameVerifier is explicitly set for a HTTPS connection, the hostname verification checks should be done at the layer over TLS, and the endpoint identification algorithm parameter should be set to null for backward compatibility.

Support Classes and Interfaces

The classes and interfaces in this section are provided to support the creation and initialization of SSLContext objects, which are used to create SSLSocketFactory, SSLServerSocketFactory, and SSLEngine objects. The support classes and interfaces are part of the javax.net.ssl package.

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. See JCA Design Principles and JCA Concepts.

The SunJSSE provider that comes standard with JSSE provides SSLContext, KeyManagerFactory, and TrustManagerFactory implementations, as well as implementations for engine classes in the standard java.security API. Table 3-4 lists implementations supplied by SunJSSE.

Table 3-4 Implementations Supplied by SunJSEE

Engine Class Implemented Algorithm or Protocol
KeyStore PKCS12
KeyManagerFactory PKIX, SunX509
TrustManagerFactory PKIX (X509 or SunPKIX), SunX509

SSLContext

SSLv3[1], TLSv1, TLSv1.1, TLSv1.2, DTLSv1.0, DTLSv1.2
Footnote 1 SSLv3 is enabled:
  • Starting with JDK 8u31, the SSLv3 protocol (Secure Socket Layer) has been deactivated and is not available by default. See the java.security.Security property jdk.tls.disabledAlgorithms in <java_home>/conf/security/java.security in file.

  • If SSLv3 is absolutely required, the protocol can be reactivated by removing "SSLv3" from the jdk.tls.disabledAlgorithms property in the java.security file or by dynamically setting this Security property before JSSE is initialized.

  • To enable SSLv3 protocol at deploy level, after following the above steps, edit the deployment.properties file and add the following : deployment.security.SSLv3=true

The SSLContext Class

The javax.net.ssl.SSLContext class is an engine class for an implementation of a secure socket protocol. An instance of this class acts as a factory for SSLSocket, SSLServerSocket, and SSLEngine. An SSLContext object holds all of the state information shared across all objects 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 at least the requested secure socket protocol. The returned instance may implement other protocols, too. For example, getInstance("TLSv1") may return an instance that implements TLSv1, TLSv1.1, and TLSv1.2. The getSupportedProtocols() method returns a list of supported protocols when an SSLSocket, SSLServerSocket, or SSLEngine is created from this context. You can control which protocols are actually enabled for an SSL connection by using the setEnabledProtocols(String[] protocols) method.

Note:

An SSLContext object is automatically created, initialized, and statically assigned to the SSLSocketFactory class when you call the SSLSocketFactory.getDefault() method.

To create an SSLContext object by calling the 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, then the system will determine whether an implementation of the requested protocol is available in the environment. If there is more than one implementation, then it will determine whether there is a preferred one.

If both a protocol name and a provider are specified, then the system will determine whether an implementation of the requested protocol is in the provider requested. If there is no implementation, an exception will be thrown.

A protocol is a string (such as "SSL") that describes the secure socket protocol desired. Common protocol names for SSLContext objects are defined in Java Cryptography Architecture Standard Algorithm Name Documentation.

An SSLContext can be obtained as follows:

    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[] parameter is null, then an empty KeyManager will be defined for this context. If the TrustManager[] parameter is null, then 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 SecureRandom parameter may be null, in which case a default implementation will be used.

If the internal default context is used, (for example, an SSLContext is created by SSLSocketFactory.getDefault() or SSLServerSocketFactory.getDefault()), then a default KeyManager and TrustManager are created. The default SecureRandom implementation is also chosen.

The TrustManager Interface

The primary responsibility of the TrustManager is to determine whether the presented authentication credentials should be trusted. If the credentials are not trusted, then the connection will be terminated. To authenticate the remote identity of a secure socket peer, you must initialize an SSLContext object with one or more TrustManager objects. You must pass one TrustManager for each authentication mechanism that is supported. If null is passed into the SSLContext initialization, then a trust manager will be created for you. Typically, a single trust manager supports authentication based on X.509 public key certificates (for example, X509TrustManager). Some secure socket implementations may also support authentication based on shared secret keys, Kerberos, or other mechanisms.

TrustManager objects are created either by a TrustManagerFactory, or by providing a concrete implementation of the interface.

The TrustManagerFactory Class

The javax.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. Because it is provider-based, additional factories can be implemented and configured to provide additional or alternative 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:

    TrustManagerFactory tmf = TrustManagerFactory.getInstance(String algorithm);
    
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(String algorithm, String provider);
    
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(String algorithm, Provider provider);

A sample call is as follows:

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

The preceding call creates an instance of the SunJSSE provider's PKIX trust manager factory. This factory can be used to create trust managers that provide X.509 PKIX-based certification path validity checking.

When initializing an SSLContext, you can use trust managers created from a trust manager factory, or you can write your own trust manager, for example, using the CertPath API. See Java PKI Programmer’s Guide. You do not need to use a trust manager factory if you implement a trust manager using the X509TrustManager interface.

A newly created factory should be initialized by calling one of the init() methods:

    public void init(KeyStore ks);
    public void init(ManagerFactoryParameters spec);

Call whichever init() method is appropriate for the TrustManagerFactory you are using. If you are not sure, then ask the provider vendor.

For many factories, such as the SunX509 TrustManagerFactory from the SunJSSE provider, the KeyStore is the only information required to initialize the TrustManagerFactory and thus the first init method is the appropriate one to call. The TrustManagerFactory will query the KeyStore for information about which remote certificates should be trusted during authorization checks.

Sometimes, initialization parameters other than a KeyStore are needed by a provider. Users of that provider are expected to pass an implementation of the appropriate ManagerFactoryParameters as defined by the provider. The provider can then call the specified methods in the ManagerFactoryParameters implementation to obtain the needed information.

For example, suppose the TrustManagerFactory provider requires initialization parameters B, R, and S from any application that wants to use that provider. Like all providers that require initialization parameters other than a KeyStore, the provider requires the application to provide an instance of a class that implements a particular ManagerFactoryParameters subinterface. In the example, suppose that the provider requires the calling application to implement and create an instance of MyTrustManagerFactoryParams and pass it to the second init() method. The following example illustrates what MyTrustManagerFactoryParams can look like:

    public interface MyTrustManagerFactoryParams extends ManagerFactoryParameters {
        public boolean getBValue();
        public float getRValue();
        public String getSValue():
    }

Some trust managers can make trust decisions without being explicitly initialized with a KeyStore object or any other parameters. For example, they may access trust material from a local directory service via LDAP, use a remote online certificate status checking server, or access default trust material from a standard local location.

PKIX TrustManager Support

The default trust manager algorithm is PKIX. It can be changed by editing the ssl.TrustManagerFactory.algorithm property in the java.security file.

The PKIX trust manager factory uses the CertPath PKIX implementation from an installed security provider. The trust manager factory can be initialized using the normal init(KeyStore ks) method, or by passing CertPath parameters to the PKIX trust manager using the CertPathTrustManagerParameters class.

Example 3-18 illustrates how to get the trust manager to use a particular LDAP certificate store and enable revocation checking.

If the init(KeyStore ks) method is used, then default PKIX parameters are used with the exception that revocation checking is disabled. It can be enabled by setting the com.sun.net.ssl.checkRevocation system property to true. This setting requires that the CertPath implementation can locate revocation information by itself. The PKIX implementation in the provider can do this in many cases but requires that the system property com.sun.security.enableCRLDP be set to true.

See PKIX and CertPath API

Example 3-18 Sample Code for Using a LDAP Certificate to Enable Revocation Checking

The following example illustrates how to get the trust manager to use a particular LDAP certificate store and enable revocation checking:

    import javax.net.ssl.*;
    import java.security.cert.*;
    import java.security.KeyStore;
    import java.io.FileInputStream;
    ...
    
    // Obtain Keystore password
    char[] pass = System.console().readPassword("Password: ");

    // Create PKIX parameters
    KeyStore anchors = KeyStore.getInstance("JKS");
    anchors.load(new FileInputStream(anchorsFile, pass));
    PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(anchors, new X509CertSelector());
    
    // Specify LDAP certificate store to use
    LDAPCertStoreParameters lcsp = new LDAPCertStoreParameters("ldap.imc.org", 389);
    pkixParams.addCertStore(CertStore.getInstance("LDAP", lcsp));
    
    // Specify that revocation checking is to be enabled
    pkixParams.setRevocationEnabled(true);
    
    // Wrap PKIX parameters as trust manager parameters
    ManagerFactoryParameters trustParams = new CertPathTrustManagerParameters(pkixParams);
    
    // Create TrustManagerFactory for PKIX-compliant trust managers
    TrustManagerFactory factory = TrustManagerFactory.getInstance("PKIX");
    
    // Pass parameters to factory to be passed to CertPath implementation
    factory.init(trustParams);
    
    // Use factory
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(null, factory.getTrustManagers(), null);

The X509TrustManager Interface

The javax.net.ssl.X509TrustManager interface extends the general TrustManager interface. It must be implemented by a trust manager when using X.509-based authentication.

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 interface that delegates to a factory-generated trust manager. For example, you might do this to filter the resulting trust decisions and query an end-user through a graphical user interface.

If a null KeyStore parameter is passed to the SunJSSE PKIX or SunX509 TrustManagerFactory, then the factory uses the following process to try to find trust material:

  1. If the javax.net.ssl.trustStore property is defined, then the TrustManagerFactory attempts to find a file using the file name specified by that system property, and uses that file for the KeyStore parameter. If the javax.net.ssl.trustStorePassword system property is also defined, then its value is used to check the integrity of the data in the truststore before opening it.

    If the javax.net.ssl.trustStore property is defined but the specified file does not exist, then a default TrustManager using an empty keystore is created.

  2. If the javax.net.ssl.trustStore system property was not specified, then:
    • if the file java-home/lib/security/jssecacerts exists, that file is used;
    • if the file java-home/lib/security/cacerts exists, that file is used;
    • if neither of these files exists, then the SSL cipher suite is anonymous, does not perform any authentication, and thus does not need a truststore.

To know more about what java-home refers to, see Terms and Definitions.

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

Creating Your Own X509TrustManager

If the supplied X509TrustManager behavior is not suitable for your situation, then you can create your own X509TrustManager by either creating and registering your own TrustManagerFactory or by implementing the X509TrustManager interface directly.

Example 3-19 illustrates a MyX509TrustManager class that enhances the default SunJSSE X509TrustManager behavior by providing alternative authentication logic when the default X509TrustManager fails.

Once you have created such a trust manager, assign it to an SSLContext via the init() method, as in the following example. Future SocketFactories created from this SSLContext will use your new TrustManager when making trust decisions.

    TrustManager[] myTMs = new TrustManager[] { new MyX509TrustManager() };
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(null, myTMs, null);

Example 3-19 Sample Code for Creating a X509TrustManager

The following code sample illustrates MyX509TrustManager class that enhances the default SunJSSE X509TrustManager behavior by providing alternative authentication logic when the default X509TrustManager fails:

class MyX509TrustManager implements X509TrustManager {

     /*
      * The default PKIX X509TrustManager9.  Decisions are delegated
      * to it, and a fall back to the logic in this class is performed
      * if the default X509TrustManager does not trust it.
      */
     X509TrustManager pkixTrustManager;

     MyX509TrustManager() throws Exception {
         // create a "default" JSSE X509TrustManager.

         KeyStore ks = KeyStore.getInstance("JKS");
         ks.load(new FileInputStream("trustedCerts"), "passphrase".toCharArray());

         TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
         tmf.init(ks);

         TrustManager tms [] = tmf.getTrustManagers();

         /*
          * Iterate over the returned trust managers, looking
          * for an instance of X509TrustManager.  If found,
          * use that as the default trust manager.
          */
         for (int i = 0; i < tms.length; i++) {
             if (tms[i] instanceof X509TrustManager) {
                 pkixTrustManager = (X509TrustManager) tms[i];
                 return;
             }
         }

         /*
          * Find some other way to initialize, or else the
          * constructor fails.
          */
         throw new Exception("Couldn't initialize");
     }

     /*
      * Delegate to the default trust manager.
      */
     public void checkClientTrusted(X509Certificate[] chain, String authType)
                 throws CertificateException {
         try {
             pkixTrustManager.checkClientTrusted(chain, authType);
         } catch (CertificateException excep) {
             // do any special handling here, or rethrow exception.
         }
     }

     /*
      * Delegate to the default trust manager.
      */
     public void checkServerTrusted(X509Certificate[] chain, String authType)
                 throws CertificateException {
         try {
             pkixTrustManager.checkServerTrusted(chain, authType);
         } catch (CertificateException excep) {
             /*
              * Possibly pop up a dialog box asking whether to trust the
              * cert chain.
              */
         }
     }

     /*
      * Merely pass this through.
      */
     public X509Certificate[] getAcceptedIssuers() {
         return pkixTrustManager.getAcceptedIssuers();
     }
}

Updating the Keystore Dynamically

You can enhance MyX509TrustManager to handle dynamic keystore updates. When a checkClientTrusted or checkServerTrusted test fails and does not establish a trusted certificate chain, you can add the required trusted certificate to the keystore. You must create a new pkixTrustManager from the TrustManagerFactory initialized with the updated keystore. When you establish a new connection (using the previously initialized SSLContext), the newly added certificate will be used when making trust decisions.

X509ExtendedTrustManager Class

The X509ExtendedTrustManager class is an abstract implementation of the X509TrustManager interface. It adds methods for connection-sensitive trust management. In addition, it enables endpoint verification at the TLS layer.

In TLS 1.2 and later, both client and server can specify which hash and signature algorithms they will accept. To authenticate the remote side, authentication decisions must be based on both X509 certificates and the local accepted hash and signature algorithms. The local accepted hash and signature algorithms can be obtained using the ExtendedSSLSession.getLocalSupportedSignatureAlgorithms() method.

The ExtendedSSLSession object can be retrieved by calling the SSLSocket.getHandshakeSession() method or the SSLEngine.getHandshakeSession() method.

The X509TrustManager interface is not connection-sensitive. It provides no way to access SSLSocket or SSLEngine session properties.

Besides TLS 1.2 support, the X509ExtendedTrustManager class also supports algorithm constraints and SSL layer host name verification. For JSSE providers and trust manager implementations, the X509ExtendedTrustManager class is highly recommended over the legacy X509TrustManager interface.

Creating an X509ExtendedTrustManager

You can either create an X509ExtendedTrustManager subclass yourself (which is outlined in the following section) or obtain one from a provider-based TrustManagerFactory (such as that supplied by the SunJSSE provider). In Java SE 7, the PKIX or SunX509 TrustManagerFactory returns an X509ExtendedTrustManager instance.

Creating Your Own X509ExtendedTrustManager

This section outlines how to create a subclass of X509ExtendedTrustManager in nearly the same way as described for X509TrustManager.

Example 3-20 illustrates how to create a class that uses the PKIX TrustManagerFactory to locate a default X509ExtendedTrustManager that will be used to make decisions about trust.

Example 3-20 Sample Code for Creating a PKIX TrustManagerFactory

The following code sample illustrates how to create a class that uses the PKIX TrustManagerFactory to locate a default X509ExtendedTrustManager that will be used to make decisions about trust. If the default trust manager fails for any reason, then the subclass can add other behavior. In the sample, these locations are indicated by comments in the catch clauses.

    import java.io.*;
    import java.net.*;
    
    import java.security.*;
    import java.security.cert.*;
    import javax.net.ssl.*;
    
    public class MyX509ExtendedTrustManager extends X509ExtendedTrustManager {
    
         /*
          * The default PKIX X509ExtendedTrustManager.  Decisions are
          * delegated to it, and a fall back to the logic in this class is
          * performed if the default X509ExtendedTrustManager does not
          * trust it.
          */
         X509ExtendedTrustManager pkixTrustManager;
    
         MyX509ExtendedTrustManager() throws Exception {
             // create a "default" JSSE X509ExtendedTrustManager.
    
             KeyStore ks = KeyStore.getInstance("JKS");
             ks.load(new FileInputStream("trustedCerts"), "passphrase".toCharArray());
    
             TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
             tmf.init(ks);
    
             TrustManager tms [] = tmf.getTrustManagers();
    
             /*
              * Iterate over the returned trust managers, looking
              * for an instance of X509ExtendedTrustManager. If found,
              * use that as the default trust manager.
              */
             for (int i = 0; i < tms.length; i++) {
                 if (tms[i] instanceof X509ExtendedTrustManager) {
                     pkixTrustManager = (X509ExtendedTrustManager) tms[i];
                     return;
                 }
             }
    
             /*
              * Find some other way to initialize, or else we have to fail the
              * constructor.
              */
             throw new Exception("Couldn't initialize");
         }
    
         /*
          * Delegate to the default trust manager.
          */
         public void checkClientTrusted(X509Certificate[] chain, String authType)
                     throws CertificateException {
             try {
                 pkixTrustManager.checkClientTrusted(chain, authType);
             } catch (CertificateException excep) {
                 // do any special handling here, or rethrow exception.
             }
         }
    
         /*
          * Delegate to the default trust manager.
          */
         public void checkServerTrusted(X509Certificate[] chain, String authType)
                     throws CertificateException {
             try {
                 pkixTrustManager.checkServerTrusted(chain, authType);
             } catch (CertificateException excep) {
                 /*
                  * Possibly pop up a dialog box asking whether to trust the
                  * cert chain.
                  */
             }
         }
    
         /*
          * Connection-sensitive verification.
          */
         public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket)
                     throws CertificateException {
           try {
               pkixTrustManager.checkClientTrusted(chain, authType, socket);
           } catch (CertificateException excep) {
               // do any special handling here, or rethrow exception.
           }
         }
    
         public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine)
                     throws CertificateException {
           try {
               pkixTrustManager.checkClientTrusted(chain, authType, engine);
           } catch (CertificateException excep) {
               // do any special handling here, or rethrow exception.
           }
         }
    
         public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket)
                     throws CertificateException {
           try {
               pkixTrustManager.checkServerTrusted(chain, authType, socket);
           } catch (CertificateException excep) {
               // do any special handling here, or rethrow exception.
           }
         }
    
         public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine)
                     throws CertificateException {
           try {
               pkixTrustManager.checkServerTrusted(chain, authType, engine);
           } catch (CertificateException excep) {
               // do any special handling here, or rethrow exception.
           }
         }
         
         /*
          * Merely pass this through.
          */
         public X509Certificate[] getAcceptedIssuers() {
             return pkixTrustManager.getAcceptedIssuers();
         }
    }

The KeyManager Interface

The primary responsibility of the KeyManager is to select the authentication credentials that will eventually be sent to the remote host. To authenticate yourself (a local secure socket peer) to a remote peer, you must initialize an SSLContext object with one or more KeyManager objects. You must pass one KeyManager for each different authentication mechanism that will be supported. If null is passed into the SSLContext initialization, then an empty KeyManager will be created. If the internal default context is used (for example, an SSLContext created by SSLSocketFactory.getDefault() or SSLServerSocketFactory.getDefault()), then a default KeyManager is created. See Customizing the Default Keystores and Truststores, Store Types, and Store Passwords. Typically, a single key manager 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.

KeyManager objects are created either by a KeyManagerFactory, or by providing a concrete implementation of the interface.

The KeyManagerFactory Class

The javax.net.ssl.KeyManagerFactory class 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 that can return a basic X.509 key manager. Because it is provider-based, additional factories can be implemented and configured to provide additional or alternative 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:

    KeyManagerFactory kmf = getInstance(String algorithm);
    
    KeyManagerFactory kmf = getInstance(String algorithm, String provider);
    
    KeyManagerFactory kmf = getInstance(String algorithm, Provider provider);

A sample call as follows:

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

The preceding call creates 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 one of the init methods:

    public void init(KeyStore ks, char[] password);
    public void init(ManagerFactoryParameters spec);

Call whichever init method is appropriate for the KeyManagerFactory you are using. If you are not sure, then ask the provider vendor.

For many factories, such as the default SunX509 KeyManagerFactory from the SunJSSE provider, the KeyStore and password are the only information required to initialize the KeyManagerFactory and thus the first init method is the appropriate one to call. The KeyManagerFactory will query the KeyStore for information about which private key and matching public key certificates should be used for authenticating to a remote socket peer. The password parameter specifies 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.

Sometimes initialization parameters other than a KeyStore and password are needed by a provider. Users of that provider are expected to pass an implementation of the appropriate ManagerFactoryParameters as defined by the provider. The provider can then call the specified methods in the ManagerFactoryParameters implementation to obtain the needed information.

Some factories can provide access to authentication material without being initialized with a KeyStore object or any other parameters. 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.

As previously indicated, the SunJSSE provider supports a SunX509 factory that must be initialized with a KeyStore parameter.

The X509KeyManager Interface

The javax.net.ssl.X509KeyManager interface extends the general KeyManager interface. It must be implemented by a key manager for X.509-based authentication. 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 interface that delegates to a factory-generated key manager. For example, you might do this to filter the resulting keys and query an end-user through a graphical user interface.

Creating Your Own X509KeyManager

If the default X509KeyManager behavior is not suitable for your situation, then you can create your own X509KeyManager in a way similar to that shown in Creating Your Own X509TrustManager.

The X509ExtendedKeyManager Class

The X509ExtendedKeyManager abstract class is an implementation of the X509KeyManager interface that allows for connection-specific key selection. It adds two methods that select a key alias for client or server based on the key type, allowed issuers, and current SSLEngine:

  • public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine)
  • public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine)

If a key manager is not an instance of the X509ExtendedKeyManager class, then it will not work with the SSLEngine class.

For JSSE providers and key manager implementations, the X509ExtendedKeyManager class is highly recommended over the legacy X509KeyManager interface.

In TLS 1.2 and later, both client and server can specify which hash and signature algorithms they will accept. To pass the authentication required by the remote side, local key selection decisions must be based on both X509 certificates and the remote accepted hash and signature algorithms. The remote accepted hash and signature algorithms can be retrieved using the ExtendedSSLSession.getPeerSupportedSignatureAlgorithms() method.

You can create your own X509ExtendedKeyManager subclass in a way similar to that shown in Creating Your Own X509TrustManager.

Support for the Server Name Indication (SNI) extension on the server side enables the key manager to check the server name and select the appropriate key accordingly. For example, suppose there are three key entries with certificates in the keystore:

  • cn=www.example.com
  • cn=www.example.org
  • cn=www.example.net

If the ClientHello message requests to connect to www.example.net in the SNI extension, then the server should be able to select the certificate with subject cn=www.example.net.

Relationship Between a TrustManager and a KeyManager

Historically, there has been confusion regarding the functionality of a TrustManager and a KeyManager.

A TrustManager determines whether the remote authentication credentials (and thus the connection) should be trusted.

A KeyManager determines which authentication credentials to send to the remote host.

Secondary Support Classes and Interfaces

These classes are provided as part of the JSSE 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 and support classes. The secondary support classes and interfaces are part of the javax.net.ssl and javax.security.cert packages.

The SSLParameters Class

The SSLParameters class encapsulates the following parameters that affect a SSL/TLS/DTLS connection:

  • The list of cipher suites to be accepted in an SSL/TLS/DTLS handshake
  • The list of protocols to be allowed
  • The endpoint identification algorithm during SSL/TLS/DTLS handshaking
  • The server names and server name matchers (see the Server Name Indication (SNI) Extension)
  • The cipher suite preference to be used in an SSL/TLS/DTLS handshake
  • Algorithm during SSL/TLS/DTLS handshaking

  • The Server Name Indication (SNI)

  • The maximum network packet size

  • The algorithm constraints and whether SSL/TLS/DTLS servers should request or require client authentication

You can retrieve the current SSLParameters for an SSLSocket or SSLEngine by using the following methods:

  • getSSLParameters() in an SSLSocket, SSLServerSocket, and SSLEngine
  • getDefaultSSLParameters() and getSupportedSSLParamters() in an SSLContext

You can assign SSLParameters with the setSSLParameters() method in an SSLSocket, SSLServerSocket and SSLEngine.

You can explicitly set the server name indication with the SSLParameters.setServerNames() method. The server name indication in client mode also affects endpoint identification. In the implementation of X509ExtendedTrustManager, it uses the server name indication retrieved by the ExtendedSSLSession.getRequestedServerNames() method. See Example 3-21.

In Example 3-21, the host name in the server name indication (www.example.com) will be used to make endpoint identification against the peer's identity presented in the end-entity's X.509 certificate.

Example 3-21 Sample Code to Set the Server Name Indication

The following example illustrates how to set the server name indication with the SSLParameters.setServerNames() method:

    SSLSocketFactory factory = ...
    SSLSocket sslSocket = factory.createSocket("172.16.10.6", 443);
    // SSLEngine sslEngine = sslContext.createSSLEngine("172.16.10.6", 443);

    SNIHostName serverName = new SNIHostName("www.example.com");
    List<SNIServerName> serverNames = new ArrayList<>(1);
    serverNames.add(serverName);
 
    SSLParameters params = sslSocket.getSSLParameters();
    params.setServerNames(serverNames);
    sslSocket.setSSLParameters(params);
    // sslEngine.setSSLParameters(params);

Cipher Suite Preference

During TLS handshaking, the client requests to negotiate a cipher suite from a list of cryptographic options that it supports, starting with its first preference. Then, the server selects a single cipher suite from the list of cipher suites requested by the client. Normally, the selection honors the client's preference. However, to mitigate the risks of using weak cipher suites, the server may select cipher suites based on its own preference rather than the client's preference, by invoking the method SSLParameters.setUseCipherSuitesOrder(true).

The SSLSessionContext Interface

The javax.net.ssl.SSLSessionContext interface is a grouping of SSLSession objects associated with a single entity. For example, it could be associated with a server or client that participates in many sessions concurrently. The methods in 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.

The SSLSessionBindingListener Interface

The javax.net.ssl.SSLSessionBindingListener interface is implemented by objects that are notified when they are being bound or unbound from an SSLSession.

The SSLSessionBindingEvent Class

The javax.net.ssl.SSLSessionBindingEvent class defines the event communicated to an  SSLSessionBindingListener when it is bound or unbound from an SSLSession.

The HandShakeCompletedListener Interface

The javax.net.ssl.HandShakeCompletedListener interface is an interface implemented by any class that is notified of the completion of an SSL protocol handshake on a given SSLSocket connection.

The HandShakeCompletedEvent Class

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

The HostnameVerifier Interface

If the SSL/TLS implementation's standard host name verification logic fails, then the implementation calls the verify() method of the class that implements this interface and is assigned to this HttpsURLConnection instance. If the callback class can determine that the host name is acceptable given the parameters, it reports that the connection should be allowed. An unacceptable response causes the connection to be terminated. See Example 3-22.

See HttpsURLConnection about how to assign the HostnameVerifier to the HttpsURLConnection.

Example 3-22 Sample Code for Implementing the HostnameVerifier Interface

The following example illustrates a class that implements HostnameVerifier interface:

    public class MyHostnameVerifier implements HostnameVerifier {
    
        public boolean verify(String hostname, SSLSession session) {
            // pop up an interactive dialog box
            // or insert additional matching logic
            if (good_address) {
                return true;
            } else {
                return false;
            }
        }
    }
    
    //...deleted...
    
    HttpsURLConnection urlc = (HttpsURLConnection)
      (new URL("https://www.example.com/")).openConnection();
    urlc.setHostnameVerifier(new MyHostnameVerifier());

The 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/TLS protocols.

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

Note:

The javax.security.cert.X509Certificate class is supported only for backward compatibility with previous (1.0.x and 1.1.x) versions of JSSE. New applications should use the java.security.cert.X509Certificate class instead.

The AlgorithmConstraints Interface

The java.security.AlgorithmConstraints interface is used for controlling allowed cryptographic algorithms. AlgorithmConstraints defines three permits() methods. These methods tell whether an algorithm name or a key is permitted for certain cryptographic functions. Cryptographic functions are represented by a set of CryptoPrimitive, which is an enumeration containing fields like STREAM_CIPHER, MESSAGE_DIGEST, and SIGNATURE.

Thus, an AlgorithmConstraints implementation can answer questions like: Can I use this key with this algorithm for the purpose of a cryptographic operation?

An AlgorithmConstraints object can be associated with an SSLParameters object by using the new setAlgorithmConstraints() method. The current AlgorithmConstraints object for an SSLParameters object is retrieved using the getAlgorithmConstraints() method.

The StandardConstants Class

The StandardConstants class is used to represent standard constants definitions in JSSE.

StandardConstants.SNI_HOST_NAME represents a domain name server (DNS) host name in a Server Name Indication (SNI) extension, which can be used when instantiating an SNIServerName or SNIMatcher object.

The SNIServerName Class

An instance of the abstract SNIServerName class represents a server name in the Server Name Indication (SNI) extension. It is instantiated using the type and encoded value of the specified server name.

You can use the getType() and getEncoded() methods to return the server name type and a copy of the encoded server name value, respectively. The equals() method can be used to check if some other object is "equal" to this server name. The hashCode() method returns a hash code value for this server name. To get a string representation of the server name (including the server name type and encoded server name value), use the toString() method.

The SNIMatcher Class

An instance of the abstract SNIMatcher class performs match operations on an SNIServerName object. Servers can use information from the Server Name Indication (SNI) extension to decide if a specific SSLSocket or SSLEngine should accept a connection. For example, when multiple "virtual" or "name-based" servers are hosted on a single underlying network address, the server application can use SNI information to determine whether this server is the exact server that the client wants to access. Instances of this class can be used by a server to verify the acceptable server names of a particular type, such as host names.

The SNIMatcher class is instantiated using the specified server name type on which match operations will be performed. To match a given SNIServerName, use the matches() method. To return the server name type of the given SNIMatcher object, use the getType() method.

The SNIHostName Class

An instance of the SNIHostName class (which extends the SNIServerName class) represents a server name of type "host_name" (see StandardConstants Class) in the Server Name Indication (SNI) extension. To instantiate an SNIHostName, specify the fully qualified DNS host name of the server (as understood by the client) as a String argument. The argument is illegal in the following cases:

  • The argument is empty.
  • The argument ends with a trailing period.
  • The argument is not a valid Internationalized Domain Name (IDN) compliant with the RFC 3490 specification.

You can also instantiate an SNIHostName by specifying the encoded host name value as a byte array. This method is typically used to parse the encoded name value in a requested SNI extension. Otherwise, use the SNIHostName(String hostname) constructor. The encoded argument is illegal in the following cases:

  • The argument is empty.
  • The argument ends with a trailing period.
  • The argument is not a valid Internationalized Domain Name (IDN) compliant with the RFC 3490 specification.
  • The argument is not encoded in UTF-8 or US-ASCII.

Note:

The encoded byte array passed in as an argument is cloned to protect against subsequent modification.

To return the host name of an SNIHostName object in US-ASCII encoding, use the getAsciiName() method. To compare a server name to another object, use the equals() method (comparison is not case-sensitive). To return a hash code value of an SNIHostName, use the hashCode() method. To return a string representation of an SNIHostName, including the DNS host name, use the toString() method.

You can create an SNIMatcher object for an SNIHostName object by passing a regular expression representing one or more host names to match to the createSNIMatcher() method.

Customizing JSSE

JSSE includes a standard implementation that can be customized by plugging in different implementations or specifying the default keystore, and so on.

Table 3-5 and Table 3-6 summarizes which aspects can be customized, what the defaults are, and which mechanisms are used to provide customization.

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.

Note:

Many of the properties shown in this table are currently used by the JSSE 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 asterisk (*). They are documented here for your convenience for use with the JSSE implementation.

Table 3-5 shows items that are customized by setting the java.security.Security property. See How to Specify a java.security.Security Property

Table 3-5 Security Properties and Customized Items

Security Property Customized Item Default Notes
cert.provider.x509v1 X509Certificate Implementation X509Certificate implementation from Oracle

None

security.provider.n Provider Implementation SunJSSE Specify the provider in the security.provider.n= line in security properties file
*ssl.SocketFactory.provider Default SSLSocketFactory implementation SSLSocketFactory implementation from Oracle

None

*ssl.ServerSocketFactory.provider Default SSLServerSocketFactory implementation SSLServerSocketFactory implementation from Oracle

None

ssl.KeyManagerFactory.algorithm Default key manager factory algorithm name SunX509

None

jdk.certpath.disabledAlgorithms Disabled certificate verification cryptographic algorithm MD2, RSA keySize less than 1024

None

ssl.TrustManagerFactory.algorithm Default trust manager factory algorithm name PKIX

None

JCE encryption algorithms used by the SunJSSE provider Give alternative JCE algorithm providers a higher preference order than the SunJCE provider SunJCE implementations

None

jdk.tls.disabledAlgorithms

Disabled /Restricted Algorithm SSLv3 Disables specific algorithms (protocols versions, ciphersuites, key exchange mechanisms, etc.) that will not be negotiated for SSL/TLS/DTLS connections, even if they are enabled explicitly in an application
jdk.tls.server.defaultDHEParameters Diffie-Hellman groups Safe prime Diffie-Hellman groups in OpenJDK SSL/TLS/DTLS implementation Defines default finite field Diffie-Hellman ephemeral (DHE) parameters for Transport Layer Security (SSL/TLS/DTLS) processing

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

Table 3-6 shows items that are customized by setting java.lang.System property. See How to Specify a java.lang.System Property.

Table 3-6 System Properties and Customized Items

System Property Customized Item Default Notes
java.protocol.handler.pkgs HTTPS Protocol Implementation Implementation from Oracle

None

*javax.net.ssl.keyStore Default keystore

None

The value NONE may be specified. This setting is appropriate if the keystore is not file-based (for example, it resides in a hardware token)
*javax.net.ssl.keyStorePassword Default keystore password

None

It is inadvisable to specify the password in a way that exposes it to discovery by other users.

For example, specifying the password on the command line. To keep the password secure, have the application prompt for the password, or specify the password in a properly protected option file

*javax.net.ssl.keyStoreProvider Default keystore provider

None

None

*javax.net.ssl.keyStoreType Default keystore type KeyStore.getDefaultType()

None

*javax.net.ssl.trustStore Default truststore jssecacerts, if it exists.

Otherwise, cacerts

None

*javax.net.ssl.trustStorePassword Default truststore password

None

It is inadvisable to specify the password in a way that exposes it to discovery by other users.

For example, specifying the password on the command line. To keep the password secure, have the application prompt for the password, or specify the password in a properly protected option file

*javax.net.ssl.trustStoreProvider Default truststore provider

None

None

*javax.net.ssl.trustStoreType Default truststore type KeyStore.getDefaultType() The value NONE may be specified. This setting is appropriate if the truststore is not file-based (for example, it resides in a hardware token)
*https.proxyHost Default proxy host

None

None

*https.proxyPort Default proxy port 80

None

*jsse.enableSNIExtension Server Name Indication option true Server Name Indication (SNI) is a TLS extension, defined in RFC 6066. It enables TLS connections to virtual servers, in which multiple servers for different network names are hosted at a single underlying network address. Some very old SSL/TLS vendors may not be able handle SSL/TLS extensions. In this case, set this property to false to disable the SNI extension
*https.cipherSuites Default cipher suites Determined by the socket factory.

This contains a comma-separated list of cipher suite names specifying which cipher suites to enable for use on this HttpsURLConnection. See the SSLSocket.setEnabledCipherSuites(String[])

*https.protocols Default handshaking protocols Determined by the socket factory.

This contains a comma-separated list of protocol suite names specifying which protocol suites to enable on this HttpsURLConnection. See SSLSocket.setEnabledProtocols(String[])

* Customize via port field in the HTTPS URL. Default HTTPS port 443

None

*jsse.SSLEngine.acceptLargeFragments Default sizing buffers for large SSL/TLS packets

None

Setting this system property to true, SSLSession will size buffers to handle large data packets by default. This may cause applications to allocate unnecessarily large SSLEngine buffers. Instead, applications should dynamically check for buffer overflow conditions and resize buffers as appropriate

*sun.security.ssl.allowUnsafeRenegotiation Allow Unsafe SSL/TLS Renegotiations false

Setting this system property to true permits full (unsafe) legacy renegotiation.

This system property is deprecated and might be removed in a future JDK release.

*sun.security.ssl.allowLegacyHelloMessages Allow Legacy Hello Messages (Renegotiations) true

Setting this system property to true allows the peer to handshake without requiring the proper RFC 5746 messages.

This system property is deprecated and might be removed in a future JDK release.

jdk.tls.client.protocols

SunJSSE Provider Protocol Parameters in the Oracle Providers

None

To enable specific SunJSSE protocols on the client, specify them in a comma-separated list within quotation marks; all other supported protocols are not enabled on the client

For example,
  • If jdk.tls.client.protocols="TLSv1,TLSv1.1", then the default protocol settings on the client for TLSv1 and TLSv1.1 are enabled, while SSLv3, TLSv1.2, and SSLv2Hello are not enabled

  • If jdk.tls.client.protocols=“DTLSv1.2” , then the protocol setting on the client for DTLS1.2 is enabled, while DTLS1.0 is not enabled

jdk.tls.ephemeralDHKeySize Size of ephemeral Diffie-Hellman keys 1024 bits

None

jsse.enableMFLNExtension Customizing Maximum Fragment Length Negotiation (MFLN) Extension false

None

* This property is currently used by the JSSE implementation, but it is not guaranteed to be examined and used by other implementations. If it is examined by another implementation, then that implementation should handle it in the same manner as the JSSE 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 java.lang.System Property

You can specify a java.lang.System property in the javax.net.ssl.trustStore .

You can customize some aspects of JSSE by setting system properties. There are several ways to set these properties:
  • To set a system property statically, use the -D option of the java command. For example, to run an application named MyApp and set the javax.net.ssl.trustStore system property to specify a truststore named MyCacertsFile. See truststore. Enter the following:
            java -Djavax.net.ssl.trustStore=MyCacertsFile MyApp
                    
    
  • To set a system property dynamically, call the java.lang.System.setProperty() method in your code:
            System.setProperty("propertyName", "propertyValue");
                    
    
    For example, a setProperty() call corresponding to the previous example for setting the javax.net.ssl.trustStore system property to specify a truststore named "MyCacertsFile" would be:
            System.setProperty("javax.net.ssl.trustStore", "MyCacertsFile");
                    
    
  • In the Java Deployment environment (Plug-In/Web Start), there are several ways to set the system properties.
    • Use the Java Control Panel to set the Runtime Environment Property on a local or per-VM basis. This creates a local deployment.properties file. Deployers can also distribute an enterprise wide deployment.properties file by using the deployment.config mechanism.

    • To set a property for a specific applet, use the HTML subtag <PARAM> "java_arguments" within the <APPLET> tag.

    • To set the property in a specific Java Web Start application or applet using Plugin2, use the JNLP property sub element of the resources element. See resources Element in the Java Platform, Standard Edition Deployment Guide.

How to Specify a java.security.Security Property

Procedure to specify a java.security.Security property either statically or dynamically.

You can customize some aspects of JSSE by setting security properties. You can set a security property either statically or dynamically:
  • To set a security property statically, add a line to the security properties file. The security properties file is located at java-home/conf/security/java.security
    java-home
    See Terms and Definitions

    To specify a security property value in the security properties file, you add a line of the following form:

            propertyName=propertyValue
                    
    

    For example, suppose that you want to specify a different key manager factory algorithm name than the default SunX509. You do this by specifying the algorithm name as the value of a security property named ssl.KeyManagerFactory.algorithm. For example, to set the value to MyX509, add the following line to the security properties file:

            ssl.KeyManagerFactory.algorithm=MyX509
                    
    
  • To set a security property dynamically, call the java.security.Security.setProperty method in your code:
            Security.setProperty("propertyName," "propertyValue");
                    
    
    For example, a call to the setProperty() method corresponding to the previous example for specifying the key manager factory algorithm name would be:
            Security.setProperty("ssl.KeyManagerFactory.algorithm", "MyX509");
            
    

Customizing the X509Certificate Implementation

The X509Certificate implementation returned by the X509Certificate.getInstance() method is by default the implementation from the JSSE implementation.

To cause a different implementation to be returned:
Specify the name (and package) of the other implementation's class as the value of a How to Specify a java.security.Security Property named cert.provider.x509v1.
For example, if the class is called MyX509CertificateImpl and it appears in the com.cryptox package, then you should add the following line to the security properties file:
    cert.provider.x509v1=com.cryptox.MyX509CertificateImpl

Specifying an Alternative HTTPS Protocol Implementation

You can communicate securely with an SSL-enabled web server by using the HTTPS URL scheme for the java.net.URL class. The JDK provides a default HTTPS URL implementation.

If you want an alternative HTTPS protocol implementation to be used, set the java.protocol.handler.pkgs How to Specify a java.lang.System Property to include the new class name. This action causes the specified classes to be found and loaded before the JDK default classes. See the URL documentation for details.

Note:

In past JSSE releases, you had to set the java.protocol.handler.pkgs system property during JSSE installation. This step is no longer required unless you want to obtain an instance of com.sun.net.ssl.HttpsURLConnection. See Code Using HttpsURLConnection Class Throws ClassCastException in JSSE 1.0.x in the "Troubleshooting" section.

Customizing the Default Keystores and Truststores, 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 implementation.)

This default SSLContext is initialized with a default KeyManager and a default TrustManager. If a keystore is specified by the javax.net.ssl.keyStore system property and an appropriate javax.net.ssl.keyStorePassword 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 Managers and Trust Managers.) If no such system property is specified, then the keystore managed by the KeyManager will be a new empty keystore.

Generally, the peer acting as the server in the handshake will need a keystore for its KeyManager in order to obtain credentials for authentication to the client. However, if one of the anonymous cipher suites is selected, then the server's KeyManager keystore is not necessary. And, unless the server requires client authentication, the peer acting as the client does not need a KeyManager keystore. Thus, in these situations it may be OK if no javax.net.ssl.keyStore system property value is defined.

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 does not, then no truststore is used. 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 Terms and Definitions. Finally, if a truststore is still not found, then the truststore managed by the TrustManager will be a new empty truststore.

Note:

The JDK ships with a limited number of trusted root certificates in the java-home/lib/security/cacerts file. As documented in Java Security Tools reference pages, it is your responsibility to maintain (that is, add and remove) the certificates contained in this file if you use this file as a truststore.

Depending on the certificate configuration of the servers that you contact, you may need to add additional root certificates. Obtain the needed specific root certificates from the appropriate vendor.

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

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

Note:

This section describes the current JSSE 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 implementations. If they are examined by an implementation, then that implementation should handle them in the same manner as the JSSE reference implementation does, as described herein.

Customizing the Provider Implementation

JDK 1.4 and later releases come standard with a JSSE 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 engine classes are SSLContext, KeyManagerFactory, and TrustManagerFactory. See Java Cryptography Architecture (JCA) Reference Guide to know more about providers and engine classes.

Note:

The transformation strings used when SunJSSE calls Cipher.getInstance() are "RSA/ECB/PKCS1Padding", "RC4", "DES/CBC/NoPadding", and "DESede/CBC/NoPadding". See Java Cryptography Architecture (JCA) Reference Guide.

Before it can be used, a provider must be registered, either statically or dynamically. You do not need to register the SunJSSE provider because it is preregistered. If you want to use other providers, read the following sections to see how to register them.

Registering the Cryptographic Provider Statically

Register a provider and specify the preference order for the provider with security.provider.n property.

    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). "1" is the most preferred, followed by "2", and so on.

The providerClassNameis the fully qualified name of the provider class. You obtain this name from the provider vendor.

The standard security provider and the SunJSSE provider shipped with JDK 6 are automatically registered for you; the following lines appear in the java.security security properties file to register the SunJCE security provider with preference order 5 and the SunJSSE provider with preference order 4:

security.provider.1=sun.security.pkcs11.SunPKCS11 \
${java.home}/lib/security/sunpkcs11-solaris.cfg
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider

To use another JSSE provider, add a line registering the other provider, giving it whatever preference order you prefer.

You can have more than one JSSE provider registered at the same time. The registered providers 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, then 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 dynamically add a provider whose provider class name is MyProvider and whose MyProvider class resides in the com.ABC package, you would call:

    Security.addProvider(new com.ABC.MyProvider());

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.

Provider Configuration

Some providers may require configuration. This is done using the configure method of the Provider class, prior to calling the addProvider method of the Security class. See The SunPKCS11 Configuration for an example. The Provider.configure() method is new to Java SE 9.

Configuring the Preferred Provider for Specific Algorithms

Specify the preferred provider for a specific algorithm in the jdk.security.provider.preferred security property. By specifying a preferred provider you can configure providers that offer performance gains for specific algorithms but are not the best performing provider for other algorithms. The ordered provider list specified using the security.provider.n property is not sufficient to order providers that offer performance gains for specific algorithms but are not the best performing provider for other algorithms. More flexibility is required for configuring the ordering of provider list to achieve performance gains.

The jdk.security.provider.preferred security property allows specific algorithms, or service types to be selected from a preferred set of providers before accessing the list of registered providers. See How to Specify a java.security.Security Property.

The jdk.security.provider.preferred security property does not register the providers. The ordered provider list must be Registering the Cryptographic Provider Statically using the security.provider.n property. Any provider that is not registered is ignored.

Specifying the Preferred Provider for an Algorithm

The syntax for specifying the preferred providers string in the jdk.security.provider.preferred security property is a comma-separated list of ServiceType.Algorithm:Provider

In this syntax:

ServiceType

The name of the service type. (for example: "MessageDigest")ServiceType is optional. If it isn’t specified, the algorithm applies to all service types.

Algorithm

The standard algorithm name. See Java Cryptography Architecture Standard Algorithm Name Documentation. Algorithms can be specified as full standard name, (AES/CBC/PKCS5Padding) or as partial (AES, AES/CBC, AES//PKCS5Padding).

Provider

The name of the provider. Any provider that isn’t listed in the registered list will be ignored. See Oracle Providers.

Entries containing errors such as parsing errors are ignored. Use the command java -Djava.security.debug=jca to debug errors.

Preferred Providers and FIPS

If you add a FIPS provider to the security.provider.n property, and specify the preferred provider ordering in the jdk.security.provider.preferred property then the preferred providers specified in jdk.security.provider.preferred are selected first.

Hence, it is recommended that you don’t configure jdk.security.provider.preferred property for FIPS provider configurations.

Note:

The jdk.security.provider.preferred property doesn’t override the SunJSSE provider when it is configured in FIPS mode.

jdk.security.provider.preferred Default Values

The jdk.security.provider.preferred property is not set by default and is used only for application performance tuning.

Example 3-23 Sample jdk.security.provider.preferred Property

The syntax for specifying the jdk.security.provider.preferred property is as follows:

jdk.security.provider.preferred=AES/GCM/NoPadding:SunJCE, MessageDigest.SHA-256:SUN

In this syntax:
ServiceType
MessageDigest
Algorithm
AES/GCM/NoPadding, SHA-256
Provider
SunJCE, SUN

Customizing the Default Key Managers and Trust Managers

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.

As noted in Customizing the Default Keystores and Truststores, 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 an implementation for managing the specified keystore or truststore, as described in the aforementioned section.

The KeyManager implementation chosen is determined by first examining the ssl.KeyManagerFactory.algorithm security property. If such a property value is specified, then 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 KeyManager objects, one KeyManager for each type of key material. If no such security property value is specified, then 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 that it specifies is a javax.net.ssl.X509KeyManager implementation.

Similarly, the TrustManager implementation chosen is determined by first examining the ssl.TrustManagerFactory.algorithm security property. If such a property value is specified, then 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 TrustManager objects, one TrustManager for each type of trust material. If no such security property value is specified, then the default value of PKIX is used to perform the search.

Note:

A TrustManagerFactory implementation for the PKIX algorithm is supplied by the SunJSSE provider. The TrustManager that it specifies is a javax.net.ssl.X509TrustManager implementation.

Note:

This section describes the current JSSE 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 implementations. If they are examined by an implementation, then that implementation should handle them in the same manner as the JSSE reference implementation does, as described herein.

Disabling or Restricting Cryptographic Algorithms

The cryptographic hash algorithm MD2 is no longer considered secure. Java SE 7 included two new security properties and a new API that support disabling specific cryptographic algorithms.

The jdk.tls.disabledAlgorithms property applies to TLS handshaking, whereas the jdk.certpath.disabledAlgorithms property applies to certification path processing.

Starting with JDK 8u31, SSLv3 is disabled by default and the default value of the Security property jdk.tls.disabledAlgorithms is now as follows:

jdk.tls.disabledAlgorithms=SSLv3

If SSLv3 is absolutely required, the protocol can be reactivated by removing "SSLv3" from the jdk.tls.disabledAlgorithms property in the java.security file or by dynamically setting this Security property before JSSE is initialized.

From JDK 8 onwards, the default value of jdk.certpath.disabledAlgorithms includes RSA keySize less than 1024. This means the use of certificates with RSA key size less than 1024 bits in length is restricted. The default value of jdk.certpath.disabledAlgorithms is now as follows:

    jdk.certpath.disabledAlgorithms=MD2, RSA keySize < 1024

This means that any certificate signed with MD2 or with a RSA key of size less than 1024, is not acceptable.

Each security property contains a list of cryptographic algorithms that will not be used during certification path processing. The exact syntax of the properties is described in the java-home/conf/security/java.security file, but is briefly summarized here. The algorithm names are separated by commas. Furthermore, you can also specify certain key sizes that cannot be used.

For example, the following line in java.security specifies that the MD2 and DSA algorithms must not be used for certification path processing, and RSA is disabled for key sizes less than 2048 bits.

    jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048

Customizing the Encryption Algorithm Providers

The SunJSSE provider uses the SunJCE implementation for all its cryptographic needs. Although it is recommended that you leave the provider at its regular position, you can use implementations from other JCA or JCE providers by registering them before the SunJCE provider.

The Providerclass can be used to configure providers, either statically via the security properties file <java-home>/conf/security/java.security, or dynamically via the addProvider() or insertProviderAt() method in the java.security.Security class.

Customizing Size of Ephemeral Diffie-Hellman Keys

In SSL/TLS/DTLS connections, ephemeral Diffie-Hellman (DH) keys may be used internally during the handshaking. The SunJSSE provider provides a flexible approach to customize the strength of the ephemeral DH key size during SSL/TLS/DTLS handshaking.

Diffie-Hellman (DH) keys of sizes less than 1024 bits have been deprecated because of their insufficient strength. You can customize the ephemeral DH key size with the system property jdk.tls.ephemeralDHKeySize. This system property does not impact DH key sizes in ServerKeyExchange messages for exportable cipher suites. It impacts only the DHE_RSA, DHE_DSS, and DH_anon-based cipher suites in the JSSE Oracle provider.

You can specify one of the following values for this property:

  • Undefined: A DH key of size 1024 bits will be used always for non-exportable cipher suites. This is the default value for this property.
  • legacy: The JSSE Oracle provider preserves the legacy behavior (for example, using ephemeral DH keys of sizes 512 bits and 768 bits) of JDK 7 and earlier releases.
  • matched: For non-exportable anonymous cipher suites, the DH key size in ServerKeyExchange messages is 1024 bits. For X.509 certificate based authentication (of non-exportable cipher suites), the DH key size matching the corresponding authentication key is used, except that the size must be between 1024 bits and 2048 bits. For example, if the public key size of an authentication certificate is 2048 bits, then the ephemeral DH key size should be 2048 bits unless the cipher suite is exportable. This key sizing scheme keeps the cryptographic strength consistent between authentication keys and key-exchange keys.
  • A valid integer between 1024 and 2048, inclusively: A fixed ephemeral DH key size of the specified value, in bits, will be used for non-exportable cipher suites.

The following table summaries the minimum and maximum acceptable DH key sizes for each of the possible values for the system property jdk.tls.ephemeralDHKeySize:

Table 3-7 DH Key Sizes for the System Property jdk.tls.ephemeralDHKeySize

Value of jdk.tls.ephemeralDHKeySize Undefined legacy matched Integer value (fixed)
Exportable DH key size 512 512 512 512
Non-exportable anonymous cipher suites 1024 768 1024 The fixed key size is specified by a valid integer property value, which must be between 1024 and 2048, inclusively.
Authentication certificate 1024 768 The key size is the same as the authentication certificate, but must be between 1024 bits and 2048 bits, inclusively. However, the SunJCE provider only supports 2048-bit DH keys larger than 1024 bits. Consequently, you may use the values 1024 or 2048 only. The fixed key size is specified by a valid integer property value, which must be between 1024 and 2048, inclusively.

Customizing Maximum Fragment Length Negotiation (MFLN) Extension

In order to negotiate smaller maximum fragment lengths, clients have an option to include an extension of type max_fragment_length in the ClientHello message. A system property jsse.enableMFLNExtension, can be used to enable or disable the MFLN extension for SSL/TLS/DTLS.

Maximum Fragment Length Negotiation

It may be desirable for constrained SSL/TLS/DTLS clients to negotiate a smaller maximum fragment length due to memory limitations or bandwidth limitations. In order to negotiate smaller maximum fragment lengths, clients have an option to include an extension of type max_fragment_length in the (extended) ClientHello message. See RFC 6066.

Once a maximum fragment length has been successfully negotiated, the SSL/TLS/DTLS client and server can immediately begin fragmenting messages (including handshake messages) to ensure that no fragment larger than the negotiated length is sent.

System Property jsse.enableMFLNExtension

A system property jsse.enableMFLNExtension is defined to enable or disable the MFLN extension. The jsse.enableMFLNExtension is disabled by default.

The value of the system property can be set as follows:

Table 3-8 jsse.enableMFLNExtension system property

System Property Description
jsse.enableMFLNExtension=true Enable the MFLN extension. If the returned value of SSLParameters.getMaximumPacketSize() is less than (2^12 + header-size) the maximum fragment length negotiation extension would be enabled.  
jsse.enableMFLNExtension=false Disable the MFLN extension.

Configuring the Maximum and Minimum Packet Size

Use the SSLParameters.setMaximumPacketSize method to set the maximum expected network packet size in bytes for SSL/TLS/DTLS.

The SSLParameters.setMaximumPacketSize method is used to set the maximum expected network packet size in bytes for a SSL/TLS/DTLS record.

It is recommended that the packet size should not be less than 256 bytes so that small handshake messages, such as HelloVerifyRequests, are not fragmented.

Transport Layer Security (TLS) Renegotiation Issue

SSL/TLS renegotiations are vulnerable for man-in-the-middle (MITM) attacks . RFC 5746 specified a TLS extension to fix the renegotiation protocol flaw. The JSSE implementation enables renegotiations by default for connections compliant with RFC 5746 and provides interoperability modes for connections that are not upgraded to support the protocol fix.

In the fall of 2009, a flaw was discovered in the SSL/TLS protocols. A fix to the protocol was developed by the IETF TLS Working Group, and current version of the JDK contains this fix.

The vulnerability allowed . This vulnerability did not allow an attacker to decrypt or modify the intercepted network communication once the client and server have successfully negotiated a session between themselves.

Refer to the following links to know more about the SSL/TLS vulnerability:

Phased Approach to Fixing This Issue

The fix for this issue was handled in two phases:

  • Phase 1: Until a protocol fix could be developed, an interim fix that disabled SSL/TLS renegotiations by default was made available in the March 30, 2010 Java SE and Java for Business Critical Patch Update.

  • Phase 2: The IETF issued RFC 5746, which addresses the renegotiation protocol flaw. The following table lists the JDK and JRE releases that include the fix which implements RFC 5746 and supports secure renegotiation.

    Table 3-9 JDK and JRE Releases With Fixes to the TLS Renegotiation Issue

    JDK Family Vulnerable Releases Phase 1 Fix (Disable Renegotiations) Phase 2 Fix (RFC 5746)
    JDK and JRE 6 Update 18 and earlier Updates 19 through 21 Update 22
    JDK and JRE 5.0 Update 23 and earlier Updates 24 through 25 Update 26
    JDK and JRE 1.4.2 Update 25 and earlier Updates 26 through 27 Update 28

Note:

Applications that do not require renegotiations are not affected by the Phase 2 default configuration. However applications that require renegotiations (for example, web servers that initially allow for anonymous client browsing, but later require SSL/TLS authenticated clients):
  • Are not affected if the peer is also compliant with RFC 5746
  • Are affected if the peer has not been upgraded to RFC 5746 (see next section for details)

Description of the Phase 2 Fix

The SunJSSE implementation reenables renegotiations by default for connections to peers compliant with RFC 5746. That is, both the client and server must support RFC 5746 in order to securely renegotiate. SunJSSE provides some interoperability modes for connections with peers that have not been upgraded, but users are strongly encouraged to update both their client and server implementations as soon as possible.

With the Phase 2 fix, SunJSSE has three renegotiation interoperability modes. Each mode fully supports the RFC 5746 secure renegotiation, but has these added semantics when communicating with a peer that has not been upgraded:

  • Strict mode: Requires both client and server be upgraded to RFC 5746 and to send the proper RFC 5746 messages. If not, the initial (or subsequent) handshaking will fail and the connection will be terminated.

  • Interoperable mode (default): Use of the proper RFC 5746 messages is optional; however, legacy (original SSL/TLS specifications) renegotiations are disabled if the proper messages are not used. Initial legacy connections are still allowed, but legacy renegotiations are disabled. This is the best mix of security and interoperability, and is the default setting.

  • Insecure mode: Permits full legacy renegotiation. Most interoperable with legacy peers but vulnerable to the original MITM attack.

The three mode distinctions only affect a connection with a peer that has not been upgraded. Ideally, strict (full RFC 5746) mode should be used for all clients and servers; however, it will take some time for all deployed SSL/TLS implementations to support RFC 5746, because the interoperable mode is the current default.

The following table contains interoperability information about the modes for various cases in which the client and/or server are either updated to support RFC 5746 or not.

Table 3-10 Interoperability Information

Client Server Mode
Updated Updated Secure renegotiation in all modes.
Legacy [1] Updated
  • Strict If clients do not send the proper RFC 5746 messages, then initial connections will immediately be terminated by the server (SSLHandshakeException or handshake_failure).
  • Interoperable Initial connections from legacy clients are allowed (missing RFC 5746 messages), but renegotiations will not be allowed by the server. [3] [2]
  • Insecure Connections and renegotiations with legacy clients are allowed, but are vulnerable to the original MITM attack.
Updated Legacy [1]
  • Strict If the server does not respond with the proper RFC 5746 messages, then the client will immediately terminate the connection (SSLHandshakeException or handshake_failure).
  • Interoperable Initial connections from legacy servers are allowed (missing RFC 5746 messages), but renegotiations will not be allowed by the server. [2] [3]
  • Insecure Connections and renegotiations with legacy servers are allowed, but are vulnerable to the original MITM attack.
Legacy [1] Legacy [1] Existing SSL/TLS behavior, vulnerable to the MITM attack.

Footnote [1] "Legacy" means the original SSL/TLS specifications (that is, not RFC 5746).

Footnote [2] SunJSSE Phase 1 implementations reject renegotiations unless specifically reenabled. If renegotiations are reenabled, then they will be treated as "Legacy" by the peer that is compliant with RFC 5746, because they do not send the proper RFC 5746 messages.

Footnote [3] In SSL/TLS, renegotiations can be initiated by either side. Like the Phase 1 fix, applications communicating with a peer that has not been upgraded in Interoperable mode and that attempt to initiate renegotiation (via SSLSocket.startHandshake() or SSLEngine.beginHandshake()) will receive an SSLHandshakeException (IOException) and the connection will be shut down (handshake_failure). Applications that receive a renegotiation request from a peer that has not been upgraded will respond according to the type of connection in place:
  • TLSv1 A warning alert message of type no_renegotiation(100) will be sent to the peer and the connection will remain open. Older versions of SunJSSE will shut down the connection when a no_renegotiation alert is received.
  • SSLv3 The application will receive an SSLHandshakeException, and the connection will be closed (handshake_failure). The no_renegotiation alert is not defined in the SSLv3 specification.

The following system properties are used to set the mode:

  • sun.security.ssl.allowUnsafeRenegotiation (introduced in Phase 1) controls whether legacy (unsafe) renegotiations are permitted.
  • sun.security.ssl.allowLegacyHelloMessages (introduced in Phase 2) allows the peer to perform the handshake process without requiring the proper RFC 5746 messages.

Note:

The system properties sun.security.ssl.allowUnsafeRenegotiation and sun.security.ssl.allowLegacyHelloMessages are deprecated and might be removed in a future JDK release.

Table 3-11 Values of the System Properties for Setting the Interoperability Mode

Mode allowLegacyHelloMessages allowUnsafeRenegotiation
Strict false false
Interoperable (default) true false
Insecure true true

Caution:

Do not reenable the insecure SSL/TLS renegotiation, as this would reestablish the vulnerability.

See How to Specify a java.lang.System Property.

Workarounds and Alternatives to SSL/TLS Renegotiation

All peers should be updated to RFC 5746-compliant implementation as soon as possible. Even with this RFC 5746 fix, communications with peers that have not been upgraded will be affected if a renegotiation is necessary. Here are a few suggested options:

  • Restructure the peer to not require renegotiation.

    Renegotiations are typically used by web servers that initially allow for anonymous client browsing but later require SSL/TLS authenticated clients, or that may initially allow weak cipher suites but later need stronger ones. The alternative is to require client authentication or strong cipher suites during the initial negotiation. There are a couple of options for doing so:

    • If an application has a browse mode until a certain point is reached and a renegotiation is required, then you can restructure the server to eliminate the browse mode and require all initial connections be strong.

    • Break the server into two entities, with the browse mode occurring on one entity, and using a second entity for the more secure mode. When the renegotiation point is reached, transfer any relevant information between the servers.

    Both of these options require a fair amount of work, but will not reopen the original security flaw.

  • Set renegotiation interoperability mode to "insecure" using the system properties.

    See Description of the Phase 2 Fix.

Implementation Details

RFC 5746 defines two new data structures, which are mentioned here for advanced users:

  • A pseudo-cipher suite called the Signaling Cipher Suite Value (SCSV), "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
  • A TLS extension called the Renegotiation Info (RI).

Either of these can be used to signal that an implementation is RFC 5746-compliant and can perform secure renegotiations. See IETF email discussion from November 2009 to February 2010.

RFC 5746 enables clients to send either an SCSV or RI in the first ClientHello. For maximum interoperability, SunJSSE uses the SCSV by default, as a few TLS/SSL servers do not handle unknown extensions correctly. The presence of the SCSV in the enabled cipher suites (SSLSocket.setEnabledCipherSuites() or SSLEngine.setEnabledCipherSuites()) determines whether the SCSV is sent in the initial ClientHello, or if an RI should be sent instead.

SSLv2 does not support SSL/TLS extensions. If the SSLv2Hello protocol is enabled, then the SCSV is sent in the initial ClientHello.

Description of the Phase 1 fix

As previously mentioned, the Phase 1 Fix was to disable renegotiations by default until a fix compliant with RFC 5746 could be developed. Renegotiations could be reenabled by setting the sun.security.ssl.allowUnsafeRenegotiation system property. The Phase 2 fix uses the same sun.security.ssl.allowUnsafeRenegotiation system property, but also requires it to use RFC 5746 messages.

All applications should upgrade to the Phase 2 RFC 5746 fix as soon as possible.

Note:

The system properties sun.security.ssl.allowUnsafeRenegotiation and sun.security.ssl.allowLegacyHelloMessages are deprecated and might be removed in a future JDK release.

Allow Unsafe Server Certificate Change in SSL/TLS renegotiations

Server certificate change in an SSL/TLS renegotiation may be unsafe:

  • If endpoint identification is not enabled in an SSL/TLS handshaking; and

  • If the previous handshake is a session-resumption abbreviated initial handshake; and

  • If the identities represented by both certificates can be regarded as different.

Two certificates can be considered to represent the same identity:

  • If the subject alternative names of IP address are present in both certificates, they should be identical; otherwise,

  • If the subject alternative names of DNS name are present in both certificates, they should be identical; otherwise,

  • If the subject fields are present in both certificates, the certificate subjects and issuers should be identical.

Starting with JDK 8u25, unsafe server certificate change in SSL/TLS renegotiations is not allowed by default. The new system property jdk.tls.allowUnsafeServerCertChange, can be used to define whether unsafe server certificate change in an SSL/TLS renegotiation should be restricted or not.

The default value of this system property is "false".

Caution:

DO NOT set the system property to "true" unless it is really necessary, as this would re-establish the unsafe server certificate change vulnerability.

Hardware Acceleration and Smartcard Support

The SunJSSE provider uses JCA exclusively for all of its cryptographic operations and can automatically take advantage of JCE features.

The  Java Cryptography Architecture (JCA) is a set of packages that provides a framework and implementations for encryption, key generation and key agreement, and message authentication code (MAC) algorithms. The SunJSSE provider uses JCA exclusively for all of its cryptographic operations and can automatically take advantage of JCE features and enhancements, including JCA's support for RSA PKCS#11. This support enables the SunJSSE provider to use hardware cryptographic accelerators for significant performance improvements and to use smartcards as keystores for greater flexibility in key and trust management.

Use of hardware cryptographic accelerators is automatic if JCA has been configured to use the Oracle PKCS#11 provider, which in turn has been configured to use the underlying accelerator hardware. The provider must be configured before any other JCA providers in the provider list. For details on how to configure the Oracle PKCS#11 provider, see PKCS#11 Reference Guide.

Configuring JSSE to Use Smartcards as Keystores and Truststores

Support for PKCS#11 in JCA also enables access to smartcards as a keystore. For details on how to configure the type and location of the keystores to be used by JSSE, see Customizing JSSE. To use a smartcard as a keystore or truststore, set the javax.net.ssl.keyStoreType and javax.net.ssl.trustStoreType system properties, respectively, to pkcs11, and set the javax.net.ssl.keyStore and javax.net.ssl.trustStore system properties, respectively, to NONE. To specify the use of a specific provider, use the javax.net.ssl.keyStoreProvider and javax.net.ssl.trustStoreProvider system properties (for example, set them to SunPKCS11-joe). By using these properties, you can configure an application that previously depended on these properties to access a file-based keystore to use a smartcard keystore with no changes to the application.

Some applications request the use of keystores programmatically. These applications can continue to use the existing APIs to instantiate a Keystore and pass it to its key manager and trust manager. If the Keystore instance refers to a PKCS#11 keystore backed by a Smartcard, then the JSSE application will have access to the keys on the smartcard.

Multiple and Dynamic Keystores

Smartcards (and other removable tokens) have additional requirements for an X509KeyManager. Different smartcards can be present in a smartcard reader during the lifetime of a Java application, and they can be protected using different passwords.

The KeyStore.Builder class abstracts the construction and initialization of a KeyStore object. It supports the use of CallbackHandler for password prompting, and its subclasses can be used to support additional features as desired by an application. For example, it is possible to implement a Builder that allows individual KeyStore entries to be protected with different passwords. The KeyStoreBuilderParameters class then can be used to initialize a KeyManagerFactory using one or more of these Builder objects.

A X509KeyManager implementation in the SunJSSE provider called NewSunX509 supports these parameters. If multiple certificates are available, it attempts to pick a certificate with the appropriate key usage and prefers valid to expired certificates.

Example 3-24illustrates how to tell JSSE to use both a PKCS#11 keystore (which might in turn use a smartcard) and a PKCS#12 file-based keystore.

Example 3-24 Sample Code to Use PKCS#11 and PKCS#12 File-based Keystore

The following code sample illustrates how to tell JSSE to use both a PKCS#11 keystore (which might in turn use a smartcard) and a PKCS#12 file-based keystore:

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

// Specify keystore builder parameters for PKCS#11 keystores
Builder scBuilder = Builder.newInstance("PKCS11", null,
    new CallbackHandlerProtection(myGuiCallbackHandler));

// Specify keystore builder parameters for a specific PKCS#12 keystore
Builder fsBuilder = Builder.newInstance("PKCS12", null,
    new File(pkcsFileName), new PasswordProtection(pkcsKsPassword));

// Wrap them as key manager parameters
ManagerFactoryParameters ksParams = new KeyStoreBuilderParameters(
    Arrays.asList(new Builder[] { scBuilder, fsBuilder }) );

// Create KeyManagerFactory
KeyManagerFactory factory = KeyManagerFactory.getInstance("NewSunX509");

// Pass builder parameters to factory
factory.init(ksParams);

// Use factory
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(factory.getKeyManagers(), null, null);

Kerberos Cipher Suites

The SunJSSE provider has support for Kerberos cipher suites. Setup your Kerberos infrastructure in your deployment environment and configure such that it communicates with the TLS/DTLS client application.

The SunJSSE provider has support for Kerberos cipher suites, as described in RFC 2712. The following cipher suites are supported but not enabled by default:

Note:

According to DTLS Version 1.0 and DTLS Version 1.2, RC4 cipher suites must not be used with DTLS.
  • TLS_KRB5_WITH_RC4_128_SHA
  • TLS_KRB5_WITH_RC4_128_MD5
  • TLS_KRB5_WITH_3DES_EDE_CBC_SHA
  • TLS_KRB5_WITH_3DES_EDE_CBC_MD5
  • TLS_KRB5_WITH_DES_CBC_SHA
  • TLS_KRB5_WITH_DES_CBC_MD5
  • TLS_KRB5_EXPORT_WITH_RC4_40_SHA
  • TLS_KRB5_EXPORT_WITH_RC4_40_MD5
  • TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
  • TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5

To enable the use of these cipher suites, you must do so explicitly. See the API documentation for SSLEngine.setEnabledCipherSuites(String[]) and SSLSocket.setEnabledCipherSuites(String[]) methods. As with all other SSL/TLS/DTLS cipher suites, if a cipher suite is not supported by the peer, then it will not be selected during cipher negotiation. Furthermore, if the application and/or server cannot acquire the necessary Kerberos credentials, then the Kerberos cipher suites also will not be selected.

The following is an example of a TLS client that will only use the TLS_KRB5_WITH_DES_CBC_SHA cipher suite:

// Create socket
SSLSocketFactory sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslSocket = (SSLSocket) sslsf.createSocket(tlsServer, serverPort);

// Enable only one cipher suite
String enabledSuites[] = { "TLS_KRB5_WITH_DES_CBC_SHA" };
sslSocket.setEnabledCipherSuites(enabledSuites);

Kerberos Requirements

You must have the Kerberos infrastructure set up in your deployment environment before you can use the Kerberos cipher suites with JSSE. In particular, both the TLS client and server must have accounts set up with the Kerberos Key Distribution Center (KDC). At runtime, if one or more of the Kerberos cipher suites have been enabled, then the TLS client and server will acquire their Kerberos credentials associated with their respective account from the KDC. For example, a TLS server running on the machine mach1.imc.org in the Kerberos realm IMC.ORG must have an account with the name host/mach1.imc.org@IMC.ORG and be configured to use the KDC for IMC.ORG. See Kerberos Requirements.

An application can acquire its Kerberos credentials by using the Java Authentication and Authorization Service (JAAS) Reference Guide and a Kerberos login module. The JDK comes with a Krb5LoginModule. You can use the Kerberos cipher suites with JSSE with or without JAAS programming, similar to how you can use the JAAS and Java GSS-API Tutorial with or without JAAS programming.

To use the Kerberos cipher suites with JSSE without JAAS programming, you must use the index names com.sun.net.ssl.server or other for the TLS server JAAS configuration entry, and com.sun.net.ssl.client or other for the TLS client, and set the javax.security.auth.useSubjectCredsOnly system property to false. For example, a TLS server that is not using JAAS programming might have the following JAAS configuration file:

    com.sun.net.ssl.server {
      com.sun.security.auth.module.Krb5LoginModule required
            principal="host/mach1.imc.org@IMC.ORG"
            useKeyTab=true
            keyTab=mach1.keytab
            storeKey=true;
    };

An example of how to use Java GSS and Kerberos without JAAS programming is described in the Krb5LoginModule. You can adapt it to use JSSE by replacing Java GSS calls with JSSE calls.

To use the Kerberos cipher suites with JAAS programming, you can use any index name because your application is responsible for creating the JAAS LoginContext using the index name, and then wrapping the JSSE calls inside of a Subject.doAs() or Subject.doAsPrivileged() call. An example of how to use JAAS with Java GSS and Kerberos is described in the Use of Java GSS-API for Secure Message Exchanges Without JAAS Programming. You can adapt it to use JSSE by replacing Java GSS calls with JSSE calls.

If you have trouble using or configuring the JSSE application to use Kerberos, see Troubleshooting in the Java GSS Tutorial.

Peer Identity Information

To determine the identity of the peer of an SSL/TLS/DTLS connection, use the getPeerPrincipal() method in the following classes:

  • javax.net.ssl.SSLSession
  • javax.net.ssl.HttpsURLConnection
  • javax.net.HandshakeCompletedEvent

Similarly, to get the identity that was sent to the peer (to identify the local entity), use the getLocalPrincipal() method in these classes. For X509-based cipher suites, these methods will return an instance of javax.security.auth.x500.X500Principal; for Kerberos cipher suites, these methods will return an instance of javax.security.auth.kerberos.KerberosPrincipal.

JSSE applications use getPeerCertificates() and similar methods in javax.net.ssl.SSLSession, javax.net.ssl.HttpsURLConnection, and javax.net.HandshakeCompletedEvent classes to obtain information about the peer. When the peer does not have any certificates, SSLPeerUnverifiedException is thrown.

If the application must determine only the identity of the peer or identity sent to the peer, then it should use the getPeerPrincipal() and getLocalPrincipal() methods, respectively. It should use getPeerCertificates() and getLocalCertificates() methods only if it must examine the contents of those certificates. Furthermore, the application must be prepared to handle the case where an authenticated peer might not have any certificate.

Security Manager

When the security manager has been enabled, in addition to the SocketPermission needed to communicate with the peer, a TLS client application that uses the Kerberos cipher suites also needs the following permission:

javax.security.auth.kerberos.ServicePermission(serverPrincipal, "initiate");

Where,

serverPrincipal
Indicates the Kerberos principal name of the TLS server that the TLS client will be communicating with (such as host/mach1.imc.org@IMC.ORG).

A TLS server application needs the following permission:

javax.security.auth.kerberos.ServicePermission(serverPrincipal, "accept");
Where,
serverPrincipal
Indicates the Kerberos principal name of the TLS server (such as host/mach1.imc.org@IMC.ORG).

If the server or client must contact the KDC (for example, if its credentials are not cached locally), then it also needs the following permission:

javax.security.auth.kerberos.ServicePermission(tgtPrincipal, "initiate");

Where,

tgtPrincipal
Indicates the principal name of the KDC (such as krbtgt/IMC.ORG@IMC.ORG).

Additional Keystore Formats (PKCS12)

The SunJSSE provider supplies a complete implementation of the PKCS12 java.security.KeyStore format for reading and writing PKCS12 files.

The PKCS#12 (Personal Information Exchange Syntax Standard) specifies a portable format for storage and/or transport of a user's private keys, certificates, miscellaneous secrets, and other items. The SunJSSE provider supplies a complete implementation of the PKCS12 java.security.KeyStore format for reading and writing PKCS12 files. This format is also supported by other toolkits and applications for importing and exporting keys and certificates, such as Netscape/Mozilla, Microsoft's Internet Explorer, and OpenSSL. For example, these implementations can export client certificates and keys into a file using the .p12 file name extension.

With the SunJSSE provider, you can access PKCS12 keys through the KeyStore API with a keystore type of PKCS12. In addition, you can list the installed keys and associated certificates by using the keytool command with the -storetype option set to pkcs12. See keytool.

Server Name Indication (SNI) Extension

The SNI extension is a feature that extends the SSL/TLS/DTLS protocols to indicate what server name the client is attempting to connect to during handshaking.

Servers can use server name indication information to decide if specific SSLSocket or SSLEngine instances should accept a connection. For example, when multiple virtual or name-based servers are hosted on a single underlying network address, the server application can use SNI information to determine whether this server is the exact server that the client wants to access. Instances of this class can be used by a server to verify the acceptable server names of a particular type, such as host names. See section 3 of TLS Extensions (RFC 6066).

Developers of client applications can explicitly set the server name indication using the SSLParameters.setServerNames(List<SNIServerName> serverNames) method. See Example 3-25.

Developers of server applications can use the SNIMatcher class to decide how to recognize server name indication. Example 3-26 and Example 3-27 illustrate this functionality:

Example 3-25 Sample Code to Set the Server Name Indication

The following code sample illustrates how to set the server name indication using the SSLParameters.setServerNames(List<SNIServerName> serverNames):

 
SSLSocketFactory factory = ...
SSLSocket sslSocket = factory.createSocket("172.16.10.6", 443);
// SSLEngine sslEngine = sslContext.createSSLEngine("172.16.10.6", 443);

SNIHostName serverName = new SNIHostName("www.example.com");
List<SNIServerName> serverNames = new ArrayList<>(1);
serverNames.add(serverName);

SSLParameters params = sslSocket.getSSLParameters();
params.setServerNames(serverNames);
sslSocket.setSSLParameters(params);
// sslEngine.setSSLParameters(params);

Example 3-26 Sample Code Using SSLSocket Class to Recognize SNI

The following code sample illustrates how the server applications can use the SNIMatcher class to decide how to recognize server name indication:

 
SSLSocket sslSocket = sslServerSocket.accept();

SNIMatcher matcher = SNIHostName.createSNIMatcher("www\\.example\\.(com|org)");
Collection<SNIMatcher> matchers = new ArrayList<>(1);
matchers.add(matcher);

SSLParameters params = sslSocket.getSSLParameters();
params.setSNIMatchers(matchers);
sslSocket.setSSLParameters(params);

Example 3-27 Sample Code Using SSLServerSocket Class to Recognize SNI

The following code sample illustrates how the server applications can use the SNIMatcher class to decide how to recognize server name indication:

 
SSLServerSocket sslServerSocket = ...;

SNIMatcher matcher = SNIHostName.createSNIMatcher("www\\.example\\.(com|org)");
Collection<SNIMatcher> matchers = new ArrayList<>(1);
matchers.add(matcher);

SSLParameters params = sslServerSocket.getSSLParameters();
params.setSNIMatchers(matchers);
sslServerSocket.setSSLParameters(params);

SSLSocket sslSocket = sslServerSocket.accept();

The following list provides examples for the behavior of the SNIMatcher when receiving various server name indication requests in the ClientHello message:

  • Matcher configured to www\\.example\\.com:

    • If the requested host name is www.example.com, then it will be accepted and a confirmation will be sent in the ServerHello message.
    • If the requested host name is www.example.org, then it will be rejected with an unrecognized_name fatal error.
    • If there is no requested host name or it is empty, then the request will be accepted but no confirmation will be sent in the ServerHello message.
  • Matcher configured to www\\.invalid\\.com:

    • If the requested host name is www.example.com, then it will be rejected with an unrecognized_name fatal error.
    • If the requested host name is www.example.org, then it will be accepted and a confirmation will be sent in the ServerHello message.
    • If there is no requested host name or it is empty, then the request will be accepted but no confirmation will be sent in the ServerHello message.
  • Matcher is not configured:

    Any requested host name will be accepted but no confirmation will be sent in the ServerHello message.

For descriptions of new classes that implement the SNI extension, see:

For examples, see Using the Server Name Indication (SNI) Extension.

Code Examples

Code samples that illustrate how to set up JSSE secure or insecure socket connections, how to use JSSE, how to use keytool utility to create a keystore suitable for JSSE, and using SNI extension.

Converting an Unsecure Socket to a Secure Socket

Code examples that illustrate how to use JSSE to convert an unsecure socket connection to a secure socket connection. The code samples are excerpted from the book Java SE 6 Network Security by Marco Pistoia, et. al.

Example 3-28 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 Example 3-29 to use JSSE to set up secure socket communication.

Example 3-28 Socket Example Without SSL

The following examples demonstrates server-side and client-side code for setting up an unsecure socket connection.

In 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) { }

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) { }

Example 3-29 Socket Example with SSL

The following examples demonstrate server-side and client-side code for setting up a secure socket connection.

In 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) {
    }

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 {
        SSLSocketFactory 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 Sample Code

The JSSE sample programs that illustrate how to use JSSE.

When you use 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 you run the programs, be patient: you may not see any output for a while. If you run the programs with the javax.net.debug system property set to all, you will see more feedback. For an introduction to reading this debug information, see the guide, Debugging SSL/TLS Connections.

Where to Find the Sample Code

The JSSE Sample Code page lists all the sample code files and text files. That page also provides a link to a ZIP file that you can download to obtain all the sample code files.

The following sections describe the samples. See README.txt in JSSE Sample Code.

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

The sample programs in the samples/sockets directory 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 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 in the samples/sockets/client directory (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 to run URLReader, SSLSocketClient, or SSLSocketClientWithTunneling with ClassFileServer.

If an authentication error occurs during communication 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). See Terms and Definitions. For example, the ClassFileServer uses a keystore called testkeys containing the private key for localhost as needed during the SSL handshake. The testkeys keystore is included in the same samples/sockets/server directory as the ClassFileServer source. If the client cannot find a certificate for the corresponding public key of localhost in the truststore it consults, then an authentication error will occur. Be sure to use the samplecacerts truststore (which contains the public key and certificate of the localhost), 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 from the samples directory. Using this certificates file will allow the client to authenticate the server. The file contains all the common Certificate Authority (CA) certificates shipped with the JDK (in the cacerts file), plus a certificate for localhost needed by the client to authenticate localhost when communicating with the sample server ClassFileServer. The ClassFileServer uses a keystore containing the private key for localhost that 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 to 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

To know more about java-home, see Terms and Definitions.

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

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, then 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.

For client authentication, a separate duke certificate is available in the appropriate directories. The public key and certificate is also stored in the samplecacerts file.

Running SSLSocketClient

The SSLSocketClient.java in JSSE Sample Code program demonstrates how to create a client that uses 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 https://www.verisign.com/index.html.

You must not be behind a firewall to run this program as provided. If you run it from behind a firewall, you will get an UnknownHostException because JSSE cannot 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

The SSLSocketClientWithTunneling.java in JSSE Sample Code program 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:

java -Dhttps.proxyHost=webproxy
-Dhttps.proxyPort=ProxyPortNumber
SSLSocketClientWithTunneling

Note:

Proxy specifications with the -D options are optional. 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 https://www.verisign.com/index.html.

Running SSLSocketClientWithClientAuth

The SSLSocketClientWithClientAuth.java in JSSE Sample Code program 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 https://www.verisign.com/. The output when using these parameters is the HTML for the website https://www.verisign.com/.

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 sections.

Running ClassFileServer

The program referred to herein as ClassFileServer is made up of two files: ClassFileServer.java and ClassServer.java in JSSE Sample Code.

To execute them, run ClassFileServer.class, which requires the following parameters:

  • port can be any available unused port number, for example, you can use the number 2001.
  • docroot indicates the directory on the server that contains the file you want to retrieve. For example, on Solaris, you can use /home/userid/ (where userid refers to your particular UID), whereas on Microsoft Windows systems, you can use c:\.
  • TLS is an optional parameter that indicates that the server is to use SSL or TLS.
  • true is an optional parameter that indicates that client authentication is required. This parameter is only consulted if the TLS parameter is set.

Note:

The TLS and true parameters are optional. If you omit them, indicating that an ordinary (not TLS) file server should be used, without authentication, then nothing happens. This is because one side (the client) is trying to negotiate with TLS, while the other (the server) is not, so they cannot communicate.

Note:

The server expects GET requests in the form GET /path_to_file.

Running SSLSocketClientWithClientAuth with ClassFileServer

You can use the sample programs SSLSocketClientWithClientAuth.java and ClassFileServer in JSSE Sample Code 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.

    See Running ClassFileServer.

  2. Run the program SSLSocketClientWithClientAuth on another machine or terminal window. SSLSocketClientWithClientAuth requires the following parameters:
    • host is the host name of the machine that you are using to run ClassFileServer.
    • port is the same port that you specified for ClassFileServer.
    • requestedfilepath indicates the path to the file that 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 follows:

                                      "GET " + requestedfilepath + " HTTP/1.0"
                                      
      

Note:

You can modify the other SSLClient* applications' 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 that 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 is https://www.verisign.com.

The trust and key management for the HTTPS URL implementation is environment-specific. The JSSE implementation provides an HTTPS URL implementation. To use a different HTTPS protocol implementation, set the java.protocol.handler.pkgs. See How to Specify a java.lang.System Property to the package name. See the java.net.URL class documentation for details.

The samples that you can download with JSSE include two sample programs that illustrate how to create an HTTPS connection. Both of these sample programs (URLReader.java and URLReaderWithOptions.java ) are in the samples/urls directory.

Running URLReader

The URLReader.java in JSSE Sample Code program illustrates using the URL class to access a secure site. The output of this program is the HTML source for https://www.verisign.com/. By default, the HTTPS protocol implementation included with JSSE is used. To use a different implementation, set the system property java.protocol.handler.pkgs value to be the name of the package containing the implementation.

If you are running the sample code behind a firewall, then you must set the https.proxyHost and https.proxyPort system properties. For example, to use the proxy host "webproxy" on port 8080, you can use the following options for 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.ABC.myhttpsprotocol");

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

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

Running URLReaderWithOptions

The URLReaderWithOptions.java in JSSE Sample Code program is essentially the same as the URLReader.java program, 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, enter the following command:

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

Note:

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

You need a protocolhandlerpkgs argument only if you want to use an HTTPS protocol handler implementation other than the default one provided by Oracle.

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

Here is an example of running URLReaderWithOptions and specifying the proxy host "webproxy" on port 8080:

java URLReaderWithOptions -h webproxy -p 8080

Sample Code Illustrating a Secure RMI Connection

The sample code in the samples/rmi directory illustrates how to create a secure Java Remote Method Invocation (RMI) connection. The sample code is basically a “Hello World" example modified to install and use a custom RMI socket factory.

Sample Code Illustrating the Use of an SSLEngine

SSLEngine gives application developers flexibility when choosing I/O and compute strategies. Rather than tie the SSL/TLS implementation to a specific I/O abstraction (such as single-threaded SSLSockets), SSLEngine removes the I/O and compute constraints from the SSL/TLS implementation.

As mentioned earlier, SSLEngine is an advanced API, and is not appropriate for casual use. Some introductory sample code is provided here that helps illustrate its use. The first demo removes most of the I/O and threading issues, and focuses on many of the SSLEngine methods. The second demo is a more realistic example showing how SSLEngine might be combined with Java NIO to create a rudimentary HTTP/HTTPS server.

Running SSLEngineSimpleDemo

The SSLEngineSimpleDemo.java in JSSE Sample Code is a very simple application that focuses on the operation of the SSLEngine while simplifying the I/O and threading issues. This application creates two SSLEngine objects that exchange SSL/TLS messages via common ByteBuffer objects. A single loop serially performs all of the engine operations and demonstrates how a secure connection is established (handshaking), how application data is transferred, and how the engine is closed.

The SSLEngineResult provides a great deal of information about the current state of the SSLEngine. This example does not examine all of the states. It simplifies the I/O and threading issues to the point that this is not a good example for a production environment; nonetheless, it is useful to demonstrate the overall function of the SSLEngine.

Running the NIO-Based Server

To fully exploit the flexibility provided by SSLEngine, you must first understand complementary APIs, such as I/O and threading models.

An I/O model that large-scale application developers find of use is the NIO SocketChannel. NIO was introduced in part to solve some of the scaling problem inherent in the java.net.Socket API. SocketChannel has many different modes of operation including:

  • Blocking
  • Nonblocking
  • Nonblocking with selectors

Sample code for a basic HTTP server is provided that not only demonstrates many of the new NIO APIs, but also shows how SSLEngine can be employed to create a secure HTTPS server. The server is not production quality, but does show many of these new APIs in action.

Inside the samples directory is a README.txt file that introduces the server, explains how to build and configure the server, and provides a brief overview of the code layout. The files of most interest for SSLEngine users are ChannelIO.java and ChannelIOSecure.java.

Note:

The server example discussed in this section is included in the JDK. You can find the code bundled in the jdk-home/samples/nio/server directory.

Creating a Keystore to Use with JSSE

The procedure as to how you can use the keytool utility to create a simple PKCS12 keystore suitable for use with JSSE.

First you make a keyEntry (with public and private keys) in the keystore, and then you make a corresponding trustedCertEntry (public keys only) in a truststore. For client authentication, you follow a similar process for the client's certificates.

Note:

Storing trust anchors and secret keys in PKCS12 is supported since JDK 8.

Note:

It is beyond the scope of this example to explain each step in detail. See keytool.

User input is shown in bold.

  1. Create a new keystore and self-signed certificate with corresponding public and private keys.

        % keytool -genkeypair -alias duke -keyalg RSA -validity 7 -keystore keystore 
        
        Enter keystore password:  <password>
        What is your first and last name?
        [Unknown]:  Duke
        What is the name of your organizational unit?
        [Unknown]:  Java Software
        What is the name of your organization?
        [Unknown]:  Oracle, Inc.
        What is the name of your City or Locality?
        [Unknown]:  Palo Alto
        What is the name of your State or Province?
        [Unknown]:  CA
        What is the two-letter country code for this unit?
        [Unknown]:  US
        Is CN=Duke, OU=Java Software, O="Oracle, Inc.",
        L=Palo Alto, ST=CA, C=US correct?
        [no]:  yes
    
  2. Examine the keystore. Notice that the entry type is PrivatekeyEntry, which means that this entry has a private key associated with it).

        % keytool -list -v -keystore keystore
        
        Enter keystore password:  <password>
        
        Keystore type: PKCS12
        Keystore provider: SUN
    
        Your keystore contains 1 entry
    
        Alias name: duke
        Creation date: Jul 25, 2016
        Entry type: PrivateKeyEntry
        Certificate chain length: 1
        Certificate[1]:
        Owner: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=US
        Issuer: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=US
        Serial number: 210cccfc
        Valid from: Mon Jul 25 10:33:27 IST 2016 until: Mon Aug 01 10:33:27 IST 2016
        Certificate fingerprints:
             SHA1: 80:E5:8A:47:7E:4F:5A:70:83:97:DD:F4:DA:29:3D:15:6B:2A:45:1F
             SHA256: ED:3C:70:68:4E:86:35:9C:63:CC:B9:59:35:58:94:1F:7E:B8:B0:EE:D2:
        4B:9D:80:31:67:8A:D4:B4:7A:B5:12
        Signature algorithm name: SHA256withRSA
        Subject Public Key Algorithm: RSA (2048)
        Version: 3
    
        Extensions:
    
       #1: ObjectId: 2.5.29.14 Criticality=false
       SubjectKeyIdentifier [
       KeyIdentifier [
       0000: 7F C9 95 48 42 8D 68 91   BA 1E E6 5C 2C 6B FF 75  ...HB.h....\,k.u
       0010: 5F 19 78 43                                        _.xC
       ]
       ]
    
  3. Export and examine the self-signed certificate.

        % keytool -export -alias duke -keystore keystore -rfc -file duke.cer
        Enter keystore password:  <password>
        Certificate stored in file <duke.cer>
        % cat duke.cer
        -----BEGIN CERTIFICATE-----
        MIIDdzCCAl+gAwIBAgIEIQzM/DANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJV
        UzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0bzEVMBMGA1UEChMMT3Jh
        Y2xlLCBJbmMuMRYwFAYDVQQLEw1KYXZhIFNvZnR3YXJlMQ0wCwYDVQQDEwREdWtl
        MB4XDTE2MDcyNTA1MDMyN1oXDTE2MDgwMTA1MDMyN1owbDELMAkGA1UEBhMCVVMx
        CzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlQYWxvIEFsdG8xFTATBgNVBAoTDE9yYWNs
        ZSwgSW5jLjEWMBQGA1UECxMNSmF2YSBTb2Z0d2FyZTENMAsGA1UEAxMERHVrZTCC
        ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ7+Yeu6HDZgWwkGlG4iKH9w
        vGKrxXVR57FaFyheMevrgj1ovVnQVFhfdMvjPkjWmpqLg6rfTqU4bKbtoMWV6+Rn
        uQrCw2w9xNC93hX9PxRa20UKrSRDKnUSvi1wjlaxfj0KUKuMwbbY9S8x/naYGeTL
        lwbHiiMvkoFkP2kzhVgeqHjIwSz4HRN8vWHCwgIDFWX/ZlS+LbvB4TSZkS0ZcQUV
        vJWTocOd8RB90W3bkibWkWq166XYGE1Nq1L4WIhrVJwbav6ual69yJsEpVcshVkx
        E1WKzJg7dGb03to4agbReb6+aoCUwb2vNUudNWasSrxoEFArVFGD/ZkPT0esfqEC
        AwEAAaMhMB8wHQYDVR0OBBYEFH/JlUhCjWiRuh7mXCxr/3VfGXhDMA0GCSqGSIb3
        DQEBCwUAA4IBAQAmcTm2ahsIJLayajsvm8yPzQsHA7kIwWfPPHCoHmNbynG67oHB
        fleaNvrgm/raTT3TrqQkg0525qI6Cqaoyy8JA2fAp3i+hmyoGHaIlo14bKazaiPS
        RCCqk0J8vwY3CY9nVal1XlHJMEcYV7X1sxKbuAKFoAJ29E/p6ie0JdHtQe31M7X9
        FNLYzt8EpJYUtWo13B9Oufz/Guuex9PQ7aC93rbO32MxtnnCGMxQHlaHLLPygc/x
        cffGz5Xe5s+NEm78CY7thgN+drI7icBYmv4navsnr2OQaD3AfnJ4WYSQyyUUCPxN
        zuk+B0fbLn7PCCcQspmqfgzIpgbEM9M1/yav
        -----END CERTIFICATE-----    
    

    Alternatively, you could generate a Certificate Signing Request (CSR) with -certreq and send that to a Certificate Authority (CA) for signing, but that is beyond the scope of this example.

  4. Import the certificate into a new truststore.

        % keytool -import -alias dukecert -file duke.cer -keystore truststore
        Enter keystore password:  <password>
        Re-enter new password:
        Owner: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=US
        Issuer: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=US
        Serial number: 210cccfc
        Valid from: Mon Jul 25 10:33:27 IST 2016 until: Mon Aug 01 10:33:27 IST 2016
        Certificate fingerprints:
             SHA1: 80:E5:8A:47:7E:4F:5A:70:83:97:DD:F4:DA:29:3D:15:6B:2A:45:1F
             SHA256: ED:3C:70:68:4E:86:35:9C:63:CC:B9:59:35:58:94:1F:7E:B8:B0:EE:D2:
        4B:9D:80:31:67:8A:D4:B4:7A:B5:12
        Signature algorithm name: SHA256withRSA
        Subject Public Key Algorithm: RSA (2048)
        Version: 3
    
        Extensions:
    
        #1: ObjectId: 2.5.29.14 Criticality=false
        SubjectKeyIdentifier [
        KeyIdentifier [
        0000: 7F C9 95 48 42 8D 68 91   BA 1E E6 5C 2C 6B FF 75  ...HB.h....\,k.u
        0010: 5F 19 78 43                                        _.xC
        ]
        ]
    
        Trust this certificate? [no]:  yes
        Certificate was added to keystore
    
        
    
  5. Examine the truststore. Note that the entry type is trustedCertEntry, which means that a private key is not available for this entry. It also means that this file is not suitable as a keystore of the KeyManager.

        % keytool -list -v -keystore truststore
        Enter keystore password:  <password>
        
        Keystore type: PKCS12
        Keystore provider: SUN
        
        Your keystore contains 1 entry
    
        Alias name: dukecert
        Creation date: Jul 25, 2016
        Entry type: trustedCertEntry
    
        Owner: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=US
        Issuer: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=US
        Serial number: 210cccfc
        Valid from: Mon Jul 25 10:33:27 IST 2016 until: Mon Aug 01 10:33:27 IST 2016
        Certificate fingerprints:
             SHA1: 80:E5:8A:47:7E:4F:5A:70:83:97:DD:F4:DA:29:3D:15:6B:2A:45:1F
             SHA256: ED:3C:70:68:4E:86:35:9C:63:CC:B9:59:35:58:94:1F:7E:B8:B0:EE:D2:
        4B:9D:80:31:67:8A:D4:B4:7A:B5:12
        Signature algorithm name: SHA256withRSA
        Subject Public Key Algorithm: RSA (2048)
        Version: 3
    
        Extensions:
    
        #1: ObjectId: 2.5.29.14 Criticality=false
        SubjectKeyIdentifier [
        KeyIdentifier [
        0000: 7F C9 95 48 42 8D 68 91   BA 1E E6 5C 2C 6B FF 75  ...HB.h....\,k.u
        0010: 5F 19 78 43                                        _.xC
        ]
        ]
    
    
    
        *******************************************
        *******************************************
    
  6. Now run your applications with the appropriate keystores. Because this example assumes that the default X509KeyManager and X509TrustManager are used, you select the keystores using the system properties described in Customizing JSSE.

        % java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password Server
        
        % java -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword Client
        
    

Note:

This example authenticated the server only. For client authentication, provide a similar keystore for the client's keys and an appropriate truststore for the server.

Using the Server Name Indication (SNI) Extension

Code examples that illustrate how you can use the SNI extension for client-side and server-side applications.

Examples that illustrate how you can use the Server Name Indication (SNI) Extension for client-side and server-side applications, and how it can be applied to a virtual infrastructure.

For all examples in this section, to apply the parameters after you set them, call the setSSLParameters(SSLParameters) method on the corresponding SSLSocket, SSLEngine, or SSLServerSocket object.

Typical Client-Side Usage Examples

The following is a list of use cases that require understanding of the SNI extension for developing a client application:

  • Case 1. The client wants to access www.example.com.

    Set the host name explicitly:

        SNIHostName serverName = new SNIHostName("www.example.com");
        List<SNIServerName> serverNames = new ArrayList<>(1);
        serverNames.add(serverName);
        sslParameters.setServerNames(serverNames);
            
    

    The client should always specify the host name explicitly.

  • Case 2. The client does not want to use SNI because the server does not support it.

    Disable SNI with an empty server name list:

        List<SNIServerName> serverNames = new ArrayList<>(1);
        sslParameters.setServerNames(serverNames);
            
    
  • Case 3. The client wants to access URL https://www.example.com.

    Oracle providers will set the host name in the SNI extension by default, but third-party providers may not support the default server name indication. To keep your application provider-independent, always set the host name explicitly.

  • Case 4. The client wants to switch a socket from server mode to client mode.

    First switch the mode with the following method: sslSocket.setUseClientMode(true). Then reset the server name indication parameters on the socket.

Typical Server-Side Usage Examples

The following is a list of use cases that require understanding of the SNI extension for developing a server application:

  • Case 1. The server wants to accept all server name indication types.

    If you do not have any code dealing with the SNI extension, then the server ignores all server name indication types.

  • Case 2. The server wants to deny all server name indications of type host_name.

    Set an invalid server name pattern for host_name:

        SNIMatcher matcher = SNIHostName.createSNIMatcher("");
        Collection<SNIMatcher> matchers = new ArrayList<>(1);
        matchers.add(matcher);
        sslParameters.setSNIMatchers(matchers);
            
    

    Another way is to create an SNIMatcher subclass with a matches() method that always returns false:

        class DenialSNIMatcher extends SNIMatcher {
            DenialSNIMatcher() {
                super(StandardConstants.SNI_HOST_NAME);
            }
        
            @Override
            public boolean matches(SNIServerName serverName) {
                return false;
            }
        }
        
        SNIMatcher matcher = new DenialSNIMatcher();
        Collection<SNIMatcher> matchers = new ArrayList<>(1);
        matchers.add(matcher);
        sslParameters.setSNIMatchers(matchers);
            
    
  • Case 3. The server wants to accept connections to any host names in the example.com domain.

    Set the recognizable server name for host_name as a pattern that includes all *.example.com addresses:

        SNIMatcher matcher = SNIHostName.createSNIMatcher("(.*\\.)*example\\.com");
        Collection<SNIMatcher> matchers = new ArrayList<>(1);
        matchers.add(matcher);
        sslParameters.setSNIMatchers(matchers);
            
    
  • Case 4. The server wants to switch a socket from client mode to server mode.

    First switch the mode with the following method: sslSocket.setUseClientMode(false). Then reset the server name indication parameters on the socket.

Working with Virtual Infrastructures

This section describes how to use the Server Name Indication (SNI) extension from within a virtual infrastructure. It illustrates how to create a parser for ClientHello messages from a socket, provides examples of virtual server dispatchers using SSLSocket and SSLEngine, describes what happens when the SNI extension is not available, and demonstrates how to create a failover SSLContext.

Preparing the ClientHello Parser

Applications must implement an API to parse the ClientHello messages from a socket. The following examples illustrate the SSLCapabilities and SSLExplorer classes that can perform these functions.

SSLSocketClient.java encapsulates the SSL/TLS/DTLS security capabilities during handshaking (that is, the list of cipher suites to be accepted in an SSL/TLS/DTLS handshake, the record version, the hello version, and the server name indication). It can be retrieved by exploring the network data of an SSL/TLS/DTLS connection via the SSLExplorer.explore() method.

SSLExplorer.java explores the initial ClientHello message from a TLS client, but it does not initiate handshaking or consume network data. The SSLExplorer.explore() method parses the ClientHello message, and retrieves the security parameters into SSLCapabilities. The method must be called before handshaking occurs on any TLS connections.

Virtual Server Dispatcher Based on SSLSocket

This section describes the procedure for using a virtual server dispatcher based on SSLSocket.

  1. Register the server name handler.

    At this step, the application may create different SSLContext objects for different server name indications, or link a certain server name indication to a specified virtual machine or distributed system.

    For example, if the server name is www.example.org, then the registered server name handler may be for a local virtual hosting web service. The local virtual hosting web service will use the specified SSLContext. If the server name is www.example.com, then the registered server name handler may be for a virtual machine hosting on 10.0.0.36. The handler may map this connection to the virtual machine.

  2. Create a ServerSocket and accept the new connection.

        ServerSocket serverSocket = new ServerSocket(serverPort);
        Socket socket = serverSocket.accept();
            
    
  3. Read and buffer bytes from the socket input stream, and then explore the buffered bytes.

        InputStream ins = socket.getInputStream();
        
        byte[] buffer = new byte[0xFF];
        int position = 0;
        SSLCapabilities capabilities = null;
        
        // Read the header of TLS record
        while (position < SSLExplorer.RECORD_HEADER_SIZE) {
            int count = SSLExplorer.RECORD_HEADER_SIZE - position;
            int n = ins.read(buffer, position, count);
            if (n < 0) {
                throw new Exception("unexpected end of stream!");
            }
            position += n;
        }
        
        // Get the required size to explore the SSL capabilities
        int recordLength = SSLExplorer.getRequiredSize(buffer, 0, position);
        if (buffer.length < recordLength) {
            buffer = Arrays.copyOf(buffer, recordLength);
        }
        
        while (position < recordLength) {
            int count = recordLength - position;
            int n = ins.read(buffer, position, count);
            if (n < 0) {
                throw new Exception("unexpected end of stream!");
            }
            position += n;
        }
        
        // Explore
        capabilities = SSLExplorer.explore(buffer, 0, recordLength);
        if (capabilities != null) {
            System.out.println("Record version: " + capabilities.getRecordVersion());
            System.out.println("Hello version: " + capabilities.getHelloVersion());
        }
            
    
  4. Get the requested server name from the explored capabilities.

        List<SNIServerName> serverNames = capabilities.getServerNames();
            
    
  5. Look for the registered server name handler for this server name indication.

    If the service of the host name is resident in a virtual machine or another distributed system, then the application must forward the connection to the destination. The application will need to read and write the raw internet data, rather then the SSL application from the socket stream.

        Socket destinationSocket = new Socket(serverName, 443);
        
        // Forward buffered bytes and network data from the current socket to the destinationSocket.
            
    

    If the service of the host name is resident in the same process, and the host name service can use the SSLSocket directly, then the application will need to set the SSLSocket instance to the server:

        // Get service context from registered handler
        // or create the context
        SSLContext serviceContext = ...
        
        SSLSocketFactory serviceSocketFac = serviceContext.getSSLSocketFactory();
        
        // wrap the buffered bytes
        ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, position);
        SSLSocket serviceSocket = (SSLSocket)serviceSocketFac.createSocket(socket, bais, true);
        
        // Now the service can use serviceSocket as usual.
        
    

Virtual Server Dispatcher Based on SSLEngine

This section describes the procedure for using a virtual server dispatcher based on SSLEngine.

  1. Register the server name handler.

    At this step, the application may create different SSLContext objects for different server name indications, or link a certain server name indication to a specified virtual machine or distributed system.

    For example, if the server name is www.example.org, then the registered server name handler may be for a local virtual hosting web service. The local virtual hosting web service will use the specified SSLContext. If the server name is www.example.com, then the registered server name handler may be for a virtual machine hosting on 10.0.0.36. The handler may map this connection to the virtual machine.

  2. Create a ServerSocket or ServerSocketChannel and accept the new connection.

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(...);
        ...
        SocketChannel socketChannel = serverSocketChannel.accept();
            
    
  3. Read and buffer bytes from the socket input stream, and then explore the buffered bytes.

        ByteBuffer buffer = ByteBuffer.allocate(0xFF);
        SSLCapabilities capabilities = null;
        while (true) {
            // ensure the capacity
            if (buffer.remaining() == 0) {
                ByteBuffer oldBuffer = buffer;
                buffer = ByteBuffer.allocate(buffer.capacity() + 0xFF);
                buffer.put(oldBuffer);
            }
    
            int n = sc.read(buffer);
            if (n < 0) {
                throw new Exception("unexpected end of stream!");
            }
    
            int position = buffer.position();
            buffer.flip();
            capabilities = explorer.explore(buffer);
            buffer.rewind();
            buffer.position(position);
            buffer.limit(buffer.capacity());
            if (capabilities != null) {
                System.out.println("Record version: " +
                        capabilities.getRecordVersion());
                System.out.println("Hello version: " +
                        capabilities.getHelloVersion());
                break;
            }
        }
        buffer.flip();  // reset the buffer position and limitation 
            
    
  4. Get the requested server name from the explored capabilities.

        List<SNIServerName> serverNames = capabilities.getServerNames();
            
    
  5. Look for the registered server name handler for this server name indication.

    If the service of the host name is resident in a virtual machine or another distributed system, then the application must forward the connection to the destination. The application will need to read and write the raw internet data, rather then the SSL application from the socket stream.

        Socket destinationSocket = new Socket(serverName, 443);
        
        // Forward buffered bytes and network data from the current socket to the destinationSocket.
            
    

    If the service of the host name is resident in the same process, and the host name service can use the SSLEngine directly, then the application will simply feed the net data to the SSLEngine instance:

        // Get service context from registered handler
        // or create the context
        SSLContext serviceContext = ...
        
        SSLEngine serviceEngine = serviceContext.createSSLEngine();
    
        // Now the service can use the buffered bytes and other byte buffer as usual.
        
    

No SNI Extension Available

If there is no server name indication in a ClientHello message, then there is no way to select the proper service according to SNI. For such cases, the application may need to specify a default service, so that the connection can be delegated to it if there is no server name indication.

Failover SSLContext

The SSLExplorer.explore() method does not check the validity of SSL/TLS/DTLS contents. If the record format does not comply with SSL/TLS/DTLS specification, or the explore() method is invoked after handshaking has started, then the method may throw an IOException and be unable to produce network data. In such cases, handle the exception thrown by SSLExplorer.explore() by using a failover SSLContext, which is not used to negotiate an SSL/TLS/DTLS connection, but to close the connection with the proper alert message. The following example illustrates a failover SSLContext. You can find an example of the DenialSNIMatcher class in Case 2 of the Typical Server-Side Usage Examples.

    byte[] buffer = ...       // buffered network data
    boolean failed = true;    // SSLExplorer.explore() throws an exception
    
    SSLContext context = SSLContext.getInstance("TLS");
        // the failover SSLContext
    
    context.init(null, null, null);
    SSLSocketFactory sslsf = context.getSocketFactory();
    ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, position);
    SSLSocket sslSocket = (SSLSocket)sslsf.createSocket(socket, bais, true);
    
    SNIMatcher matcher = new DenialSNIMatcher();
    Collection<SNIMatcher> matchers = new ArrayList<>(1);
    matchers.add(matcher);
    SSLParameters params = sslSocket.getSSLParameters();
    params.setSNIMatchers(matchers);    // no recognizable server name
    sslSocket.setSSLParameters(params);
    
    try {
        InputStream sslIS = sslSocket.getInputStream();
        sslIS.read();
    } catch (Exception e) {
        System.out.println("Server exception " + e);
    } finally {
        sslSocket.close();
    }

Troubleshooting JSSE

This section contains information for troubleshooting JSSE. It provides solutions to common configuration problem.

First, it provides some common Configuration Problems and ways to solve them, and then it describes helpful Debugging Utilities.

Configuration Problems

Solutions to some common configuration problems.

CertificateException While Handshaking

CertificateException is thrown while negotiating SSL/TLS/DTLS connection.

Problem: When negotiating an SSL/TLS/DTLS connection, the client or server throws a CertificateException.

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.

Refer to the following sections:

Cause 2: The system clock is not set correctly. In this case, 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.

Solution 2: Correct the system clock time.

java.security.KeyStoreException: TrustedCertEntry Not Supported

java.security.KeyStoreException: TrustedCertEntry not supported. exception is thrown when you try to store trusted certificates.

Problem: Attempt to store trusted certificates in PKCS12 keystore throws java.security.KeyStoreException: TrustedCertEntry not supported.

Cause: Storing trusted certificates in a PKCS12 keystore is not supported. PKCS12 is mainly used to deliver private keys with the associated certificate chains. It does not have any notion of "trusted" certificates. In terms of interoperability, other PKCS12 vendors have the same restriction. Browsers such as Mozilla and Internet Explorer do not accept a PKCS12 file with only trusted certificates.

Solution: Use the JKS keystore for storing trusted certificates.

(Optional) Enter syntax information here.

Runtime Exception: SSL Service Not Available

JSSE exception indicating that an SSL service is not available.

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

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

Cause: There was a problem with SSLContext initialization, for example, due to an incorrect password on a keystore or a corrupted keystore (a JDK vendor once shipped a keystore in an unknown format, and that caused this type of error).

Solution: Check initialization parameters. Ensure that any keystores specified are valid and that the passwords specified are correct. One way that you can check this is by trying to use the Java Security Tools to examine the keystores and the relevant contents.

Runtime Exception: "No available certificate corresponding to the SSL cipher suites which are enabled"

Runtime exception encountered when you are trying to run a SSL server program.

Problem: When trying to run a simple SSL server program, the following exception is thrown:

    Exception in thread "main" javax.net.ssl.SSLException:
        No available certificate corresponding to the SSL cipher suites which are enabled...

Cause: Various cipher suites require certain types of key material. For example, if an RSA cipher suite is enabled, then an RSA keyEntry must be available in the keystore. If no such key is available, then this cipher suite cannot be used. This exception is thrown if there are no available key entries for all of the cipher suites enabled.

Solution: Create key entries for the various cipher suite types, or use an anonymous suite. Anonymous cipher suites are inherently dangerous because they are vulnerable to MITM (man-in-the-middle) attacks. See RFC 2246.

Refer to the following sections to learn how to pass the correct keystore and certificates:

Runtime Exception: No Cipher Suites in Common

The client and/or server throws the no cipher suites in common.

Problem 1: When handshaking, the client and/or server throw this exception.

Cause 1: Both sides of an SSL connection must agree on a common cipher suite. If the intersection of the client's cipher suite set with the server's cipher suite set is empty, then you will see this exception.

Solution 1: Configure the enabled cipher suites to include common cipher suites, and be sure to provide an appropriate keyEntry for asymmetric cipher suites. Also see Runtime Exception: "No available certificate corresponding to the SSL cipher suites which are enabled" in this section.)

Problem 2: When using Netscape Navigator or Microsoft Internet Explorer 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 2: By default, keyEntries created with keytool use DSA public keys. If only DSA keyEntries exist in the keystore, then only DSA-based cipher suites can be used. By default, Navigator and Internet Explorer send only RSA-based cipher suites. Because the intersection of client and server cipher suite sets is empty, this exception is thrown.

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

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

Slowness of the First JSSE Access

The first JSSE access is slow and seems to stall.

Problem: JSSE seems to stall on first access.

Cause: JSSE must have a secure source of random numbers. The initialization takes a while.

Solution: Provide an alternative generator of random numbers, or initialize ahead of time when the overhead will not be noticed:

SecureRandom sr = new SecureRandom();
sr.nextInt();
SSLContext.init(..., ..., sr);

The java-home/conf/security/java.security file also provides a way to specify the source of seed data for SecureRandom.

Code Using HttpsURLConnection Class Throws ClassCastException in JSSE 1.0.x

JSSE 1.0.x runs javax.net.ssl.HttpsURLConnection object and throws a ClassCastException.

Problem: The following code snippet was written using com.sun.net.ssl.HttpsURLConnection in JSSE 1.0.x:

import com.sun.net.ssl.*;
...deleted...
HttpsURLConnection urlc = new URL("https://example.com/").openConnection();

When running under JSSE 1.0.x, this code returns a javax.net.ssl.HttpsURLConnection object and throws a ClassCastException.

Cause: By default, opening an HTTPS URL will create a javax.net.ssl.HttpsURLConnection.

Solution: Previous releases of the JDK (release 6 and earlier) did not ship with an HTTPS URL implementation. The JSSE 1.0.x implementation did provide such an HTTPS URL handler, and the installation guide described how to set the URL handler search path to obtain a JSSE 1.0.x com.sun.net.ssl.HttpsURLConnection implementation.

In the JDK, there is a HTTPS handler in the default URL handler search path. It returns an instance of javax.net.ssl.HttpsURLConnection. By prepending the old JSSE 1.0.x implementation path to the URL search path via the java.protocol.handler.pkgs variable, you can still obtain a com.sun.net.ssl.HttpsURLConnection, and the code will no longer throw cast exceptions.

See the following examples:

    % java -Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol YourClass
    System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");

Socket Disconnected After Sending ClientHello Message

The socket is disconnected after sending ClientHello Message.

Problem: A socket attempts to connect, sends a ClientHello message, and is immediately disconnected.

Cause: Some SSL/TLS servers will disconnect if a ClientHello message is received in a format they do not understand or with a protocol version number that they do not support.

Solution: Try adjusting the enabled protocols on the client side. This involves modifying or invoking some of the following system properties and methods:

For backwards compatibility, some SSL/TLS implementations (such as SunJSSE) can send SSL/TLS ClientHello messages encapsulated in the SSLv2 ClientHello format. The SunJSSE provider supports this feature. If you want to use this feature, add the "SSLv2Hello" protocol to the enabled protocol list, if necessary. (See Protocols in the Oracle Providers, which lists the protocols that are enabled by default for the SunJSSE provider.)

The SSL/TLS RFC standards require that implementations negotiate to the latest version both sides speak, but some non-conforming implementation simply hang up if presented with a version they don't understand. For example, some older server implementations that speak only SSLv3 will shutdown if TLSv1.2 is requested. In this situation, consider using a SSL/TLS version fallback scheme:

  1. Fall back from TLSv1.2 to TLSv1.1 if the server does not understand TLSv1.2.
  2. Fall back from TLSv1.1 to TLSv1.0 if the previous step does not work.

For example, if the enabled protocol list on the client is TLSv1, TLSv1.1, and TLSv1.2, a typical SSL/TLS version fallback scheme may look like:

  1. Try to connect to server. If server rejects the SSL/TLS connection request immediately, go to step 2.
  2. Try the version fallback scheme by removing the highest protocol version (for example, TLSv1.2 for the first failure) in the enabled protocol list.
  3. Try to connect to the server again. If server rejects the connection, go to step 2 unless there is no version to which the server can fall back.
  4. If the connection fails and SSLv2Hello is not on the enabled protocol list, restore the enable protocol list and enable SSLv2Hello. (For example, the enable protocol list should be SSLv2Hello, SSLv3, TLSv1, TLSv1.1, and TLSv1.2.) Start again from step 1.

Note:

A fallback to a previous version normally means security strength downgrading to a weaker protocol. It is not suggested to use a fallback scheme unless it is really necessary, and you clearly know that the server does not support a higher protocol version.

Note:

As part of disabling SSLv3, some servers have also disabled SSLv2Hello, which means communications with SSLv2Hello-active clients (JDK 6u95 and JDK 5.0u85) will fail. Starting with JDK 7, SSLv2Hello default to disabled on clients, enabled on servers.

SunJSSE Cannot Find a JCA Provider That Supports a Required Algorithm and Causes a NoSuchAlgorithmException

SunJSSE uses JCE for all its cryptographic algorithms.

Problem: A handshake is attempted and fails when it cannot find a required algorithm. Examples might include:

Exception in thread ...deleted...
    ...deleted...
    Caused by java.security.NoSuchAlgorithmException: Cannot find any
        provider supporting RSA/ECB/PKCS1Padding

or

Caused by java.security.NoSuchAlgorithmException: Cannot find any
    provider supporting AES/CBC/NoPadding

Cause: SunJSSE uses JCE for all its cryptographic algorithms. By default, the Oracle JDK will use the Standard Extension ClassLoader to load the SunJCE provider located in java-home/lib/ext/sunjce_provider.jar. If the file cannot be found or loaded, or if the SunJCE provider has been deregistered from the Provider mechanism and an alternative implementation from JCE is not available, then this exception will be thrown.

Solution: Ensure that the SunJCE is available by checking that the file is loadable and that the provider is registered with the Provider interface. Try to run the following code in the context of your SSL connection:

import javax.crypto.*;

System.out.println("=====Where did you get AES=====");
Cipher c = Cipher.getInstance("AES/CBC/NoPadding");
System.out.println(c.getProvider());

FailedDownloadException Thrown When Trying to Obtain Application Resources from Web Server over SSL

A com.sun.deploy.net.FailedDownloadException is thrown when trying to obtain application resource from the web server over SSL.

Problem: If you receive a com.sun.deploy.net.FailedDownloadException when trying to obtain application resources from your web server over SSL, and your web server uses the virtual host with Server Name Indication (SNI) extension (such as Apache HTTP Server), then you may have not configured your web server correctly.

Cause: Because Java SE 7 supports the SNI extension in the JSSE client, the requested host name of the virtual server is included in the first message sent from the client to the server during the SSL handshake. The server may deny the client's request for a connection if the requested host name (the server name indication) does not match the expected server name, which should be specified in the virtual host's configuration. This triggers an SSL handshake unrecognized name alert, which results in a FailedDownloadException being thrown.

Solution: To better diagnose the problem, enable tracing through the Java Console. If the cause of the problem is javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name, it is likely that the virtual host configuration for SNI is incorrect. If you are using Apache HTTP Server, see Name-based Virtual Host Support about configuring virtual hosts. In particular, ensure that the ServerName directive is configured properly in a <VirtualHost> block.

See the following:

IllegalArgumentException When RC4 Cipher Suites are Configured for DTLS

In a DTLS engine, IllegalArgumentException is thrown when RC4 cipher suite algorithm is specified in SSLEngine.setEnabledCipherSuites(String[] suites) method.

Problem:

IllegalArgumentException exception is thrown when RC4 cipher suite algorithm is specified in SSLEngine.setEnabledCipherSuites(String[] suites) method, when the SSLEngine is a DTLS engine.
sslContext = SSLContext.getInstance("DTLS");

// Create the engine
SSLEngine engine = sslContext.createSSLengine(hostname, port);

String enabledSuites[] = { "SSL_RSA_WITH_RC4_128_SHA" };
engine.setEnabledCipherSuites(enabledSuites);

Cause:

According to DTLS Version 1.0 and DTLS Version 1.2, RC4 cipher suites must not be used with DTLS.

Solution:

Do not use RC4 based cipher suites for DTLS connections. See JSSE Cipher Suite Names in Java Cryptography Architecture Standard Algorithm Name Documentation.

Debugging Utilities

JSSE provides dynamic debug tracing support. This is similar to the support used for debugging access control failures in the Java SE platform.

The generic Java dynamic debug tracing support is accessed with the java.security.debug system property, whereas the JSSE-specific dynamic debug tracing support is accessed with the javax.net.debug system property.

Note:

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

To view 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.

The following complete example shows how to get a list of the debug options for an application named MyApp that uses some of the JSSE classes:

java -Djavax.net.debug=help MyApp

The MyApp application will not run after the debug help information is printed, as the help code causes the application to exit.

Current options are:

  • all: Turn on all debugging
  • ssl: Turn on SSL debugging

The following can be used with the ssl option:

  • 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

Messages generated from the handshake option can be widened with these options:

  • data: Hex dump of each handshake message
  • verbose: Verbose handshake message printing

Messages generated from the record option can be widened with these options:

  • plaintext: Hex dump of record plaintext
  • packet: Print raw SSL/TLS packets

The javax.net.debug property value must be 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 a colon (:) or a comma (,) helps readability. It does not matter what separators you use, and the ordering of the option keywords is also not important.

For an introduction to reading this debug information, see the guide, Debugging SSL/TLS Connections.

The following are examples of using the javax.net.debug property:

  • To view all debugging messages:

        java -Djavax.net.debug=all MyApp
            
    
  • To view the hexadecimal dumps of each handshake message, enter the following (the colons are optional):

        java -Djavax.net.debug=ssl:handshake:data MyApp
            
    
  • To view the hexadecimal dumps of each handshake message, and to print trust manager tracing, enter the following (the commas are optional):

        java -Djavax.net.debug=SSL,handshake,data,trustmanager MyApp
            
    

Debugging SSL/TLS Connections

Understanding SSL/TLS connection problems can sometimes be difficult, especially when it is not clear what messages are actually being sent and received. The SunJSSE has a built-in debug facility and is activated by the System property javax.net.debug.

To know more about javax.net.debug System property, see Debugging Utilities.

What follows is a brief example how to read the debug output. Please be aware that the output is non-standard, and may change from release to release. We are using the default SunJSSE X509KeyManager and X509TrustManager which prints debug information.

This example assumes a basic understanding of the SSL/TLS protocol. To know more about protocols (handshake messages, etc.), see Secure Sockets Layer (SSL) Protocol Overview.

In this example, we connect using the SSLSocketClientWithClientAuth sample application to a simple HTTPS server that requires client authentication, then send a HTTPS request and receive the reply.

    java  -Djavax.net.debug=all  \
        -Djavax.net.ssl.trustStore=trustStore
        SSLSocketClientWithClientAuth bongos 2001 /index.html

First, the X509KeyManager is initialized and discovers there is one keyEntry in the supplied KeyStore for a subject called "duke". If a server requests a client to authenticate itself, the X509KeyManager will search its list of keyEntries for an appropriate credential.

***
found key for : duke
chain [0] = [
[
  Version: V1
  Subject: CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.",
  L=Cupertino, ST=CA, C=US
  Signature Algorithm: MD5withRSA, OID = 1.2.840.113549.1.1.4

  Key:  Sun RSA public key, 1024 bits
  modulus: 134968166047563266914058280571444028986498087544923991226919517
  667593269213420979048109900052353578998293280426361122296881234393722020
  704208851688212064483570055963805034839797994154526862998272017486468599
  962268346037652120279791547218281230795146025359480589335682217749874703
  510467348902637769973696151441
  public exponent: 65537
  Validity: [From: Tue May 22 16:46:46 PDT 2001,
               To: Sun May 22 16:46:46 PDT 2011]
  Issuer: CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.",
  L=Cupertino, ST=CA, C=US
  SerialNumber: [    3b0afa66]

]
  Algorithm: [MD5withRSA]
  Signature:
0000: 5F B5 62 E9 A0 26 1D 8E   A2 7E 7C 02 08 36 3A 3E  _.b..&.......6:>
0010: C9 C2 45 03 DD F9 BC 06   FC 25 CF 30 92 91 B1 4E  ..E......%.0...N
0020: 62 17 08 48 14 68 80 CF   DD 89 11 EA 92 7F CE DD  b..H.h..........
0030: B4 FD 12 A8 71 C7 9E D7   C3 D0 E3 BD BB DE 20 92  ....q......... .
0040: C2 3B C8 DE CB 25 23 C0   8B B6 92 B9 0B 64 80 63  .;...%#......d.c
0050: D9 09 25 2D 7A CF 0A 31   B6 E9 CA C1 37 93 BC 0D  ..%-z..1....7...
0060: 4E 74 95 4F 58 31 DA AC   DF D8 BD 89 BD AF EC C8  Nt.OX1..........
0070: 2D 18 A2 BC B2 15 4F B7   28 6F D3 00 E1 72 9B 6C  -.....O.(o...r.l

]
***

The X509TrustManager is next initialized, and finds a certificate for a Certificate Authority (CA) named "JSSE Test CA". Any server presenting

valid

credentials signed by this CA will be trusted.

trustStore is: trustkeys
trustStore type is : jks
trustStore provider is : 
init truststore
adding as trusted cert:
  Subject: CN=JSSE Test CA, OU=JWS, O=Sun,
      L=Santa Clara, ST=CA, C=US
  Issuer:  CN=JSSE Test CA, OU=JWS, O=Sun,
      L=Santa Clara, ST=CA, C=US
  Algorithm: RSA; Serial number: 0x0
  Valid from Mon Jul 19 13:30:15 PDT 2004 until Fri Dec 05 12:30:15 PST 2031

We finish some additional initialization code, and after this, we are now finally ready to make the connection to the server.

trigger seeding of SecureRandom
done seeding SecureRandom
export control - checking the cipher suites
export control - no cached value available...
export control - storing legal entry into cache...
%% No cached client session

The connection to the server is made, and we see the initial ClientHello message, which contains:

  • random information to initialize the cryptographic routines,
  • the SessionID, which if non-null, would be used in reestablishing a previous session,
  • the list of ciphersuites that the client requests,
  • and no compression algorithms.

This is followed by the output of various filters, such as encapsulating the TLSv1 header into the SSLv2Hello header format (See setEnabledProtocols()).

*** ClientHello, TLSv1
RandomCookie:  GMT: 1073239164 bytes = { 10, 80, 71, 86, 124, 135, 104,
151, 72, 153, 70, 28, 97, 232, 160, 217, 146, 178, 87, 255, 122, 147, 83,
197, 60, 187, 227, 76 }
Session ID:  {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA,
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA,
SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5,
SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA]
Compression Methods:  { 0 }
***
[write] MD5 and SHA1 hashes:  len = 73
0000: 01 00 00 45 03 01 40 F8   54 7C 0A 50 47 56 7C 87  ...E..@.T..PGV..
0010: 68 97 48 99 46 1C 61 E8   A0 D9 92 B2 57 FF 7A 93  h.H.F.a.....W.z.
0020: 53 C5 3C BB E3 4C 00 00   1E 00 04 00 05 00 2F 00  S.<..L......../.
0030: 33 00 32 00 0A 00 16 00   13 00 09 00 15 00 12 00  3.2.............
0040: 03 00 08 00 14 00 11 01   00                       .........
main, WRITE: TLSv1 Handshake, length = 73
[write] MD5 and SHA1 hashes:  len = 98
0000: 01 03 01 00 39 00 00 00   20 00 00 04 01 00 80 00  ....9... .......
0010: 00 05 00 00 2F 00 00 33   00 00 32 00 00 0A 07 00  ..../..3..2.....
0020: C0 00 00 16 00 00 13 00   00 09 06 00 40 00 00 15  ............@...
0030: 00 00 12 00 00 03 02 00   80 00 00 08 00 00 14 00  ................
0040: 00 11 40 F8 54 7C 0A 50   47 56 7C 87 68 97 48 99  ..@.T..PGV..h.H.
0050: 46 1C 61 E8 A0 D9 92 B2   57 FF 7A 93 53 C5 3C BB  F.a.....W.z.S.<.
0060: E3 4C                                              .L
main, WRITE: SSLv2 client hello message, length = 98

Section labeled "[Raw write]" represent the actual data sent to the raw output object (in this case, an OutputStream).

[Raw write]: length = 100
0000: 80 62 01 03 01 00 39 00   00 00 20 00 00 04 01 00  .b....9... .....
0010: 80 00 00 05 00 00 2F 00   00 33 00 00 32 00 00 0A  ....../..3..2...
0020: 07 00 C0 00 00 16 00 00   13 00 00 09 06 00 40 00  ..............@.
0030: 00 15 00 00 12 00 00 03   02 00 80 00 00 08 00 00  ................
0040: 14 00 00 11 40 F8 54 7C   0A 50 47 56 7C 87 68 97  ....@.T..PGV..h.
0050: 48 99 46 1C 61 E8 A0 D9   92 B2 57 FF 7A 93 53 C5  H.F.a.....W.z.S.
0060: 3C BB E3 4C                                        <..L

After sending the initial ClientHello, we wait for the server's response, a ServerHello. "[Raw read]" displays the raw data read from the input device (InputStream), before any processing has been performed.

[Raw read]: length = 5
0000: 16 03 01 06 F0                                     .....
[Raw read]: length = 1776
0000: 02 00 00 46 03 01 40 FC   31 10 79 AB 17 66 FA 8B  ...F..@.1.y..f..
0010: 3F AA FD 5E 48 23 FA 90   31 D8 3C B9 A3 2C 8C F5  ?..^H#..1.<..,..
0020: E9 81 9B A2 63 6C 20 40   FC 31 10 BD 8D A5 91 06  ....cl @.1......
0030: 8B E1 E6 80 C6 5A 5C D9   8D 0A AE CA 58 4A BA 36  .....Z\.....XJ.6
0040: B1 3D 04 8D 82 21 B4 00   04 00 0B 00 06 1B 00 06  .=...!..........
0050: 18 00 03 11 30 82 03 0D   30 82 02 76 A0 03 02 01  ....0...0..v....
0060: 02 02 01 01 30 0D 06 09   2A 86 48 86 F7 0D 01 01  ....0...*.H.....
0070: 04 05 00 30 63 31 0B 30   09 06 03 55 04 06 13 02  ...0c1.0...U....
0080: 55 53 31 0B 30 09 06 03   55 04 08 13 02 43 41 31  US1.0...U....CA1
0090: 14 30 12 06 03 55 04 07   13 0B 53 61 6E 74 61 20  .0...U....Santa 
00A0: 43 6C 61 72 61 31 0C 30   0A 06 03 55 04 0A 13 03  Clara1.0...U....
00B0: 53 75 6E 31 0C 30 0A 06   03 55 04 0B 13 03 4A 57  Sun1.0...U....JW
00C0: 53 31 15 30 13 06 03 55   04 03 13 0C 4A 53 53 45  S1.0...U....JSSE
00D0: 20 54 65 73 74 20 43 41   30 1E 17 0D 30 34 30 37   Test CA0...0407
00E0: 31 39 32 30 33 30 35 31   5A 17 0D 33 31 31 32 30  19203051Z..31120
00F0: 35 32 30 33 30 35 31 5A   30 48 31 0B 30 09 06 03  5203051Z0H1.0...
0100: 55 04 06 13 02 55 53 31   0B 30 09 06 03 55 04 08  U....US1.0...U..
0110: 13 02 43 41 31 0C 30 0A   06 03 55 04 0A 13 03 53  ..CA1.0...U....S
0120: 75 6E 31 0D 30 0B 06 03   55 04 0B 13 04 4A 61 76  un1.0...U....Jav
0130: 61 31 0F 30 0D 06 03 55   04 03 13 06 62 6F 6E 67  a1.0...U....bong
0140: 6F 73 30 81 9F 30 0D 06   09 2A 86 48 86 F7 0D 01  os0..0...*.H....
0150: 01 01 05 00 03 81 8D 00   30 81 89 02 81 81 00 CC  ........0.......
0160: 09 74 CB 43 AB 6D ED F6   35 AA 0E 49 29 D9 E0 F0  .t.C.m..5..I)...
0170: A1 D5 E2 3E 8F 5E C5 CE   F4 DE C1 A4 F3 CB 8C 45  ...>.^.........E
0180: 0B 0F 6E 21 E1 00 65 CB   3C D1 5C EF 6A FB 5D 96  ..n!..e.<.\.j.].
0190: 93 F4 71 41 41 45 FF 37   86 4C AB F9 EA 9A 3F A5  ..qAAE.7.L....?.
01A0: 82 60 BF 0A 81 84 C9 3E   AC 0F 3D 20 3D AC A0 69  .`.....>..= =..i
01B0: EF CA 4A A7 94 AD C8 A5   CE 37 66 52 D1 25 43 CB  ..J......7fR.%C.
01C0: 10 44 07 1E 93 74 D9 68   01 D7 06 48 C9 0D 52 2D  .D...t.h...H..R-
01D0: D5 6A 2E A6 48 4C 59 E2   5C C6 C1 5C C8 4C 1B 02  .j..HLY.\..\.L..
01E0: 03 01 00 01 A3 81 EB 30   81 E8 30 09 06 03 55 1D  .......0..0...U.
01F0: 13 04 02 30 00 30 2C 06   09 60 86 48 01 86 F8 42  ...0.0,..`.H...B
0200: 01 0D 04 1F 16 1D 4F 70   65 6E 53 53 4C 20 47 65  ......OpenSSL Ge
0210: 6E 65 72 61 74 65 64 20   43 65 72 74 69 66 69 63  nerated Certific
0220: 61 74 65 30 1D 06 03 55   1D 0E 04 16 04 14 58 D7  ate0...U......X.
0230: 3A A9 37 AA 3E 14 27 FC   EC CC 45 08 04 8E 2A 8B  :.7.>.'...E...*.
0240: 77 28 30 81 8D 06 03 55   1D 23 04 81 85 30 81 82  w(0....U.#...0..
0250: 80 14 08 A3 7E 35 96 15   FA B0 F5 1B 5F CD 4F 54  .....5......_.OT
0260: EF 31 33 70 E4 A7 A1 67   A4 65 30 63 31 0B 30 09  .13p...g.e0c1.0.
0270: 06 03 55 04 06 13 02 55   53 31 0B 30 09 06 03 55  ..U....US1.0...U
0280: 04 08 13 02 43 41 31 14   30 12 06 03 55 04 07 13  ....CA1.0...U...
0290: 0B 53 61 6E 74 61 20 43   6C 61 72 61 31 0C 30 0A  .Santa Clara1.0.
02A0: 06 03 55 04 0A 13 03 53   75 6E 31 0C 30 0A 06 03  ..U....Sun1.0...
02B0: 55 04 0B 13 03 4A 57 53   31 15 30 13 06 03 55 04  U....JWS1.0...U.
02C0: 03 13 0C 4A 53 53 45 20   54 65 73 74 20 43 41 82  ...JSSE Test CA.
02D0: 01 00 30 0D 06 09 2A 86   48 86 F7 0D 01 01 04 05  ..0...*.H.......
02E0: 00 03 81 81 00 05 3E 17   DA F2 05 CB 4E 9E BF 12  ......>.....N...
02F0: CE 13 76 FF B2 FB 7F 9C   3D 45 28 43 6C 98 28 E3  ..v.....=E(Cl.(.
0300: 92 17 C2 C6 F1 62 CA 60   C2 B0 EC E6 7E 4C 2F C2  .....b.`.....L/.
0310: 40 FE 06 CB 34 60 B1 F4   26 1C E8 46 39 24 E1 8A  @...4`..&..F9$..
0320: 71 F2 13 90 A4 0A 7B 0B   13 AB 51 68 53 D9 7A 31  q.........QhS.z1
0330: 5A C1 7E 3C 44 2C 49 70   57 25 F9 18 FE 5D A5 42  Z..<D,IpW%...].B
0340: 7F 3E 61 1F 29 A3 31 46   02 C6 D2 8C 27 79 40 76  .>a.).1F....'y@v
0350: 97 B6 25 19 BE 6C 6A 92   DC EF 11 BE E7 4A FF 2A  ..%..lj......J.*
0360: E6 D6 AC 39 31 00 03 01   30 82 02 FD 30 82 02 66  ...91...0...0..f
0370: A0 03 02 01 02 02 01 00   30 0D 06 09 2A 86 48 86  ........0...*.H.
0380: F7 0D 01 01 04 05 00 30   63 31 0B 30 09 06 03 55  .......0c1.0...U
0390: 04 06 13 02 55 53 31 0B   30 09 06 03 55 04 08 13  ....US1.0...U...
03A0: 02 43 41 31 14 30 12 06   03 55 04 07 13 0B 53 61  .CA1.0...U....Sa
03B0: 6E 74 61 20 43 6C 61 72   61 31 0C 30 0A 06 03 55  nta Clara1.0...U
03C0: 04 0A 13 03 53 75 6E 31   0C 30 0A 06 03 55 04 0B  ....Sun1.0...U..
03D0: 13 03 4A 57 53 31 15 30   13 06 03 55 04 03 13 0C  ..JWS1.0...U....
03E0: 4A 53 53 45 20 54 65 73   74 20 43 41 30 1E 17 0D  JSSE Test CA0...
03F0: 30 34 30 37 31 39 32 30   33 30 31 35 5A 17 0D 33  040719203015Z..3
0400: 31 31 32 30 35 32 30 33   30 31 35 5A 30 63 31 0B  11205203015Z0c1.
0410: 30 09 06 03 55 04 06 13   02 55 53 31 0B 30 09 06  0...U....US1.0..
0420: 03 55 04 08 13 02 43 41   31 14 30 12 06 03 55 04  .U....CA1.0...U.
0430: 07 13 0B 53 61 6E 74 61   20 43 6C 61 72 61 31 0C  ...Santa Clara1.
0440: 30 0A 06 03 55 04 0A 13   03 53 75 6E 31 0C 30 0A  0...U....Sun1.0.
0450: 06 03 55 04 0B 13 03 4A   57 53 31 15 30 13 06 03  ..U....JWS1.0...
0460: 55 04 03 13 0C 4A 53 53   45 20 54 65 73 74 20 43  U....JSSE Test C
0470: 41 30 81 9F 30 0D 06 09   2A 86 48 86 F7 0D 01 01  A0..0...*.H.....
0480: 01 05 00 03 81 8D 00 30   81 89 02 81 81 00 9A 0A  .......0........
0490: B6 45 66 D5 DE 4A D9 3C   8C AC A6 B5 A5 88 B4 CF  .Ef..J.<........
04A0: 14 E1 A6 1B 25 25 4F 44   C9 1F 22 38 32 29 CF A1  ....%%OD.."82)..
04B0: 7C 18 30 93 DC 2B EC 2B   67 EE 2E 08 66 2D 0F 47  ..0..+.+g...f-.G
04C0: E0 12 3A DC E0 03 E9 65   16 F6 18 C6 16 14 56 24  ..:....e......V$
04D0: 55 7D 32 3E F9 66 A2 DD   55 EB 4D 0A 67 C7 5D 21  U.2>.f..U.M.g.]!
04E0: 9B 29 EA 2E 51 C5 83 A3   55 FF 35 CA A6 99 8F 46  .)..Q...U.5....F
04F0: F8 8E 56 BB A2 B1 39 83   D8 61 42 79 E0 95 78 FA  ..V...9..aBy..x.
0500: C6 E3 65 B0 FD 74 2D 64   51 71 04 F2 A1 91 02 03  ..e..t-dQq......
0510: 01 00 01 A3 81 C0 30 81   BD 30 1D 06 03 55 1D 0E  ......0..0...U..
0520: 04 16 04 14 08 A3 7E 35   96 15 FA B0 F5 1B 5F CD  .......5......_.
0530: 4F 54 EF 31 33 70 E4 A7   30 81 8D 06 03 55 1D 23  OT.13p..0....U.#
0540: 04 81 85 30 81 82 80 14   08 A3 7E 35 96 15 FA B0  ...0.......5....
0550: F5 1B 5F CD 4F 54 EF 31   33 70 E4 A7 A1 67 A4 65  .._.OT.13p...g.e
0560: 30 63 31 0B 30 09 06 03   55 04 06 13 02 55 53 31  0c1.0...U....US1
0570: 0B 30 09 06 03 55 04 08   13 02 43 41 31 14 30 12  .0...U....CA1.0.
0580: 06 03 55 04 07 13 0B 53   61 6E 74 61 20 43 6C 61  ..U....Santa Cla
0590: 72 61 31 0C 30 0A 06 03   55 04 0A 13 03 53 75 6E  ra1.0...U....Sun
05A0: 31 0C 30 0A 06 03 55 04   0B 13 03 4A 57 53 31 15  1.0...U....JWS1.
05B0: 30 13 06 03 55 04 03 13   0C 4A 53 53 45 20 54 65  0...U....JSSE Te
05C0: 73 74 20 43 41 82 01 00   30 0C 06 03 55 1D 13 04  st CA...0...U...
05D0: 05 30 03 01 01 FF 30 0D   06 09 2A 86 48 86 F7 0D  .0....0...*.H...
05E0: 01 01 04 05 00 03 81 81   00 73 6A 46 A2 05 E3 D8  .........sjF....
05F0: 6E 5C F4 18 A2 74 BC CF   EB 0C 5B FF 81 1C 28 85  n\...t....[...(.
0600: C7 FA E4 ED 5C 4F 71 22   FB 26 E3 01 3D 0C 10 AA  ....\Oq".&..=...
0610: BB 3E 90 ED 0E 1F 0C 9B   B1 8C 49 6A 51 E4 C3 52  .>........IjQ..R
0620: D6 FB 42 6C B4 A9 A9 57   A5 84 00 42 6D 37 37 6D  ..Bl...W...Bm77m
0630: C7 6C 23 BC DC 60 D1 9D   6F B3 75 47 3A 15 33 1A  .l#..`..o.uG:.3.
0640: EC 90 09 9D F9 EB BD 88   96 E7 1D 41 BC 01 8D CA  ...........A....
0650: 88 D9 5B 04 09 8F 3E EA   C8 15 A0 AA 4E 85 95 AE  ..[...>.....N...
0660: 2F 0E 31 92 AC 3C FB 2F   C4 0D 00 00 7F 02 01 02  /.1..<./........
0670: 00 7A 00 78 30 76 31 0B   30 09 06 03 55 04 06 13  .z.x0v1.0...U...
0680: 02 55 53 31 0B 30 09 06   03 55 04 08 13 02 43 41  .US1.0...U....CA
0690: 31 12 30 10 06 03 55 04   07 13 09 43 75 70 65 72  1.0...U....Cuper
06A0: 74 69 6E 6F 31 1F 30 1D   06 03 55 04 0A 13 16 53  tino1.0...U....S
06B0: 75 6E 20 4D 69 63 72 6F   73 79 73 74 65 6D 73 2C  un Microsystems,
06C0: 20 49 6E 63 2E 31 16 30   14 06 03 55 04 0B 13 0D   Inc.1.0...U....
06D0: 4A 61 76 61 20 53 6F 66   74 77 61 72 65 31 0D 30  Java Software1.0
06E0: 0B 06 03 55 04 03 13 04   44 75 6B 65 0E 00 00 00  ...U....Duke....
main, READ: TLSv1 Handshake, length = 1776

The data is unpackaged, and if the message is in the SSL/TLS format, it is parsed into a ServerHello. If you connected to a non-SSL/TLS socket (plaintext?), the received data will not be in SSL/TLS format, and you'll have problems connecting.

The ServerHello specifies several things:

  • The server's random data, also used to initialize the cryptographic algorithms,
  • the identifier of this session (if the client wants to try to rejoin this session using a different connection, it can send this ID in its ClientHello. If the client session ID equals the server session ID, an abbreviated handshake takes place, and the previously established parameters are used),
  • the selected cipher suite,
  • and the compression method (none in this case).

Lastly note that the ServerHello has specified that the connection should use "TLSv1", rather than "SSLv3."

                                           
*** ServerHello, TLSv1
RandomCookie:  GMT: 1073492240 bytes = { 121, 171, 23, 102, 250, 139, 63,
170, 253, 94, 72, 35, 250, 144, 49, 216, 60, 185, 163, 44, 140, 245, 233,
129, 155, 162, 99, 108 }
Session ID:  {64, 252, 49, 16, 189, 141, 165, 145, 6, 139, 225, 230, 128,
198, 90, 92, 217, 141, 10, 174, 202, 88, 74, 186, 54, 177, 61, 4, 141, 130,
33, 180}
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
Compression Method: 0
***
%% Created:  [Session-1, SSL_RSA_WITH_RC4_128_MD5]
** SSL_RSA_WITH_RC4_128_MD5
[read] MD5 and SHA1 hashes:  len = 74
0000: 02 00 00 46 03 01 40 FC   31 10 79 AB 17 66 FA 8B  ...F..@.1.y..f..
0010: 3F AA FD 5E 48 23 FA 90   31 D8 3C B9 A3 2C 8C F5  ?..^H#..1.<..,..
0020: E9 81 9B A2 63 6C 20 40   FC 31 10 BD 8D A5 91 06  ....cl @.1......
0030: 8B E1 E6 80 C6 5A 5C D9   8D 0A AE CA 58 4A BA 36  .....Z\.....XJ.6
0040: B1 3D 04 8D 82 21 B4 00   04 00                    .=...!....

The server next identifies itself to the client by passing a Certificate chain. In this example, we have a certificate for the subject "bongos", signed by the issuer "JSSE Test CA". We know that "JSSE Test CA" is a trusted CA, so if the certificate chain verifies correctly by our X509TrustManager, we can accept this connection.

There are many different ways of establishing trust, so if the default X509TrustManager is not doing the types of trust management you need, you can supply your own X509TrustManager to the SSLContext.

*** Certificate chain
chain [0] = [
[
  Version: V3
  Subject: 
  CN=bongos, OU=Java, O=Sun, ST=CA, C=US
  Signature Algorithm: MD5withRSA, OID = 1.2.840.113549.1.1.4

  Key:  Sun RSA public key, 1024 bits
  modulus: 143279610700427050704216702734995283650706638118826657356308087
  682552751165540126665070195006746918193702313900836063802045448392771274
  463088345157808670190122017153821642985630288017629294930800445939721128
  735250668515619736933648548512047941708018130926985936894512063397816602
  623867976474763783110866258971
  public exponent: 65537
  Validity: [From: Mon Jul 19 13:30:51 PDT 2004,
               To: Fri Dec 05 12:30:51 PST 2031]
  Issuer: CN=JSSE Test CA, OU=JWS, O=Sun,
      L=Santa Clara, ST=CA, C=US
  SerialNumber: [    01]

Certificate Extensions: 3

[1]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 58 D7 3A A9 37 AA 3E 14   27 FC EC CC 45 08 04 8E  X.:.7.>.'...E...
0010: 2A 8B 77 28                                        *.w(
]
]

[2]: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 08 A3 7E 35 96 15 FA B0   F5 1B 5F CD 4F 54 EF 31  ...5......_.OT.1
0010: 33 70 E4 A7                                        3p..
]

[CN=JSSE Test CA, OU=JWS, O=Sun, L=Santa Clara, ST=CA, C=US]
SerialNumber: [    00]
]

[3]: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:false
PathLen: undefined
]

]
  Algorithm: [MD5withRSA]
  Signature:
0000: 05 3E 17 DA F2 05 CB 4E   9E BF 12 CE 13 76 FF B2  .>.....N.....v..
0010: FB 7F 9C 3D 45 28 43 6C   98 28 E3 92 17 C2 C6 F1  ...=E(Cl.(......
0020: 62 CA 60 C2 B0 EC E6 7E   4C 2F C2 40 FE 06 CB 34  b.`.....L/.@...4
0030: 60 B1 F4 26 1C E8 46 39   24 E1 8A 71 F2 13 90 A4  `..&..F9$..q....
0040: 0A 7B 0B 13 AB 51 68 53   D9 7A 31 5A C1 7E 3C 44  .....QhS.z1Z..<D
0050: 2C 49 70 57 25 F9 18 FE   5D A5 42 7F 3E 61 1F 29  ,IpW%...].B.>a.)
0060: A3 31 46 02 C6 D2 8C 27   79 40 76 97 B6 25 19 BE  .1F....'y@v..%..
0070: 6C 6A 92 DC EF 11 BE E7   4A FF 2A E6 D6 AC 39 31  lj......J.*...91

]
chain [1] = [
[
  Version: V3
  Subject: CN=JSSE Test CA, OU=JWS, O=Sun,
      L=Santa Clara, ST=CA, C=US
  Signature Algorithm: MD5withRSA, OID = 1.2.840.113549.1.1.4

  Key:  Sun RSA public key, 1024 bits
  modulus: 108171861314934294923646852258201093253619460299818135230481040
  615923025149195168140458238629251726950220398889722590740552079782864577
  976838691751841449679901644183317203824143803940037883199193775839934767
  304560313841716869284745769157293013188246601563271959824290073095150730
  505329011956986145636520993169
  public exponent: 65537
  Validity: [From: Mon Jul 19 13:30:15 PDT 2004,
               To: Fri Dec 05 12:30:15 PST 2031]
  Issuer: CN=JSSE Test CA, OU=JWS, O=Sun,
      L=Santa Clara, ST=CA, C=US
  SerialNumber: [    00]

Certificate Extensions: 3
[1]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 08 A3 7E 35 96 15 FA B0   F5 1B 5F CD 4F 54 EF 31  ...5......_.OT.1
0010: 33 70 E4 A7                                        3p..
]
]

[2]: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 08 A3 7E 35 96 15 FA B0   F5 1B 5F CD 4F 54 EF 31  ...5......_.OT.1
0010: 33 70 E4 A7                                        3p..
]

[CN=JSSE Test CA, OU=JWS, O=Sun, L=Santa Clara, ST=CA, C=US]
SerialNumber: [    00]
]

[3]: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:true
PathLen:2147483647
]

]
  Algorithm: [MD5withRSA]
  Signature:
0000: 73 6A 46 A2 05 E3 D8 6E   5C F4 18 A2 74 BC CF EB  sjF....n\...t...
0010: 0C 5B FF 81 1C 28 85 C7   FA E4 ED 5C 4F 71 22 FB  .[...(.....\Oq".
0020: 26 E3 01 3D 0C 10 AA BB   3E 90 ED 0E 1F 0C 9B B1  &..=....>.......
0030: 8C 49 6A 51 E4 C3 52 D6   FB 42 6C B4 A9 A9 57 A5  .IjQ..R..Bl...W.
0040: 84 00 42 6D 37 37 6D C7   6C 23 BC DC 60 D1 9D 6F  ..Bm77m.l#..`..o
0050: B3 75 47 3A 15 33 1A EC   90 09 9D F9 EB BD 88 96  .uG:.3..........
0060: E7 1D 41 BC 01 8D CA 88   D9 5B 04 09 8F 3E EA C8  ..A......[...>..
0070: 15 A0 AA 4E 85 95 AE 2F   0E 31 92 AC 3C FB 2F C4  ...N.../.1..<./.

]

We recognize this cert! We can trust it, and continue on with the handshake.

***
Found trusted certificate:
[
[
  Version: V3
  Subject: CN=JSSE Test CA, OU=JWS, O=Sun, L=Santa Clara, ST=CA, C=US
  Signature Algorithm: MD5withRSA, OID = 1.2.840.113549.1.1.4

  Key:  Sun RSA public key, 1024 bits
  modulus: 108171861314934294923646852258201093253619460299818135230481040
  615923025149195168140458238629251726950220398889722590740552079782864577
  976838691751841449679901644183317203824143803940037883199193775839934767
  304560313841716869284745769157293013188246601563271959824290073095150730
  505329011956986145636520993169
  public exponent: 65537
  Validity: [From: Mon Jul 19 13:30:15 PDT 2004,
               To: Fri Dec 05 12:30:15 PST 2031]
  Issuer: CN=JSSE Test CA, OU=JWS, O=Sun, L=Santa Clara, ST=CA, C=US
  SerialNumber: [    00]

Certificate Extensions: 3
[1]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 08 A3 7E 35 96 15 FA B0   F5 1B 5F CD 4F 54 EF 31  ...5......_.OT.1
0010: 33 70 E4 A7                                        3p..
]
]

[2]: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 08 A3 7E 35 96 15 FA B0   F5 1B 5F CD 4F 54 EF 31  ...5......_.OT.1
0010: 33 70 E4 A7                                        3p..
]

[CN=JSSE Test CA, OU=JWS, O=Sun, L=Santa Clara, ST=CA, C=US]
SerialNumber: [    00]
]

[3]: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:true
PathLen:2147483647
]

]
  Algorithm: [MD5withRSA]
  Signature:
0000: 73 6A 46 A2 05 E3 D8 6E   5C F4 18 A2 74 BC CF EB  sjF....n\...t...
0010: 0C 5B FF 81 1C 28 85 C7   FA E4 ED 5C 4F 71 22 FB  .[...(.....\Oq".
0020: 26 E3 01 3D 0C 10 AA BB   3E 90 ED 0E 1F 0C 9B B1  &..=....>.......
0030: 8C 49 6A 51 E4 C3 52 D6   FB 42 6C B4 A9 A9 57 A5  .IjQ..R..Bl...W.
0040: 84 00 42 6D 37 37 6D C7   6C 23 BC DC 60 D1 9D 6F  ..Bm77m.l#..`..o
0050: B3 75 47 3A 15 33 1A EC   90 09 9D F9 EB BD 88 96  .uG:.3..........
0060: E7 1D 41 BC 01 8D CA 88   D9 5B 04 09 8F 3E EA C8  ..A......[...>..
0070: 15 A0 AA 4E 85 95 AE 2F   0E 31 92 AC 3C FB 2F C4  ...N.../.1..<./.

]

We read the next few bytes of the handshake...

[read] MD5 and SHA1 hashes:  len = 1567
0000: 0B 00 06 1B 00 06 18 00   03 11 30 82 03 0D 30 82  ..........0...0.
0010: 02 76 A0 03 02 01 02 02   01 01 30 0D 06 09 2A 86  .v........0...*.
0020: 48 86 F7 0D 01 01 04 05   00 30 63 31 0B 30 09 06  H........0c1.0..
0030: 03 55 04 06 13 02 55 53   31 0B 30 09 06 03 55 04  .U....US1.0...U.
0040: 08 13 02 43 41 31 14 30   12 06 03 55 04 07 13 0B  ...CA1.0...U....
0050: 53 61 6E 74 61 20 43 6C   61 72 61 31 0C 30 0A 06  Santa Clara1.0..
0060: 03 55 04 0A 13 03 53 75   6E 31 0C 30 0A 06 03 55  .U....Sun1.0...U
0070: 04 0B 13 03 4A 57 53 31   15 30 13 06 03 55 04 03  ....JWS1.0...U..
0080: 13 0C 4A 53 53 45 20 54   65 73 74 20 43 41 30 1E  ..JSSE Test CA0.
0090: 17 0D 30 34 30 37 31 39   32 30 33 30 35 31 5A 17  ..040719203051Z.
00A0: 0D 33 31 31 32 30 35 32   30 33 30 35 31 5A 30 48  .311205203051Z0H
00B0: 31 0B 30 09 06 03 55 04   06 13 02 55 53 31 0B 30  1.0...U....US1.0
00C0: 09 06 03 55 04 08 13 02   43 41 31 0C 30 0A 06 03  ...U....CA1.0...
00D0: 55 04 0A 13 03 53 75 6E   31 0D 30 0B 06 03 55 04  U....Sun1.0...U.
00E0: 0B 13 04 4A 61 76 61 31   0F 30 0D 06 03 55 04 03  ...Java1.0...U..
00F0: 13 06 62 6F 6E 67 6F 73   30 81 9F 30 0D 06 09 2A  ..bongos0..0...*
0100: 86 48 86 F7 0D 01 01 01   05 00 03 81 8D 00 30 81  .H............0.
0110: 89 02 81 81 00 CC 09 74   CB 43 AB 6D ED F6 35 AA  .......t.C.m..5.
0120: 0E 49 29 D9 E0 F0 A1 D5   E2 3E 8F 5E C5 CE F4 DE  .I)......>.^....
0130: C1 A4 F3 CB 8C 45 0B 0F   6E 21 E1 00 65 CB 3C D1  .....E..n!..e.<.
0140: 5C EF 6A FB 5D 96 93 F4   71 41 41 45 FF 37 86 4C  \.j.]...qAAE.7.L
0150: AB F9 EA 9A 3F A5 82 60   BF 0A 81 84 C9 3E AC 0F  ....?..`.....>..
0160: 3D 20 3D AC A0 69 EF CA   4A A7 94 AD C8 A5 CE 37  = =..i..J......7
0170: 66 52 D1 25 43 CB 10 44   07 1E 93 74 D9 68 01 D7  fR.%C..D...t.h..
0180: 06 48 C9 0D 52 2D D5 6A   2E A6 48 4C 59 E2 5C C6  .H..R-.j..HLY.\.
0190: C1 5C C8 4C 1B 02 03 01   00 01 A3 81 EB 30 81 E8  .\.L.........0..
01A0: 30 09 06 03 55 1D 13 04   02 30 00 30 2C 06 09 60  0...U....0.0,..`
01B0: 86 48 01 86 F8 42 01 0D   04 1F 16 1D 4F 70 65 6E  .H...B......Open
01C0: 53 53 4C 20 47 65 6E 65   72 61 74 65 64 20 43 65  SSL Generated Ce
01D0: 72 74 69 66 69 63 61 74   65 30 1D 06 03 55 1D 0E  rtificate0...U..
01E0: 04 16 04 14 58 D7 3A A9   37 AA 3E 14 27 FC EC CC  ....X.:.7.>.'...
01F0: 45 08 04 8E 2A 8B 77 28   30 81 8D 06 03 55 1D 23  E...*.w(0....U.#
0200: 04 81 85 30 81 82 80 14   08 A3 7E 35 96 15 FA B0  ...0.......5....
0210: F5 1B 5F CD 4F 54 EF 31   33 70 E4 A7 A1 67 A4 65  .._.OT.13p...g.e
0220: 30 63 31 0B 30 09 06 03   55 04 06 13 02 55 53 31  0c1.0...U....US1
0230: 0B 30 09 06 03 55 04 08   13 02 43 41 31 14 30 12  .0...U....CA1.0.
0240: 06 03 55 04 07 13 0B 53   61 6E 74 61 20 43 6C 61  ..U....Santa Cla
0250: 72 61 31 0C 30 0A 06 03   55 04 0A 13 03 53 75 6E  ra1.0...U....Sun
0260: 31 0C 30 0A 06 03 55 04   0B 13 03 4A 57 53 31 15  1.0...U....JWS1.
0270: 30 13 06 03 55 04 03 13   0C 4A 53 53 45 20 54 65  0...U....JSSE Te
0280: 73 74 20 43 41 82 01 00   30 0D 06 09 2A 86 48 86  st CA...0...*.H.
0290: F7 0D 01 01 04 05 00 03   81 81 00 05 3E 17 DA F2  ............>...
02A0: 05 CB 4E 9E BF 12 CE 13   76 FF B2 FB 7F 9C 3D 45  ..N.....v.....=E
02B0: 28 43 6C 98 28 E3 92 17   C2 C6 F1 62 CA 60 C2 B0  (Cl.(......b.`..
02C0: EC E6 7E 4C 2F C2 40 FE   06 CB 34 60 B1 F4 26 1C  ...L/.@...4`..&.
02D0: E8 46 39 24 E1 8A 71 F2   13 90 A4 0A 7B 0B 13 AB  .F9$..q.........
02E0: 51 68 53 D9 7A 31 5A C1   7E 3C 44 2C 49 70 57 25  QhS.z1Z..<D,IpW%
02F0: F9 18 FE 5D A5 42 7F 3E   61 1F 29 A3 31 46 02 C6  ...].B.>a.).1F..
0300: D2 8C 27 79 40 76 97 B6   25 19 BE 6C 6A 92 DC EF  ..'y@v..%..lj...
0310: 11 BE E7 4A FF 2A E6 D6   AC 39 31 00 03 01 30 82  ...J.*...91...0.
0320: 02 FD 30 82 02 66 A0 03   02 01 02 02 01 00 30 0D  ..0..f........0.
0330: 06 09 2A 86 48 86 F7 0D   01 01 04 05 00 30 63 31  ..*.H........0c1
0340: 0B 30 09 06 03 55 04 06   13 02 55 53 31 0B 30 09  .0...U....US1.0.
0350: 06 03 55 04 08 13 02 43   41 31 14 30 12 06 03 55  ..U....CA1.0...U
0360: 04 07 13 0B 53 61 6E 74   61 20 43 6C 61 72 61 31  ....Santa Clara1
0370: 0C 30 0A 06 03 55 04 0A   13 03 53 75 6E 31 0C 30  .0...U....Sun1.0
0380: 0A 06 03 55 04 0B 13 03   4A 57 53 31 15 30 13 06  ...U....JWS1.0..
0390: 03 55 04 03 13 0C 4A 53   53 45 20 54 65 73 74 20  .U....JSSE Test 
03A0: 43 41 30 1E 17 0D 30 34   30 37 31 39 32 30 33 30  CA0...0407192030
03B0: 31 35 5A 17 0D 33 31 31   32 30 35 32 30 33 30 31  15Z..31120520301
03C0: 35 5A 30 63 31 0B 30 09   06 03 55 04 06 13 02 55  5Z0c1.0...U....U
03D0: 53 31 0B 30 09 06 03 55   04 08 13 02 43 41 31 14  S1.0...U....CA1.
03E0: 30 12 06 03 55 04 07 13   0B 53 61 6E 74 61 20 43  0...U....Santa C
03F0: 6C 61 72 61 31 0C 30 0A   06 03 55 04 0A 13 03 53  lara1.0...U....S
0400: 75 6E 31 0C 30 0A 06 03   55 04 0B 13 03 4A 57 53  un1.0...U....JWS
0410: 31 15 30 13 06 03 55 04   03 13 0C 4A 53 53 45 20  1.0...U....JSSE 
0420: 54 65 73 74 20 43 41 30   81 9F 30 0D 06 09 2A 86  Test CA0..0...*.
0430: 48 86 F7 0D 01 01 01 05   00 03 81 8D 00 30 81 89  H............0..
0440: 02 81 81 00 9A 0A B6 45   66 D5 DE 4A D9 3C 8C AC  .......Ef..J.<..
0450: A6 B5 A5 88 B4 CF 14 E1   A6 1B 25 25 4F 44 C9 1F  ..........%%OD..
0460: 22 38 32 29 CF A1 7C 18   30 93 DC 2B EC 2B 67 EE  "82)....0..+.+g.
0470: 2E 08 66 2D 0F 47 E0 12   3A DC E0 03 E9 65 16 F6  ..f-.G..:....e..
0480: 18 C6 16 14 56 24 55 7D   32 3E F9 66 A2 DD 55 EB  ....V$U.2>.f..U.
0490: 4D 0A 67 C7 5D 21 9B 29   EA 2E 51 C5 83 A3 55 FF  M.g.]!.)..Q...U.
04A0: 35 CA A6 99 8F 46 F8 8E   56 BB A2 B1 39 83 D8 61  5....F..V...9..a
04B0: 42 79 E0 95 78 FA C6 E3   65 B0 FD 74 2D 64 51 71  By..x...e..t-dQq
04C0: 04 F2 A1 91 02 03 01 00   01 A3 81 C0 30 81 BD 30  ............0..0
04D0: 1D 06 03 55 1D 0E 04 16   04 14 08 A3 7E 35 96 15  ...U.........5..
04E0: FA B0 F5 1B 5F CD 4F 54   EF 31 33 70 E4 A7 30 81  ...._.OT.13p..0.
04F0: 8D 06 03 55 1D 23 04 81   85 30 81 82 80 14 08 A3  ...U.#...0......
0500: 7E 35 96 15 FA B0 F5 1B   5F CD 4F 54 EF 31 33 70  .5......_.OT.13p
0510: E4 A7 A1 67 A4 65 30 63   31 0B 30 09 06 03 55 04  ...g.e0c1.0...U.
0520: 06 13 02 55 53 31 0B 30   09 06 03 55 04 08 13 02  ...US1.0...U....
0530: 43 41 31 14 30 12 06 03   55 04 07 13 0B 53 61 6E  CA1.0...U....San
0540: 74 61 20 43 6C 61 72 61   31 0C 30 0A 06 03 55 04  ta Clara1.0...U.
0550: 0A 13 03 53 75 6E 31 0C   30 0A 06 03 55 04 0B 13  ...Sun1.0...U...
0560: 03 4A 57 53 31 15 30 13   06 03 55 04 03 13 0C 4A  .JWS1.0...U....J
0570: 53 53 45 20 54 65 73 74   20 43 41 82 01 00 30 0C  SSE Test CA...0.
0580: 06 03 55 1D 13 04 05 30   03 01 01 FF 30 0D 06 09  ..U....0....0...
0590: 2A 86 48 86 F7 0D 01 01   04 05 00 03 81 81 00 73  *.H............s
05A0: 6A 46 A2 05 E3 D8 6E 5C   F4 18 A2 74 BC CF EB 0C  jF....n\...t....
05B0: 5B FF 81 1C 28 85 C7 FA   E4 ED 5C 4F 71 22 FB 26  [...(.....\Oq".&
05C0: E3 01 3D 0C 10 AA BB 3E   90 ED 0E 1F 0C 9B B1 8C  ..=....>........
05D0: 49 6A 51 E4 C3 52 D6 FB   42 6C B4 A9 A9 57 A5 84  IjQ..R..Bl...W..
05E0: 00 42 6D 37 37 6D C7 6C   23 BC DC 60 D1 9D 6F B3  .Bm77m.l#..`..o.
05F0: 75 47 3A 15 33 1A EC 90   09 9D F9 EB BD 88 96 E7  uG:.3...........
0600: 1D 41 BC 01 8D CA 88 D9   5B 04 09 8F 3E EA C8 15  .A......[...>...
0610: A0 AA 4E 85 95 AE 2F 0E   31 92 AC 3C FB 2F C4     ..N.../.1..<./.

...and parse it to find that it's a CertificateRequest message.

The server is asking the client to identify itself with a X509 certificate subject having the common name (CN=) "Duke". The server's X509TrustManager has the option of rejecting any credentials provided by the client (or lack thereof). In a real-world situation, you'd probably use a certificate signed by a CA, and the list of trusted CA's would be included in this message instead.

*** CertificateRequest
Cert Types: RSA, DSS, 
Cert Authorities:
CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.",
L=Cupertino, ST=CA, C=US>
[read] MD5 and SHA1 hashes:  len = 131
0000: 0D 00 00 7F 02 01 02 00   7A 00 78 30 76 31 0B 30  ........z.x0v1.0
0010: 09 06 03 55 04 06 13 02   55 53 31 0B 30 09 06 03  ...U....US1.0...
0020: 55 04 08 13 02 43 41 31   12 30 10 06 03 55 04 07  U....CA1.0...U..
0030: 13 09 43 75 70 65 72 74   69 6E 6F 31 1F 30 1D 06  ..Cupertino1.0..
0040: 03 55 04 0A 13 16 53 75   6E 20 4D 69 63 72 6F 73  .U....Sun Micros
0050: 79 73 74 65 6D 73 2C 20   49 6E 63 2E 31 16 30 14  ystems, Inc.1.0.
0060: 06 03 55 04 0B 13 0D 4A   61 76 61 20 53 6F 66 74  ..U....Java Soft
0070: 77 61 72 65 31 0D 30 0B   06 03 55 04 03 13 04 44  ware1.0...U....D
0080: 75 6B 65                                           uke
*** ServerHelloDone
[read] MD5 and SHA1 hashes:  len = 4
0000: 0E 00 00 00                                        ....

We need to send client credentials back to the server, so the client's X509KeyManager is now consulted. We look for a match between the list of accepted issuers (above), and the certificates we have in our KeyStore. In this case (luckily?), there is a match: we have credentials for "duke". It's now up to the server's X509TrustManager to decide whether to accept these credentials.

matching alias: duke
*** Certificate chain
chain [0] = [
[
  Version: V1
  Subject: CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.",
  L=Cupertino, ST=CA, C=US
  Signature Algorithm: MD5withRSA, OID = 1.2.840.113549.1.1.4

  Key:  Sun RSA public key, 1024 bits
  modulus: 134968166047563266914058280571444028986498087544923991226919517
  667593269213420979048109900052353578998293280426361122296881234393722020
  704208851688212064483570055963805034839797994154526862998272017486468599
  962268346037652120279791547218281230795146025359480589335682217749874703
  510467348902637769973696151441
  public exponent: 65537
  Validity: [From: Tue May 22 16:46:46 PDT 2001,
               To: Sun May 22 16:46:46 PDT 2011]
  Issuer: CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.",
  L=Cupertino, ST=CA, C=US
  SerialNumber: [    3b0afa66]

]
  Algorithm: [MD5withRSA]
  Signature:
0000: 5F B5 62 E9 A0 26 1D 8E   A2 7E 7C 02 08 36 3A 3E  _.b..&.......6:>
0010: C9 C2 45 03 DD F9 BC 06   FC 25 CF 30 92 91 B1 4E  ..E......%.0...N
0020: 62 17 08 48 14 68 80 CF   DD 89 11 EA 92 7F CE DD  b..H.h..........
0030: B4 FD 12 A8 71 C7 9E D7   C3 D0 E3 BD BB DE 20 92  ....q......... .
0040: C2 3B C8 DE CB 25 23 C0   8B B6 92 B9 0B 64 80 63  .;...%#......d.c
0050: D9 09 25 2D 7A CF 0A 31   B6 E9 CA C1 37 93 BC 0D  ..%-z..1....7...
0060: 4E 74 95 4F 58 31 DA AC   DF D8 BD 89 BD AF EC C8  Nt.OX1..........
0070: 2D 18 A2 BC B2 15 4F B7   28 6F D3 00 E1 72 9B 6C  -.....O.(o...r.l

]
***

In the case of this particular cipher suite, we must now pass a message called a ClientKeyExchange, which helps establish a shared secret between the two parties.

All of this data is eventually collected and written to the raw device.

*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
Random Secret:  { 3, 1, 132, 84, 245, 214, 235, 245, 168, 8, 186, 250,
122, 34, 97, 45, 117, 220, 64, 232, 152, 249, 14, 178, 135, 128, 184,
26, 143, 104, 37, 184, 81, 208, 84, 69, 97, 138, 80, 201, 187, 14, 57,
83, 69, 120, 190, 121 }
[write] MD5 and SHA1 hashes:  len = 754
0000: 0B 00 02 68 00 02 65 00   02 62 30 82 02 5E 30 82  ...h..e..b0..^0.
0010: 01 C7 02 04 3B 0A FA 66   30 0D 06 09 2A 86 48 86  ....;..f0...*.H.
0020: F7 0D 01 01 04 05 00 30   76 31 0B 30 09 06 03 55  .......0v1.0...U
0030: 04 06 13 02 55 53 31 0B   30 09 06 03 55 04 08 13  ....US1.0...U...
0040: 02 43 41 31 12 30 10 06   03 55 04 07 13 09 43 75  .CA1.0...U....Cu
0050: 70 65 72 74 69 6E 6F 31   1F 30 1D 06 03 55 04 0A  pertino1.0...U..
0060: 13 16 53 75 6E 20 4D 69   63 72 6F 73 79 73 74 65  ..Sun Microsyste
0070: 6D 73 2C 20 49 6E 63 2E   31 16 30 14 06 03 55 04  ms, Inc.1.0...U.
0080: 0B 13 0D 4A 61 76 61 20   53 6F 66 74 77 61 72 65  ...Java Software
0090: 31 0D 30 0B 06 03 55 04   03 13 04 44 75 6B 65 30  1.0...U....Duke0
00A0: 1E 17 0D 30 31 30 35 32   32 32 33 34 36 34 36 5A  ...010522234646Z
00B0: 17 0D 31 31 30 35 32 32   32 33 34 36 34 36 5A 30  ..110522234646Z0
00C0: 76 31 0B 30 09 06 03 55   04 06 13 02 55 53 31 0B  v1.0...U....US1.
00D0: 30 09 06 03 55 04 08 13   02 43 41 31 12 30 10 06  0...U....CA1.0..
00E0: 03 55 04 07 13 09 43 75   70 65 72 74 69 6E 6F 31  .U....Cupertino1
00F0: 1F 30 1D 06 03 55 04 0A   13 16 53 75 6E 20 4D 69  .0...U....Sun Mi
0100: 63 72 6F 73 79 73 74 65   6D 73 2C 20 49 6E 63 2E  crosystems, Inc.
0110: 31 16 30 14 06 03 55 04   0B 13 0D 4A 61 76 61 20  1.0...U....Java 
0120: 53 6F 66 74 77 61 72 65   31 0D 30 0B 06 03 55 04  Software1.0...U.
0130: 03 13 04 44 75 6B 65 30   81 9F 30 0D 06 09 2A 86  ...Duke0..0...*.
0140: 48 86 F7 0D 01 01 01 05   00 03 81 8D 00 30 81 89  H............0..
0150: 02 81 81 00 C0 33 77 E7   1F D0 CE CE BD 43 2F 8D  .....3w......C/.
0160: EB C6 D3 07 A9 00 F5 75   4D C8 4B 04 52 42 EE 69  .......uM.K.RB.i
0170: F3 30 E9 A0 C6 07 B7 C8   55 2D B9 5B 57 7A 4C AD  .0......U-.[WzL.
0180: 1A 30 63 5C 7D 6D 16 BF   ED 54 13 49 8A 1B E6 29  .0c\.m...T.I...)
0190: 26 20 85 F9 5E 2B 2F A7   12 9C 98 2D 83 F6 EE B1  &..^+/....-....
01A0: 85 68 DA B5 8E 4C 1D 2D   8E 21 97 B0 30 C8 3A 57  .h...L.-.!..0.:W
01B0: F4 E1 18 9E F6 98 B2 D5   3D 8E D5 2B 09 E2 E1 A0  ........=..+....
01C0: 49 C1 A6 43 CE EA 57 7F   3B 5C 3A C9 BA DB B7 F0  I..C..W.;\:.....
01D0: 89 69 BF 91 02 03 01 00   01 30 0D 06 09 2A 86 48  .i.......0...*.H
01E0: 86 F7 0D 01 01 04 05 00   03 81 81 00 5F B5 62 E9  ............_.b.
01F0: A0 26 1D 8E A2 7E 7C 02   08 36 3A 3E C9 C2 45 03  .&.......6:>..E.
0200: DD F9 BC 06 FC 25 CF 30   92 91 B1 4E 62 17 08 48  .....%.0...Nb..H
0210: 14 68 80 CF DD 89 11 EA   92 7F CE DD B4 FD 12 A8  .h..............
0220: 71 C7 9E D7 C3 D0 E3 BD   BB DE 20 92 C2 3B C8 DE  q......... ..;..
0230: CB 25 23 C0 8B B6 92 B9   0B 64 80 63 D9 09 25 2D  .%#......d.c..%-
0240: 7A CF 0A 31 B6 E9 CA C1   37 93 BC 0D 4E 74 95 4F  z..1....7...Nt.O
0250: 58 31 DA AC DF D8 BD 89   BD AF EC C8 2D 18 A2 BC  X1..........-...
0260: B2 15 4F B7 28 6F D3 00   E1 72 9B 6C 10 00 00 82  ..O.(o...r.l....
0270: 00 80 4E DD E7 77 F1 91   6B 31 4E FA D6 61 D9 69  ..N..w..k1N..a.i
0280: 82 BD 22 40 83 FD 76 E6   FF A7 18 95 A0 04 28 0D  .."@..v.......(.
0290: 0D F7 44 6F 0C 42 4F 17   77 A0 99 56 2A 13 77 28  ..Do.BO.w..V*.w(
02A0: 0B 09 48 C1 B9 8C 09 ED   9F C6 2E 32 18 DB BD ED  ..H........2....
02B0: AF C3 AB E7 AD 8F DF 9E   AB 07 43 B4 50 EF 74 98  ..........C.P.t.
02C0: EA FC E8 4D C9 DA FC B0   B2 C7 D4 83 50 B5 84 B8  ...M........P...
02D0: 44 86 7B 5D 8A C2 F8 04   80 06 E6 84 42 33 B2 EE  D..]........B3..
02E0: 05 E6 D3 48 0E 23 E5 1F   63 4C 53 98 B8 8C 45 BA  ...H.#..cLS...E.
02F0: C8 19                                              ..
main, WRITE: TLSv1 Handshake, length = 754
[Raw write]: length = 759
0000: 16 03 01 02 F2 0B 00 02   68 00 02 65 00 02 62 30  ........h..e..b0
0010: 82 02 5E 30 82 01 C7 02   04 3B 0A FA 66 30 0D 06  ..^0.....;..f0..
0020: 09 2A 86 48 86 F7 0D 01   01 04 05 00 30 76 31 0B  .*.H........0v1.
0030: 30 09 06 03 55 04 06 13   02 55 53 31 0B 30 09 06  0...U....US1.0..
0040: 03 55 04 08 13 02 43 41   31 12 30 10 06 03 55 04  .U....CA1.0...U.
0050: 07 13 09 43 75 70 65 72   74 69 6E 6F 31 1F 30 1D  ...Cupertino1.0.
0060: 06 03 55 04 0A 13 16 53   75 6E 20 4D 69 63 72 6F  ..U....Sun Micro
0070: 73 79 73 74 65 6D 73 2C   20 49 6E 63 2E 31 16 30  systems, Inc.1.0
0080: 14 06 03 55 04 0B 13 0D   4A 61 76 61 20 53 6F 66  ...U....Java Sof
0090: 74 77 61 72 65 31 0D 30   0B 06 03 55 04 03 13 04  tware1.0...U....
00A0: 44 75 6B 65 30 1E 17 0D   30 31 30 35 32 32 32 33  Duke0...01052223
00B0: 34 36 34 36 5A 17 0D 31   31 30 35 32 32 32 33 34  4646Z..110522234
00C0: 36 34 36 5A 30 76 31 0B   30 09 06 03 55 04 06 13  646Z0v1.0...U...
00D0: 02 55 53 31 0B 30 09 06   03 55 04 08 13 02 43 41  .US1.0...U....CA
00E0: 31 12 30 10 06 03 55 04   07 13 09 43 75 70 65 72  1.0...U....Cuper
00F0: 74 69 6E 6F 31 1F 30 1D   06 03 55 04 0A 13 16 53  tino1.0...U....S
0100: 75 6E 20 4D 69 63 72 6F   73 79 73 74 65 6D 73 2C  un Microsystems,
0110: 20 49 6E 63 2E 31 16 30   14 06 03 55 04 0B 13 0D   Inc.1.0...U....
0120: 4A 61 76 61 20 53 6F 66   74 77 61 72 65 31 0D 30  Java Software1.0
0130: 0B 06 03 55 04 03 13 04   44 75 6B 65 30 81 9F 30  ...U....Duke0..0
0140: 0D 06 09 2A 86 48 86 F7   0D 01 01 01 05 00 03 81  ...*.H..........
0150: 8D 00 30 81 89 02 81 81   00 C0 33 77 E7 1F D0 CE  ..0.......3w....
0160: CE BD 43 2F 8D EB C6 D3   07 A9 00 F5 75 4D C8 4B  ..C/........uM.K
0170: 04 52 42 EE 69 F3 30 E9   A0 C6 07 B7 C8 55 2D B9  .RB.i.0......U-.
0180: 5B 57 7A 4C AD 1A 30 63   5C 7D 6D 16 BF ED 54 13  [WzL..0c\.m...T.
0190: 49 8A 1B E6 29 26 20 85   F9 5E 2B 2F A7 12 9C 98  I...)& ..^+/....
01A0: 2D 83 F6 EE B1 85 68 DA   B5 8E 4C 1D 2D 8E 21 97  -.....h...L.-.!.
01B0: B0 30 C8 3A 57 F4 E1 18   9E F6 98 B2 D5 3D 8E D5  .0.:W........=..
01C0: 2B 09 E2 E1 A0 49 C1 A6   43 CE EA 57 7F 3B 5C 3A  +....I..C..W.;\:
01D0: C9 BA DB B7 F0 89 69 BF   91 02 03 01 00 01 30 0D  ......i.......0.
01E0: 06 09 2A 86 48 86 F7 0D   01 01 04 05 00 03 81 81  ..*.H...........
01F0: 00 5F B5 62 E9 A0 26 1D   8E A2 7E 7C 02 08 36 3A  ._.b..&.......6:
0200: 3E C9 C2 45 03 DD F9 BC   06 FC 25 CF 30 92 91 B1  >..E......%.0...
0210: 4E 62 17 08 48 14 68 80   CF DD 89 11 EA 92 7F CE  Nb..H.h.........
0220: DD B4 FD 12 A8 71 C7 9E   D7 C3 D0 E3 BD BB DE 20  .....q......... 
0230: 92 C2 3B C8 DE CB 25 23   C0 8B B6 92 B9 0B 64 80  ..;...%#......d.
0240: 63 D9 09 25 2D 7A CF 0A   31 B6 E9 CA C1 37 93 BC  c..%-z..1....7..
0250: 0D 4E 74 95 4F 58 31 DA   AC DF D8 BD 89 BD AF EC  .Nt.OX1.........
0260: C8 2D 18 A2 BC B2 15 4F   B7 28 6F D3 00 E1 72 9B  .-.....O.(o...r.
0270: 6C 10 00 00 82 00 80 4E   DD E7 77 F1 91 6B 31 4E  l......N..w..k1N
0280: FA D6 61 D9 69 82 BD 22   40 83 FD 76 E6 FF A7 18  ..a.i.."@..v....
0290: 95 A0 04 28 0D 0D F7 44   6F 0C 42 4F 17 77 A0 99  ...(...Do.BO.w..
02A0: 56 2A 13 77 28 0B 09 48   C1 B9 8C 09 ED 9F C6 2E  V*.w(..H........
02B0: 32 18 DB BD ED AF C3 AB   E7 AD 8F DF 9E AB 07 43  2..............C
02C0: B4 50 EF 74 98 EA FC E8   4D C9 DA FC B0 B2 C7 D4  .P.t....M.......
02D0: 83 50 B5 84 B8 44 86 7B   5D 8A C2 F8 04 80 06 E6  .P...D..].......
02E0: 84 42 33 B2 EE 05 E6 D3   48 0E 23 E5 1F 63 4C 53  .B3.....H.#..cLS
02F0: 98 B8 8C 45 BA C8 19                               ...E...

At this point, we have everything we need to generate the actual secrets.

SESSION KEYGEN:
PreMaster Secret:
0000: 03 01 84 54 F5 D6 EB F5   A8 08 BA FA 7A 22 61 2D  ...T........z"a-
0010: 75 DC 40 E8 98 F9 0E B2   87 80 B8 1A 8F 68 25 B8  u.@..........h%.
0020: 51 D0 54 45 61 8A 50 C9   BB 0E 39 53 45 78 BE 79  Q.TEa.P...9SEx.y
CONNECTION KEYGEN:
Client Nonce:
0000: 40 FC 30 AE 2D 63 84 BB   C5 4B 27 FD 58 21 CA 90  @.0.-c...K'.X!..
0010: 05 F6 A7 7B 37 BB 72 E1   FC 1D 1B 6A F5 1C C8 9F  ....7.r....j....
Server Nonce:
0000: 40 FC 31 10 79 AB 17 66   FA 8B 3F AA FD 5E 48 23  @.1.y..f..?..^H#
0010: FA 90 31 D8 3C B9 A3 2C   8C F5 E9 81 9B A2 63 6C  ..1.<..,......cl
Master Secret:
0000: B0 00 22 34 59 03 16 B7   7A 6C 56 9B 89 D2 7A CC  .."4Y..<.c.
Server MAC write Secret:
0000: 1E 4D D1 D3 0A 78 EE B7   4F EC 15 79 B2 59 18 40  .M...x..O..y.Y.@
Client write key:
0000: 10 D0 D6 C2 D9 B7 62 CB   2C 74 BF 5F 85 3C 6F E7  ......b.,t._.<o.
Server write key:
0000: 06 65 DF BD 16 4B A5 7D   8C 66 2A 80 C1 45 B4 F3  .e...K...f*..E..
... no IV for cipher
>

Send a quick confirmation to the server verifying that we know the private key corresponding to the client certificate we just sent.

*** CertificateVerify
[write] MD5 and SHA1 hashes:  len = 134
0000: 0F 00 00 82 00 80 45 41   43 4B 47 1D F0 EE D1 14  ......EACKG.....
0010: AE F9 B3 2C 1F B9 FE 7B   3E 91 50 C5 0F F1 57 4F  ...,....>.P...WO
0020: 55 F1 4B C3 79 16 A8 F1   72 6B 10 CA CC 83 02 FC  U.K.y...rk......
0030: 97 3D 04 29 44 4C 58 74   84 94 19 63 BB 8A 2C 78  .=.)DLXt...c..,x
0040: 43 A0 DD 5E 54 52 AA 97   15 92 1C 39 6B 10 2E BF  C..^TR.....9k...
0050: F2 DA AE 2D 8F FB 50 44   9E E2 1F 7D C9 C5 CB A0  ...-..PD........
0060: 31 A0 F9 AA 93 2D 1B 07   1B FA E0 EE 95 E7 88 D7  1....-..........
0070: AD 4A 3A 40 DC FB DF 9E   EB 75 04 14 E2 F2 BB DC  .J:@.....u......
0080: 1B 7E 6E D5 8C 62                                  ..n..b
main, WRITE: TLSv1 Handshake, length = 134
[Raw write]: length = 139
0000: 16 03 01 00 86 0F 00 00   82 00 80 45 41 43 4B 47  ...........EACKG
0010: 1D F0 EE D1 14 AE F9 B3   2C 1F B9 FE 7B 3E 91 50  ........,....>.P
0020: C5 0F F1 57 4F 55 F1 4B   C3 79 16 A8 F1 72 6B 10  ...WOU.K.y...rk.
0030: CA CC 83 02 FC 97 3D 04   29 44 4C 58 74 84 94 19  ......=.)DLXt...
0040: 63 BB 8A 2C 78 43 A0 DD   5E 54 52 AA 97 15 92 1C  c..,xC..^TR.....
0050: 39 6B 10 2E BF F2 DA AE   2D 8F FB 50 44 9E E2 1F  9k......-..PD...
0060: 7D C9 C5 CB A0 31 A0 F9   AA 93 2D 1B 07 1B FA E0  .....1....-.....
0070: EE 95 E7 88 D7 AD 4A 3A   40 DC FB DF 9E EB 75 04  ......J:@.....u.
0080: 14 E2 F2 BB DC 1B 7E 6E   D5 8C 62                 .......n..b

Almost finished! Tell the server we're changing to the newly established cipher suite. All further messages will be encrypted using the parameters we just established. We send an encrypted Finished message to verify everything worked.

main, WRITE: TLSv1 Change Cipher Spec, length = 1 
[Raw write]: length = 6
0000: 14 03 01 00 01 01                                  ......
*** Finished
verify_data:  { 242, 98, 66, 170, 124, 124, 204, 231, 73, 15, 237, 172 }
***
[write] MD5 and SHA1 hashes:  len = 16
0000: 14 00 00 0C F2 62 42 AA   7C 7C CC E7 49 0F ED AC  .....bB.....I...
Padded plaintext before ENCRYPTION:  len = 32
0000: 14 00 00 0C F2 62 42 AA   7C 7C CC E7 49 0F ED AC  .....bB.....I...
0010: FA 06 3C 9F 8C 41 1D ED   2B 06 D0 5A ED 31 F2 80  ..<..A..+..Z.1..  
main, WRITE: TLSv1 Handshake, length = 32

Note next that when the message above is actually written to the raw output device (following the 5 bytes of header information), the message is now encrypted.

[Raw write]: length = 37
0000: 16 03 01 00 20 15 8C 25   BA 4E 73 F5 27 79 49 B1  .... ..%.Ns.'yI.
0010: E9 F5 7E C8 48 A7 D3 A6   9B BD 6F 8E A5 8E 2B B7  ....H.....o...+.
0020: EE DC BD F4 D7                                     .....

We now wait for the server to send the same (Change Cipher Spec/Finshed), so we can know it completed negotiations successfully.

[Raw read]: length = 5
0000: 14 03 01 00 01                                     .....
[Raw read]: length = 1
0000: 01                                                 .
main, READ: TLSv1 Change Cipher Spec, length = 1
[Raw read]: length = 5
0000: 16 03 01 00 20                                     .... 
[Raw read]: length = 32
0000: 1F F5 FA C8 79 20 CE 91   AA 68 7F 6C F3 5A DB 7B  ....y ...h.l.Z..
0010: A5 1C 31 1F 6F 41 50 C5   C6 25 25 8D 48 50 3F F1  ..1.oAP..%%.HP?.
main, READ: TLSv1 Handshake, length = 32
Padded plaintext after DECRYPTION:  len = 32
0000: 14 00 00 0C 07 38 46 5F   62 AD 41 B3 DC 79 30 FD  .....8F_b.A..y0.
0010: 34 F2 3B 54 1C D4 68 0E   92 0B 9C 7E ED 47 9F 3B  4.;T..h......G.;
*** Finished
verify_data:  { 7, 56, 70, 95, 98, 173, 65, 179, 220, 121, 48, 253 }
***
[read] MD5 and SHA1 hashes:  len = 16
0000: 14 00 00 0C 07 38 46 5F   62 AD 41 B3 DC 79 30 FD  .....8F_b.A..y0.

Everything completed successfully! Let's cache the established session in case we want to reestablish this session after this connection is dropped.

At this point, a SSL/TLS client should examine the credentials of the peer to make sure that it is communicating with the expected server. A HttpsURLConnection would check the hostname and call HostnameVerifier if there was a problem, but the raw SSLSocket doesn't. This verification should be done by hand, but we're ignoring this for now.

So, after all that, we're finally ready to exchange application data. We send a "GET /index.html HTTP1.1" command.

%% Cached client session: [Session-1, SSL_RSA_WITH_RC4_128_MD5]
Padded plaintext before ENCRYPTION:  len = 42
0000: 47 45 54 20 2F 69 6E 64   65 78 2E 68 74 6D 6C 20  GET /index.html
0010: 48 54 54 50 2F 31 2E 31   0A 0A CA CB D1 10 9D 0E  HTTP/1.1........
0020: 13 3C D9 66 6B 9E 36 87   ED 9B                    .<.fk.6...
main, WRITE: TLSv1 Application Data, length = 42

Note again the data over the wire is encrypted (skipping the 5 header bytes).

[Raw write]: length = 47
0000: 17 03 01 00 2A 8A E9 EC   2C 8D 19 B6 E2 50 C1 E2  ....*...,....P..
0010: 22 1A C0 97 95 23 99 E1   20 DD F3 2A B4 DC 14 57  "....#.. ..*...W
0020: 32 71 58 98 01 BE 70 11   A3 FC 8E 3A 7C 8D BF     2qX...p....:...

We get the application data back. First the HTTPS header, then the actual data.

[Raw read]: length = 5
0000: 17 03 01 00 50                                     ....P
[Raw read]: length = 80
0000: 70 10 0D D6 FA ED 51 FC   C2 7E CE 24 2E F1 2F F7  p.....Q....$../.
0010: E7 CD A5 D6 2D 1B 10 FD   48 56 9C 1B B5 EC 8F 1E  ....-...HV......
0020: DB DA F9 83 62 52 15 38   70 4B C1 85 13 EF CA 17  ....bR.8pK......
0030: 89 37 D3 45 C0 88 BB 92   63 F6 9C DE 69 E6 60 3E  .7.E....c...i.`>
0040: 1F F7 4D C1 56 61 79 01   49 55 FB 38 6B 16 81 BC  ..M.Vay.IU.8k...
main, READ: TLSv1 Application Data, length = 80
Padded plaintext after DECRYPTION:  len = 80
0000: 48 54 54 50 2F 31 2E 30   20 32 30 30 20 4F 4B 0D  HTTP/1.0 200 OK.
0010: 0A 43 6F 6E 74 65 6E 74   2D 4C 65 6E 67 74 68 3A  .Content-Length:
0020: 20 35 38 0D 0A 43 6F 6E   74 65 6E 74 2D 54 79 70   58..Content-Typ
0030: 65 3A 20 74 65 78 74 2F   68 74 6D 6C 0D 0A 0D 0A  e: text/html....
0040: 40 18 A1 FF 1D 5A D4 55   98 DB E3 95 01 A0 91 AF  @....Z.U........
HTTP/1.0 200 OK
Content-Length: 58
Content-Type: text/html 
[Raw read]: length = 5
0000: 17 03 01 00 4A                                     ....J
[Raw read]: length = 74
0000: 75 DA F2 58 C3 5E 58 DE   14 AD FE 71 A3 78 07 58  u..X.^X....q.x.X
0010: EB E9 2B A2 D7 82 5C 6E   C9 9C 58 84 D7 A8 C6 F8  ..+...\n..X.....
0020: DE C6 5B BA 10 59 DF CC   11 AE 35 F7 C7 0F F6 C2  ..[..Y....5.....
0030: 3E 67 4E 95 30 AA 91 0B   E4 4F 5C C7 BF 50 AC 61  >gN.0....O\..P.a
0040: 87 B7 80 75 F0 81 F1 00   63 C9                    ...u....c.
main, READ: TLSv1 Application Data, length = 74
Padded plaintext after DECRYPTION:  len = 74
0000: 3C 48 54 4D 4C 3E 0A 3C   48 31 3E 48 65 6C 6C 6F  <HTML>.<H1>Hello
0010: 20 57 6F 72 6C 64 3C 2F   48 31 3E 0A 54 68 65 20   World</H1>.The 
0020: 74 65 73 74 20 69 73 20   63 6F 6D 70 6C 65 74 65  test is complete
0030: 21 0A 3C 2F 48 54 4D 4C   3E 0A 38 2E 68 72 F1 47  !.</HTML>.8.hr.G
0040: E8 56 D1 EA A6 FC 3C 30   6F F3                    .V....<0o.
 <HTML>
<H1>Hello World<H1>
The test is complete!
<HTML>

Read from the socket again to see if there is any more data. We get a close_notify message, which means this connection is shutting down properly. We send our own in turn, then close the socket.

[Raw read]: length = 5
0000: 15 03 01 00 12                                     .....
[Raw read]: length = 18
0000: 09 AB 95 00 43 8D C8 7C   83 18 EB C4 8C 99 43 A6  ....C.........C.
0010: 76 49                                              vI
main, READ: TLSv1 Alert, length = 18
Padded plaintext after DECRYPTION:  len = 18
0000: 01 00 FA 44 D5 57 71 5C   CC C7 D9 D0 04 23 10 D8  ...D.Wq\.....#..
0010: 21 7B                                              !.
main, RECV TLSv1 ALERT:  warning, close_notify
main, called closeInternal(false)
main, SEND TLSv1 ALERT:  warning, description = close_notify
Padded plaintext before ENCRYPTION:  len = 18
0000: 01 00 8A 2C A2 36 9C 88   22 50 6E BC 95 3B B2 C4  ...,.6.."Pn..;..
0010: FE F2                                              ..
main, WRITE: TLSv1 Alert, length = 18
[Raw write]: length = 23
0000: 15 03 01 00 12 19 BE 10   8D FA F1 CA DD AB CC 91  ................
0010: 2E 49 08 71 2B C1 05                               .I.q+..
main, called close()
main, called closeInternal(true)
main, called close()
main, called closeInternal(true)
main, called close()
main, called closeInternal(true)

Appendix A: Standard Names

The JDK Security API requires and uses a set of standard names for algorithms, certificates and keystore types.

The specification names previously found here in Appendix A and in the other security specifications (JCA, CertPath) have been combined in the Java Cryptography Architecture Standard Algorithm Name Documentation. Specific provider information can be found in the Oracle Providers.

Appendix B: Provider Pluggability

JSSE is fully pluggable and does not restrict the use of third-party JSSE providers in any way.

Appendix C JSSE Cipher Suite Parameters

Table 3-12 contains a list of additional JSSE cipher suite names related parameters. See Java Cryptography Architecture Standard Algorithm Name Documentation.

Table 3-12 JSSE Cipher Suite Parameters

Standard Name (IANA name if different) Key Exchange Algorithm Bulk Cipher Algorithm Message Authentication Code Algorithm

SSL_NULL_WITH_NULL_NULL

IANA: TLS_NULL_WITH_NULL_NULL

K_NULL

B_NULL

M_NULL

SSL_RSA_WITH_NULL_MD5

IANA: TLS_RSA_WITH_NULL_MD5

RSA

B_NULL

MD5

SSL_RSA_WITH_NULL_SHA

IANA: TLS_RSA_WITH_NULL_SHA

RSA

B_NULL

SHA-1

SSL_RSA_EXPORT_WITH_RC4_40_MD5

IANA: TLS_RSA_EXPORT_WITH_RC4_40_MD5

RSA_EXPORT

RC4_40

MD5

SSL_RSA_WITH_RC4_128_MD5

IANA: TLS_RSA_WITH_RC4_128_MD5

RSA

RC4

MD5

SSL_RSA_WITH_RC4_128_SHA

IANA: TLS_RSA_WITH_RC4_128_SHA

RSA

RC4

SHA-1

SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5

IANA: TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5

RSA_EXPORT

RC2_CBC_40

MD5

SSL_RSA_WITH_IDEA_CBC_SHA

IANA: TLS_RSA_WITH_IDEA_CBC_SHA

RSA

IDEA_CBC

SHA-1

SSL_RSA_EXPORT_WITH_DES40_CBC_SHA

IANA: TLS_RSA_EXPORT_WITH_DES40_CBC_SHA

RSA_EXPORT

DES40_CBC

SHA-1

SSL_RSA_WITH_DES_CBC_SHA

IANA: TLS_RSA_WITH_DES_CBC_SHA

RSA

DES_CBC

SHA-1

SSL_RSA_WITH_3DES_EDE_CBC_SHA

IANA: TLS_RSA_WITH_3DES_EDE_CBC_SHA

RSA

3DES_EDE_CBC

SHA-1

SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA

IANA: TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA

DH_DSS

DES40_CBC

SHA-1

SSL_DH_DSS_WITH_DES_CBC_SHA

IANA: TLS_DH_DSS_WITH_DES_CBC_SHA

DH_DSS

DES_CBC

SHA-1

SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA

IANA: TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA

DH_DSS

3DES_EDE_CBC

SHA-1

SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA

IANA: TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA

DH_RSA_EXPORT

DES40_CBC

SHA-1

SSL_DH_RSA_WITH_DES_CBC_SHA

IANA: TLS_DH_RSA_WITH_DES_CBC_SHA

DH_RSA

DES_CBC

SHA-1

SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA

IANA: TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA

DH_RSA

3DES_EDE_CBC

SHA-1

SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA

IANA: TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA

DHE_DSS_EXPORT

DES40_CBC

SHA-1

SSL_DHE_DSS_WITH_DES_CBC_SHA

IANA: TLS_DHE_DSS_WITH_DES_CBC_SHA

DHE_DSS

DES_CBC

SHA-1

SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA

IANA: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA

DHE_DSS

3DES_EDE_CBC

SHA-1

SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA

IANA: TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA

DHE_RSA_EXPORT

DES40_CBC

SHA-1

SSL_DHE_RSA_WITH_DES_CBC_SHA

IANA: TLS_DHE_RSA_WITH_DES_CBC_SHA

DHE_RSA

DES_CBC

SHA-1

SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA

IANA: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA

DHE_RSA

3DES_EDE_CBC

SHA-1

SSL_DH_anon_EXPORT_WITH_RC4_40_MD5

IANA: TLS_DH_anon_EXPORT_WITH_RC4_40_MD5

DH_anon_EXPORT

RC4_40

MD5

SSL_DH_anon_WITH_RC4_128_MD5

IANA: TLS_DH_anon_WITH_RC4_128_MD5

DH_anon

RC4

MD5

SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA

IANA: TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA

DH_anon

DES40_CBC

SHA-1

SSL_DH_anon_WITH_DES_CBC_SHA

IANA: TLS_DH_anon_WITH_DES_CBC_SHA

DH_anon

DES_CBC

SHA-1

SSL_DH_anon_WITH_3DES_EDE_CBC_SHA

IANA: TLS_DH_anon_WITH_3DES_EDE_CBC_SHA

DH_anon

3DES_EDE_CBC

SHA-1

TLS_KRB5_WITH_DES_CBC_SHA

KRB5

DES_CBC

SHA-1

TLS_KRB5_WITH_3DES_EDE_CBC_SHA

KRB5

3DES_EDE_CBC

SHA-1

TLS_KRB5_WITH_RC4_128_SHA

KRB5

RC4

SHA-1

TLS_KRB5_WITH_IDEA_CBC_SHA

KRB5

IDEA_CBC

SHA-1

TLS_KRB5_WITH_DES_CBC_MD5

KRB5

DES_CBC

MD5

TLS_KRB5_WITH_3DES_EDE_CBC_MD5

KRB5

3DES_EDE_CBC

MD5

TLS_KRB5_WITH_RC4_128_MD5

KRB5

RC4

MD5

TLS_KRB5_WITH_IDEA_CBC_MD5

KRB5

IDEA_CBC

MD5

TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA

KRB5_EXPORT

DES_CBC

SHA-1

TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA

KRB5_EXPORT

RC2_CBC_40

SHA-1

TLS_KRB5_EXPORT_WITH_RC4_40_SHA

KRB5_EXPORT

RC4_40

SHA-1

TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5

KRB5_EXPORT

DES_CBC

MD5

TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5

KRB5_EXPORT

RC2_CBC_40

MD5

TLS_KRB5_EXPORT_WITH_RC4_40_MD5

KRB5_EXPORT

RC4_40

MD5

TLS_PSK_WITH_NULL_SHA

PSK

B_NULL

SHA-1

TLS_DHE_PSK_WITH_NULL_SHA

DHE_PSK

B_NULL

SHA-1

TLS_RSA_PSK_WITH_NULL_SHA

RSA_PSK

B_NULL

SHA-1

TLS_RSA_WITH_AES_128_CBC_SHA

RSA

AES_128_CBC

SHA-1

TLS_DH_DSS_WITH_AES_128_CBC_SHA

DH_DSS

AES_128_CBC

SHA-1

TLS_DH_RSA_WITH_AES_128_CBC_SHA

DH_RSA

AES_128_CBC

SHA-1

TLS_DHE_DSS_WITH_AES_128_CBC_SHA

DHE_DSS

AES_128_CBC

SHA-1

TLS_DHE_RSA_WITH_AES_128_CBC_SHA

DHE_RSA

AES_128_CBC

SHA-1

TLS_DH_anon_WITH_AES_128_CBC_SHA

DH_anon

AES_128_CBC

SHA-1

TLS_RSA_WITH_AES_256_CBC_SHA

RSA

AES_256_CBC

SHA-1

TLS_DH_DSS_WITH_AES_256_CBC_SHA

DH_DSS

AES_256_CBC

SHA-1

TLS_DH_RSA_WITH_AES_256_CBC_SHA

DH_RSA

AES_256_CBC

SHA-1

TLS_DHE_DSS_WITH_AES_256_CBC_SHA

DHE_DSS

AES_256_CBC

SHA-1

TLS_DHE_RSA_WITH_AES_256_CBC_SHA

DHE_RSA

AES_256_CBC

SHA-1

TLS_DH_anon_WITH_AES_256_CBC_SHA

DH_anon

AES_256_CBC

SHA-1

TLS_RSA_WITH_NULL_SHA256

RSA

B_NULL

SHA-1

TLS_RSA_WITH_AES_128_CBC_SHA256

RSA

AES_128_CBC

SHA-256

TLS_RSA_WITH_AES_256_CBC_SHA256

RSA

AES_256_CBC

SHA-256

TLS_DH_DSS_WITH_AES_128_CBC_SHA256

DH_DSS

AES_128_CBC

SHA-256

TLS_DH_RSA_WITH_AES_128_CBC_SHA256

DH_RSA

AES_128_CBC

SHA-256

TLS_DHE_DSS_WITH_AES_128_CBC_SHA256

DHE_DSS

AES_128_CBC

SHA-256

TLS_RSA_WITH_CAMELLIA_128_CBC_SHA

RSA

CAMELLIA_128_CBC

SHA-1

TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA

DH_DSS

CAMELLIA_128_CBC

SHA-1

TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA

DH_RSA

CAMELLIA_128_CBC

SHA-1

TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA

DHE_DSS

CAMELLIA_128_CBC

SHA-1

TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA

DHE_RSA

CAMELLIA_128_CBC

SHA-1

TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA

DH_anon

CAMELLIA_128_CBC

SHA-1

TLS_DHE_RSA_WITH_AES_128_CBC_SHA256

DHE_RSA

AES_128_CBC

SHA-256

TLS_DH_DSS_WITH_AES_256_CBC_SHA256

DH_DSS

AES_256_CBC

SHA-256

TLS_DH_RSA_WITH_AES_256_CBC_SHA256

DH_RSA

AES_256_CBC

SHA-256

TLS_DHE_DSS_WITH_AES_256_CBC_SHA256

DHE_DSS

AES_256_CBC

SHA-256

TLS_DHE_RSA_WITH_AES_256_CBC_SHA256

DHE_RSA

AES_256_CBC

SHA-256

TLS_DH_anon_WITH_AES_128_CBC_SHA256

DH_anon

AES_128_CBC

SHA-256

TLS_DH_anon_WITH_AES_256_CBC_SHA256

DH_anon

AES_256_CBC

SHA-256

TLS_RSA_WITH_CAMELLIA_256_CBC_SHA

RSA

CAMELLIA_256_CBC

SHA-1

TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA

DH_DSS

CAMELLIA_256_CBC

SHA-1

TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA

DH_RSA

CAMELLIA_256_CBC

SHA-1

TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA

DHE_DSS

CAMELLIA_256_CBC

SHA-1

TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA

DHE_RSA

CAMELLIA_256_CBC

SHA-1

TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA

DH_anon

CAMELLIA_256_CBC

SHA-1

TLS_PSK_WITH_RC4_128_SHA

PSK

RC4

SHA-1

TLS_PSK_WITH_3DES_EDE_CBC_SHA

PSK

3DES_EDE_CBC

SHA-1

TLS_PSK_WITH_AES_128_CBC_SHA

PSK

AES_128_CBC

SHA-1

TLS_PSK_WITH_AES_256_CBC_SHA

PSK

AES_256_CBC

SHA-1

TLS_DHE_PSK_WITH_RC4_128_SHA

DHE_PSK

RC4

SHA-1

TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA

DHE_PSK

3DES_EDE_CBC

SHA-1

TLS_DHE_PSK_WITH_AES_128_CBC_SHA

DHE_PSK

AES_128_CBC

SHA-1

TLS_DHE_PSK_WITH_AES_256_CBC_SHA

DHE_PSK

AES_256_CBC

SHA-1

TLS_RSA_PSK_WITH_RC4_128_SHA

RSA_PSK

RC4

SHA-1

TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA

RSA_PSK

3DES_EDE_CBC

SHA-1

TLS_RSA_PSK_WITH_AES_128_CBC_SHA

RSA_PSK

AES_128_CBC

SHA-1

TLS_RSA_PSK_WITH_AES_256_CBC_SHA

RSA_PSK

AES_256_CBC

SHA-1

TLS_RSA_WITH_SEED_CBC_SHA

RSA

SEED_CBC

SHA-1

TLS_DH_DSS_WITH_SEED_CBC_SHA

DH_DSS

SEED_CBC

SHA-1

TLS_DH_RSA_WITH_SEED_CBC_SHA

DH_RSA

SEED_CBC

SHA-1

TLS_DHE_DSS_WITH_SEED_CBC_SHA

DHE_DSS

SEED_CBC

SHA-1

TLS_DHE_RSA_WITH_SEED_CBC_SHA

DHE_RSA

SEED_CBC

SHA-1

TLS_DH_anon_WITH_SEED_CBC_SHA

DH_anon

SEED_CBC

SHA-1

TLS_RSA_WITH_AES_128_GCM_SHA256

RSA

AES_128_GCM

SHA-256

TLS_RSA_WITH_AES_256_GCM_SHA384

RSA

AES_256_GCM

SHA-384

TLS_DHE_RSA_WITH_AES_128_GCM_SHA256

DHE_RSA

AES_128_GCM

SHA-256

TLS_DHE_RSA_WITH_AES_256_GCM_SHA384

DHE_RSA

AES_256_GCM

SHA-384

TLS_DH_RSA_WITH_AES_128_GCM_SHA256

DH_RSA

AES_128_GCM

SHA-256

TLS_DH_RSA_WITH_AES_256_GCM_SHA384

DH_RSA

AES_256_GCM

SHA-384

TLS_DHE_DSS_WITH_AES_128_GCM_SHA256

DHE_DSS

AES_128_GCM

SHA-256

TLS_DHE_DSS_WITH_AES_256_GCM_SHA384

DHE_DSS

AES_256_GCM

SHA-384

TLS_DH_DSS_WITH_AES_128_GCM_SHA256

DH_DSS

AES_128_GCM

SHA-256

TLS_DH_DSS_WITH_AES_256_GCM_SHA384

DH_DSS

AES_256_GCM

SHA-384

TLS_DH_anon_WITH_AES_128_GCM_SHA256

DH_anon

AES_128_GCM

SHA-256

TLS_DH_anon_WITH_AES_256_GCM_SHA384

DH_anon

AES_256_GCM

SHA-384

TLS_PSK_WITH_AES_128_GCM_SHA256

PSK

AES_128_GCM

SHA-256

TLS_PSK_WITH_AES_256_GCM_SHA384

PSK

AES_256_GCM

SHA-384

TLS_DHE_PSK_WITH_AES_128_GCM_SHA256

DHE_PSK

AES_128_GCM

SHA-256

TLS_DHE_PSK_WITH_AES_256_GCM_SHA384

DHE_PSK

AES_256_GCM

SHA-384

TLS_RSA_PSK_WITH_AES_128_GCM_SHA256

RSA_PSK

AES_128_GCM

SHA-256

TLS_RSA_PSK_WITH_AES_256_GCM_SHA384

RSA_PSK

AES_256_GCM

SHA-384

TLS_PSK_WITH_AES_128_CBC_SHA256

PSK

AES_128_CBC

SHA-256

TLS_PSK_WITH_AES_256_CBC_SHA384

PSK

AES_256_CBC

SHA-384

TLS_PSK_WITH_NULL_SHA256

PSK

B_NULL

SHA-256

TLS_PSK_WITH_NULL_SHA384

PSK

B_NULL

SHA-384

TLS_DHE_PSK_WITH_AES_128_CBC_SHA256

DHE_PSK

AES_128_CBC

SHA-256

TLS_DHE_PSK_WITH_AES_256_CBC_SHA384

DHE_PSK

AES_256_CBC

SHA-384

TLS_DHE_PSK_WITH_NULL_SHA256

DHE_PSK

B_NULL

SHA-256

TLS_DHE_PSK_WITH_NULL_SHA384

DHE_PSK

B_NULL

SHA-384

TLS_RSA_PSK_WITH_AES_128_CBC_SHA256

RSA_PSK

AES_128_CBC

SHA-256

TLS_RSA_PSK_WITH_AES_256_CBC_SHA384

RSA_PSK

AES_256_CBC

SHA-384

TLS_RSA_PSK_WITH_NULL_SHA256

RSA_PSK

B_NULL

SHA-256

TLS_RSA_PSK_WITH_NULL_SHA384

RSA_PSK

B_NULL

SHA-384

TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256

RSA

CAMELLIA_128_CBC

SHA-256

TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256

DH_DSS

CAMELLIA_128_CBC

SHA-256

TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256

DH_RSA

CAMELLIA_128_CBC

SHA-256

TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256

DHE_DSS

CAMELLIA_128_CBC

SHA-256

TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256

DHE_RSA

CAMELLIA_128_CBC

SHA-256

TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256

DH_anon

CAMELLIA_128_CBC

SHA-256

TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256

RSA

CAMELLIA_256_CBC

SHA-256

TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256

DH_DSS

CAMELLIA_256_CBC

SHA-256

TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256

DH_RSA

CAMELLIA_256_CBC

SHA-256

TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256

DHE_DSS

CAMELLIA_256_CBC

SHA-256

TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256

DHE_RSA

CAMELLIA_256_CBC

SHA-256

TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256

DH_anon

CAMELLIA_256_CBC

SHA-256

TLS_EMPTY_RENEGOTIATION_INFO_SCSV

Not applicable

Not applicable

Not applicable

TLS_FALLBACK_SCSV

Not applicable

Not applicable

Not applicable

TLS_ECDH_ECDSA_WITH_NULL_SHA

ECDH_ECDSA

B_NULL

SHA-1

TLS_ECDH_ECDSA_WITH_RC4_128_SHA

ECDH_ECDSA

RC4

SHA-1

TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA

ECDH_ECDSA

3DES_EDE_CBC

SHA-1

TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA

ECDH_ECDSA

AES_128_CBC

SHA-1

TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA

ECDH_ECDSA

AES_256_CBC

SHA-1

TLS_ECDHE_ECDSA_WITH_NULL_SHA

ECDHE_ECDSA

B_NULL

SHA-1

TLS_ECDHE_ECDSA_WITH_RC4_128_SHA

ECDHE_ECDSA

RC4

SHA-1

TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA

ECDHE_ECDSA

3DES_EDE_CBC

SHA-1

TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA

ECDHE_ECDSA

AES_128_CBC

SHA-1

TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA

ECDHE_ECDSA

AES_256_CBC

SHA-1

TLS_ECDH_RSA_WITH_NULL_SHA

ECDH_RSA

B_NULL

SHA-1

TLS_ECDH_RSA_WITH_RC4_128_SHA

ECDH_RSA

RC4

SHA-1

TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA

ECDH_RSA

3DES_EDE_CBC

SHA-1

TLS_ECDH_RSA_WITH_AES_128_CBC_SHA

ECDH_RSA

AES_128_CBC

SHA-1

TLS_ECDH_RSA_WITH_AES_256_CBC_SHA

ECDH_RSA

AES_256_CBC

SHA-1

TLS_ECDHE_RSA_WITH_NULL_SHA

ECDHE_RSA

B_NULL

SHA-1

TLS_ECDHE_RSA_WITH_RC4_128_SHA

ECDHE_RSA

RC4

SHA-1

TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA

ECDHE_RSA

3DES_EDE_CBC

SHA-1

TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

ECDHE_RSA

AES_128_CBC

SHA-1

TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA

ECDHE_RSA

AES_256_CBC

SHA-1

TLS_ECDH_anon_WITH_NULL_SHA

ECDH_anon

B_NULL

SHA-1

TLS_ECDH_anon_WITH_RC4_128_SHA

ECDH_anon

RC4

SHA-1

TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA

ECDH_anon

3DES_EDE_CBC

SHA-1

TLS_ECDH_anon_WITH_AES_128_CBC_SHA

ECDH_anon

AES_128_CBC

SHA-1

TLS_ECDH_anon_WITH_AES_256_CBC_SHA

ECDH_anon

AES_256_CBC

SHA-1

TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA

SRP_SHA

3DES_EDE_CBC

SHA-1

TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA

SRP_SHA

3DES_EDE_CBC

SHA-1

TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA

SRP_SHA

3DES_EDE_CBC

SHA-1

TLS_SRP_SHA_WITH_AES_128_CBC_SHA

SRP_SHA

AES_128_CBC

SHA-1

TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA

SRP_SHA

AES_128_CBC

SHA-1

TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA

SRP_SHA

AES_128_CBC

SHA-1

TLS_SRP_SHA_WITH_AES_256_CBC_SHA

SRP_SHA

AES_256_CBC

SHA-1

TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA

SRP_SHA

AES_256_CBC

SHA-1

TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA

SRP_SHA

AES_256_CBC

SHA-1

TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256

ECDHE_ECDSA

AES_128_CBC

SHA-256

TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384

ECDHE_ECDSA

AES_256_CBC

SHA-384

TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256

ECDH_ECDSA

AES_128_CBC

SHA-256

TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384

ECDH_ECDSA

AES_256_CBC

SHA-384

TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256

ECDHE_RSA

AES_128_CBC

SHA-256

TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

ECDHE_RSA

AES_256_CBC

SHA-384

TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256

ECDH_RSA

AES_128_CBC

SHA-256

TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384

ECDH_RSA

AES_256_CBC

SHA-384

TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256

ECDHE_ECDSA

AES_128_GCM

SHA-256

TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

ECDHE_ECDSA

AES_256_GCM

SHA-384

TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256

ECDH_ECDSA

AES_128_GCM

SHA-256

TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384

ECDH_ECDSA

AES_256_GCM

SHA-384

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

ECDHE_RSA

AES_128_GCM

SHA-256

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

ECDHE_RSA

AES_256_GCM

SHA-384

TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256

ECDH_RSA

AES_128_GCM

SHA-256

TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384

ECDH_RSA

AES_256_GCM

SHA-384

TLS_ECDHE_PSK_WITH_RC4_128_SHA

ECDHE_PSK

RC4

SHA-1

TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA

ECDHE_PSK

3DES_EDE_CBC

SHA-1

TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA

ECDHE_PSK

AES_128_CBC

SHA-1

TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA

ECDHE_PSK

AES_256_CBC

SHA-1

TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256

ECDHE_PSK

AES_128_CBC

SHA-256

TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384

ECDHE_PSK

AES_256_CBC

SHA-384

TLS_ECDHE_PSK_WITH_NULL_SHA

ECDHE_PSK

B_NULL

SHA-1

TLS_ECDHE_PSK_WITH_NULL_SHA256

ECDHE_PSK

B_NULL

SHA-256

TLS_ECDHE_PSK_WITH_NULL_SHA384

ECDHE_PSK

B_NULL

SHA-384

TLS_RSA_WITH_ARIA_128_CBC_SHA256

RSA

ARIA_128_CBC

SHA-256

TLS_RSA_WITH_ARIA_256_CBC_SHA384

RSA

ARIA_256_CBC

SHA-384

TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256

DH_DSS

ARIA_128_CBC

SHA-256

TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384

DH_DSS

ARIA_256_CBC

SHA-384

TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256

DH_RSA

ARIA_128_CBC

SHA-256

TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384

DH_RSA

ARIA_256_CBC

SHA-384

TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256

DHE_DSS

ARIA_128_CBC

SHA-256

TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384

DHE_DSS

ARIA_256_CBC

SHA-384

TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256

DHE_RSA

ARIA_128_CBC

SHA-256

TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384

DHE_RSA

ARIA_256_CBC

SHA-384

TLS_DH_anon_WITH_ARIA_128_CBC_SHA256

DH_anon

ARIA_128_CBC

SHA-256

TLS_DH_anon_WITH_ARIA_256_CBC_SHA384

DH_anon

ARIA_256_CBC

SHA-384

TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256

ECDHE_ECDSA

ARIA_128_CBC

SHA-256

TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384

ECDHE_ECDSA

ARIA_256_CBC

SHA-384

TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256

ECDH_ECDSA

ARIA_128_CBC

SHA-256

TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384

ECDH_ECDSA

ARIA_256_CBC

SHA-384

TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256

ECDHE_RSA

ARIA_128_CBC

SHA-256

TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384

ECDHE_RSA

ARIA_256_CBC

SHA-384

TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256

ECDH_RSA

ARIA_128_CBC

SHA-256

TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384

ECDH_RSA

ARIA_256_CBC

SHA-384

TLS_RSA_WITH_ARIA_128_GCM_SHA256

RSA

ARIA_128_GCM

SHA-256

TLS_RSA_WITH_ARIA_256_GCM_SHA384

RSA

ARIA_256_GCM

SHA-384

TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256

DHE_RSA

ARIA_128_GCM

SHA-256

TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384

DHE_RSA

ARIA_256_GCM

SHA-384

TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256

DH_RSA

ARIA_128_GCM

SHA-256

TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384

DH_RSA

ARIA_256_GCM

SHA-384

TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256

DHE_DSS

ARIA_128_GCM

SHA-256

TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384

DHE_DSS

ARIA_256_GCM

SHA-384

TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256

DH_DSS

ARIA_128_GCM

SHA-256

TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384

DH_DSS

ARIA_256_GCM

SHA-384

TLS_DH_anon_WITH_ARIA_128_GCM_SHA256

DH_anon

ARIA_128_GCM

SHA-256

TLS_DH_anon_WITH_ARIA_256_GCM_SHA384

DH_anon

ARIA_256_GCM

SHA-384

TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256

ECDHE_ECDSA

ARIA_128_GCM

SHA-256

TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384

ECDHE_ECDSA

ARIA_256_GCM

SHA-384

TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256

ECDH_ECDSA

ARIA_128_GCM

SHA-256

TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384

ECDH_ECDSA

ARIA_256_GCM

SHA-384

TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256

ECDHE_RSA

ARIA_128_GCM

SHA-256

TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384

ECDHE_RSA

ARIA_256_GCM

SHA-384

TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256

ECDH_RSA

ARIA_128_GCM

SHA-256

TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384

ECDH_RSA

ARIA_256_GCM

SHA-384

TLS_PSK_WITH_ARIA_128_CBC_SHA256

PSK

ARIA_128_CBC

SHA-256

TLS_PSK_WITH_ARIA_256_CBC_SHA384

PSK

ARIA_256_CBC

SHA-384

TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256

DHE_PSK

ARIA_128_CBC

SHA-256

TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384

DHE_PSK

ARIA_256_CBC

SHA-384

TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256

RSA_PSK

ARIA_128_CBC

SHA-256

TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384

RSA_PSK

ARIA_256_CBC

SHA-384

TLS_PSK_WITH_ARIA_128_GCM_SHA256

PSK

ARIA_128_GCM

SHA-256

TLS_PSK_WITH_ARIA_256_GCM_SHA384

PSK

ARIA_256_GCM

SHA-384

TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256

DHE_PSK

ARIA_128_GCM

SHA-256

TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384

DHE_PSK

ARIA_256_GCM

SHA-384

TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256

RSA_PSK

ARIA_128_GCM

SHA-256

TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384

RSA_PSK

ARIA_256_GCM

SHA-384

TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256

ECDHE_PSK

ARIA_128_CBC

SHA-256

TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384

ECDHE_PSK

ARIA_256_CBC

SHA-384

TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256

ECDHE_ECDSA

CAMELLIA_128_CBC

SHA-256

TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384

ECDHE_ECDSA

CAMELLIA_256_CBC

SHA-384

TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256

ECDH_ECDSA

CAMELLIA_128_CBC

SHA-256

TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384

ECDH_ECDSA

CAMELLIA_256_CBC

SHA-384

TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256

ECDHE_RSA

CAMELLIA_128_CBC

SHA-256

TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384

ECDHE_RSA

CAMELLIA_256_CBC

SHA-384

TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256

ECDH_RSA

CAMELLIA_128_CBC

SHA-256

TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384

ECDH_RSA

CAMELLIA_256_CBC

SHA-384

TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256

RSA

CAMELLIA_128_GCM

SHA-256

TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384

RSA

CAMELLIA_256_GCM

SHA-384

TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256

DHE_RSA

CAMELLIA_128_GCM

SHA-256

TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384

DHE_RSA

CAMELLIA_256_GCM

SHA-384

TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256

DH_RSA

CAMELLIA_128_GCM

SHA-256

TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384

DH_RSA

CAMELLIA_256_GCM

SHA-384

TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256

DHE_DSS

CAMELLIA_128_GCM

SHA-256

TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384

DHE_DSS

CAMELLIA_256_GCM

SHA-384

TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256

DH_DSS

CAMELLIA_128_GCM

SHA-256

TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384

DH_DSS

CAMELLIA_256_GCM

SHA-384

TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256

DH_anon

CAMELLIA_128_GCM

SHA-256

TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384

DH_anon

CAMELLIA_256_GCM

SHA-384

TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256

ECDHE_ECDSA

CAMELLIA_128_GCM

SHA-256

TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384

ECDHE_ECDSA

CAMELLIA_256_GCM

SHA-384

TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256

ECDH_ECDSA

CAMELLIA_128_GCM

SHA-256

TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384

ECDH_ECDSA

CAMELLIA_256_GCM

SHA-384

TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256

ECDHE_RSA

CAMELLIA_128_GCM

SHA-256

TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384

ECDHE_RSA

CAMELLIA_256_GCM

SHA-384

TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256

ECDH_RSA

CAMELLIA_128_GCM

SHA-256

TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384

ECDH_RSA

CAMELLIA_256_GCM

SHA-384

TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256

PSK

CAMELLIA_128_GCM

SHA-256

TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384

PSK

CAMELLIA_256_GCM

SHA-384

TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256

DHE_PSK

CAMELLIA_128_GCM

SHA-256

TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384

DHE_PSK

CAMELLIA_256_GCM

SHA-384

TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256

RSA_PSK

CAMELLIA_128_GCM

SHA-256

TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384

RSA_PSK

CAMELLIA_256_GCM

SHA-384

TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256

PSK

CAMELLIA_128_CBC

SHA-256

TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384

PSK

CAMELLIA_256_CBC

SHA-384

TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256

DHE_PSK

CAMELLIA_128_CBC

SHA-256

TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384

DHE_PSK

CAMELLIA_256_CBC

SHA-384

TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256

RSA_PSK

CAMELLIA_128_CBC

SHA-256

TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384

RSA_PSK

CAMELLIA_256_CBC

SHA-384

TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256

ECDHE_PSK

CAMELLIA_128_CBC

SHA-256

TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384

ECDHE_PSK

CAMELLIA_256_CBC

SHA-384

TLS_RSA_WITH_AES_128_CCM

RSA

AES_128_CCM

CCM

TLS_RSA_WITH_AES_256_CCM

RSA

AES_256_CCM

CCM

TLS_DHE_RSA_WITH_AES_128_CCM

DHE_RSA

AES_128_CCM

CCM

TLS_DHE_RSA_WITH_AES_256_CCM

DHE_RSA

AES_256_CCM

CCM

TLS_RSA_WITH_AES_128_CCM_8

RSA

AES_128_CCM

CCM_8

TLS_RSA_WITH_AES_256_CCM_8

RSA

AES_256_CCM

CCM_8

TLS_DHE_RSA_WITH_AES_128_CCM_8

DHE_RSA

AES_128_CCM

CCM_8

TLS_DHE_RSA_WITH_AES_256_CCM_8

DHE_RSA

AES_256_CCM

CCM_8

TLS_PSK_WITH_AES_128_CCM

PSK

AES_128_CCM

CCM

TLS_PSK_WITH_AES_256_CCM

PSK

AES_256_CCM

CCM

TLS_DHE_PSK_WITH_AES_128_CCM

DHE_PSK

AES_128_CCM

CCM

TLS_DHE_PSK_WITH_AES_256_CCM

DHE_PSK

AES_256_CCM

CCM

TLS_PSK_WITH_AES_128_CCM_8

PSK

AES_128_CCM

CCM_8

TLS_PSK_WITH_AES_256_CCM_8

PSK

AES_256_CCM

CCM_8

TLS_DHE_PSK_WITH_AES_128_CCM_8

DHE_PSK

AES_128_CCM

CCM_8

TLS_DHE_PSK_WITH_AES_256_CCM_8

DHE_PSK

AES_256_CCM

CCM_8

TLS_ECDHE_ECDSA_WITH_AES_128_CCM

ECDHE_ECDSA

AES_128_CCM

CCM

TLS_ECDHE_ECDSA_WITH_AES_256_CCM

ECDHE_ECDSA

AES_256_CCM

CCM

TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8

ECDHE_ECDSA

AES_128_CCM

CCM_8

TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8

ECDHE_ECDSA

AES_256_CCM

CCM_8

TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256

ECDHE_RSA

AEAD_CHACHA20_POLY1305

SHA-256

TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256

ECDHE_ECDSA

AEAD_CHACHA20_POLY1305

SHA-256

TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256

DHE_RSA

AEAD_CHACHA20_POLY1305

SHA-256

TLS_PSK_WITH_CHACHA20_POLY1305_SHA256

PSK

AEAD_CHACHA20_POLY1305

SHA-256

TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256

ECDHE_PSK

AEAD_CHACHA20_POLY1305

SHA-256

TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256

DHE_PSK

AEAD_CHACHA20_POLY1305

SHA-256

TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256

RSA_PSK

AEAD_CHACHA20_POLY1305

SHA-256