Java Secure Socket Extension (JSSE) Reference Guide


Introduction

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

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

By abstracting the complex underlying security algorithms and handshaking mechanisms, JSSE minimizes the risk of creating subtle but dangerous security vulnerabilities. Furthermore, it simplifies application development by serving as a building block 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 supports the following security protocols:

These security protocols encapsulate a normal bidirectional stream socket, and the JSSE API adds transparent support for authentication, encryption, and integrity protection.

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. This 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 stream socket API.

The JSSE API was designed to allow other SSL/TLS 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 features:

JSSE Standard API

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

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:

More information about this provider is available in the SunJSSE section of the Oracle Providers Documentation.

Related Documentation

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

Terms and Definitions

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

authentication

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

cipher suite

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

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 Comodo, DigiCert, and GoDaddy. X509 is a common certificate format that can be managed by the JDK's keytool.

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 is a one-way function, meaning that it is not possible to produce the original data from the hash; a small change in the original data produces a large change in the resulting hash; and it does not require a cryptographic key.

Cryptographic Service Provider

Sometimes referred to simply as provider 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.

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.

handshake protocol

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

key agreement

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 cannot 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 Secure Hash Algorithm (SHA-256), 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.

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.

trust manager

See key manager/trust manager.

truststore

See keystore/truststore.

Transport Layer Security (TLS) Protocol Overview

Transport Layer Security (TLS) is the most widely used protocol for implementing cryptography on the web. TLS uses a combination of cryptographic processes to provide secure communication over a network. The page Transport Layer Security (TLS) Protocol Overview provides an introduction to TLS and the cryptographic processes it uses.

JSSE Classes and Interfaces

To communicate securely, both sides of the connection must be SSL-enabled. In the JSSE API, the endpoint classes of the connection are SSLSocket and SSLEngine. In the figure JSSE Classes Used to Create SSLSocket and SSLEngine, the major classes used to create SSLSocket and SSLEngine are laid out in a logical ordering. The text following the diagram, explains the contents of the illustration.

This image illustrates the JSSE classes required to create SSLEngine
and SSLSocket classes. The image also describes the JSSE classes and
interfaces and their relationships. The sections following this image
describe these classes and interfaces.

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 the method SSLParameters.setEndpointIdentificationAlgorithm. For example, the host name in a URL should match 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.

SocketFactory and ServerSocketFactory Classes

The abstract javax.net.SocketFactory class is used to create sockets. Subclasses of this 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.

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

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

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:

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:

Cipher Suite Choice and Remote Entity Verification

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 the SSLParameters.getEndpointIdentificationAlgorithm method.

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 the SSLParameters.getEndpointIdentificationAlgorithm method. Alternatively, applications can use the HostnameVerifier interface to override the default HTTPS host name rules.

SSLEngine Class

TLS 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 TLS with different I/O and threading models to satisfy the applications' performance, scalability, footprint, and other requirements. There are demands to use TLS 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 TLS protocol 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 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) 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 a TLS state machine and operates on inbound and outbound byte buffers supplied by the user of the SSLEngine class. The diagram Flow of Data Through SSLEngine illustrates the flow of data from the application, through SSLEngine, to the transport mechanism, and back.

The following text describes this figure.

The application, shown on the left, supplies application (plaintext) data in an application buffer and passes it to SSLEngine. The SSLEngine object processes the data contained in the buffer, or any handshaking data, to produce TLS encoded data and places it to the network buffer supplied by the application. The application is then responsible for using an appropriate transport (shown on the right) to send the contents of the network buffer to its peer. Upon receiving TLS encoded data from its peer (via the transport), the application places the data into a network buffer and passes it to SSLEngine. The SSLEngine object processes the network buffer's contents to produce handshaking data or application data.

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

Understanding SSLEngine Operation Statuses

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 the example Using a Nonblocking SocketChannel. 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:

The example Handling BUFFER_UNDERFLOW and BUFFER_OVERFLOW 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.

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

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 statuses are available:

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

The example Checking and Processing Handshaking Statuses and Overall Statuses 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
...
}

SSLEngine for TLS Protocols

This section shows you how to create an SSLEngine object and use it to generate and process TLS data.

Creating an SSLEngine Object

To create an SSLEngine object, you use the SSLContext.createSSLEngine() method. 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 to require client authentication. The SSLContext.createSSLEngine method creates a javax.net.ssl.SSLEngine object.

The example Creating an SSLEngine Client for TLS with JKS as Keystore illustrates how to create an SSLEngine client for TLS that uses JKS as keystore.


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.


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("PKIX");
kmf.init(ksKeys, passphrase);

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

// Get an instance of SSLContext for 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 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.

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 figure State Machine during TLS Handshake shows the state machine during a typical TLS handshake, with corresponding messages and statuses:

The following text describes this image.

The following steps are performed before the status of the handshake is determined:

This image illustrates some of the possible handshake statuses. The section Understanding SSLEngine Operation Statuses describes these statuses in more detail:

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.

The example Using a Nonblocking SocketChannel shows an SSL application that uses a nonblocking SocketChannel to communicate with its peer.


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


In the example Using a Nonblocking SocketChannel, the string hello is sent to the peer by encoding it using the SSLEngine created in the example Creating an SSLEngine Client for TLS with JKS as Keystore. It uses information from the SSLSession to determine how large the byte buffers should be.

// 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 to use 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 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 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
...
}

The example Reading Data From Nonblocking SocketChannel illustrates how to read data from the same nonblocking SocketChannel and extract the plaintext data from it by using the SSLEngine created in the example Creating an SSLEngine Client for TLS with JKS as Keystore. Each iteration of this code may or may not produce plaintext data, depending on whether handshaking is in progress.

// Read SSL/TLS 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
...
}

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

For an orderly shutdown of an SSL/TLS connection, the SSL/TLS protocols require transmission of close messages. Therefore, when an application is done with the SSL/TLS 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. Example 6 illustrates this.

// 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();

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 6), 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 perspective. Then the application should still try to shut down cleanly by using the procedure in Example 6. Obviously, unlike SSLSocket, the application using SSLEngine must deal with more state transitions, statuses, and programming. For more information about writing an SSLEngine-based application, see Sample Code Illustrating the Use of an SSLEngine.

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.

In Java SE, a TLS 1.2 session is represented by ExtendedSSLSession, an implementation of SSLSession. 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. 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 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. For more information about how HTTPS URLs are constructed and used, see the API specification sections about the java.net.URL, java.net.URLConnection, java.net.HttpURLConnection, and javax.net.ssl.HttpURLConnection 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. If the implementation cannot determine a host name match with reasonable certainty, then the SSL implementation performs a callback to the instance's assigned HostnameVerifier for further checking. The host name verifier can take whatever steps are necessary to make the determination, such as performing host name pattern matching or perhaps opening an interactive dialog box. An unsuccessful verification by the host name verifier closes the connection. For more information regarding host name verification, see RFC 2818.

The setHostnameVerifier() and setDefaultHostnameVerifier() methods operate in a similar manner to the setSSLSocketFactory() and setDefaultSSLSocketFactory() methods, in that HostnameVerifier objects are assigned on a per-instance and per-class basis, and the current values can be obtained by a call to the getHostnameVerifier() or getDefaultHostnameVerifier() method.

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. For more information about providers and engine classes, see the "Design Principles" and "Concepts" sections of the Java Cryptography Architecture Reference Guide.

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. The following table lists implementations supplied by SunJSSE.

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, TLSv1.3 (since JDK 8u261)

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 SSL socket factories and SSL engines. 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.

Obtaining and Initializing the SSLContext Class

There are two ways to obtain and initialize an SSLContext:

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.

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.2") 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. Therefore, you do not have to directly create and initialize an SSLContext object (unless you want to override the default behavior).

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:

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 "TLS") that describes the secure socket protocol desired. Common protocol names for SSLContext objects are defined in Appendix A.

An SSLContext can be obtained as follows:

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

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. For details, see the 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 the PKIX trust manager using the javax.net.ssl.CertPathTrustManagerParameters class.

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("PKCS12");
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);

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.

For more information about PKIX and the CertPath API, see the Java PKI Programmer's Guide.

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.


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

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.

The following example illustrates a 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("PKCS12");
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();
}
}

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);

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.

The following example 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 is can add other behavior. In the example, 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. 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:

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

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:

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 TLS connection:

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

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. The following example illustrates this functionality:

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 serverNames = new ArrayList<>(1);
serverNames.add(serverName);

SSLParameters params = sslSocket.getSSLParameters();
params.setServerNames(serverNames);
sslSocket.setSSLParameters(params);
// sslEngine.setSSLParameters(params);

In the preceding example, 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.

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. The selection honors the server's preference by default, which is the most secure setting. However, the server can choose to honor the client's preference rather than its own preference by invoking the method SSLParameters.setUseCipherSuitesOrder(false).

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.

For example:

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());

See The HttpsURLConnection Class for more information about how to assign the HostnameVerifier to the HttpsURLConnection.

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 The 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:

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:


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. The following tables summarize 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 Security Property or system property values. Sections following the table explain how to set such property values.

The following table shows items that are customized by setting a java.security.Security property:

Security Property Customized Item Default Value Notes
cert.provider.x509v1 Customizing the X509Certificate Implementation X509Certificate implementation from Oracle None
JCE encryption algorithms used by the SunJSSE provider Give alternative JCE algorithm providers a higher preference order than the SunJCE provider; see Customizing the Encryption Algorithm Providers. SunJCE implementations None
jdk.certpath.disabledAlgorithms1 Disabled certificate verification cryptographic algorithm (see Disabled and Restricted Cryptographic Algorithms) MD2, MD5, SHA1 jdkCA & usage TLSServer, RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, include jdk.disabled.namedCurves, SHA1 usage SignedJAR & denyAfter 2019-01-012 None
jdk.tls.disabledAlgorithms1 Disabled and Restricted Cryptographic Algorithms SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, ECDH, include jdk.disabled.namedCurves2 Disables specific algorithms (protocols versions, cipher suites, key exchange mechanisms, etc.) that will not be negotiated for TLS connections, even if they are enabled explicitly in an application
jdk.tls.keyLimits1 (since JDK 8u261) Limiting Amount of Data Algorithms May Encrypt with a Set of Keys AES/GCM/NoPadding KeyUpdate 2^37 Limits the amount of data an algorithm may encrypt with a specific set of keys; once this limit is reached, a KeyUpdate post-handshake message is sent, which requests that the current set of keys be updated.
jdk.tls.legacyAlgorithms1 Legacy Cryptographic Algorithms K_NULL, C_NULL, M_NULL, DH_anon, ECDH_anon, RC4_128, RC4_40, DES_CBC, DES40_CBC, 3DES_EDE_CBC2 Specifies which algorithms are considered legacy algorithms, which are not negotiated during TLS security parameters negotiation unless there are no other candidates.
jdk.tls.maxCertificateChainLength1 Certificate chain handling 10 Specifies the maximum allowed length of the certificate chain in TLS handshaking.
jdk.tls.maxHandshakeMessageSize1 Certificate chain handling 32768 (32 kilobytes) Specifies the maximum allowed size, in bytes, for the handshake message in TLS handshaking.
jdk.tls.server.defaultDHEParameters1 Diffie-Hellman groups Safe prime Diffie-Hellman groups in JDK TLS implementation Defines default finite field Diffie-Hellman ephemeral (DHE) parameters for Transport Layer Security (TLS) processing
ocsp.enable1 Client-Driven OCSP and OCSP Stapling false Enables client-driven Online Certificate Status Protocol (OCSP). You must also enable revocation checking; see Setting up a Java Client to use Client-Driven OCSP.
security.provider.n Cryptographic service provider; see Customizing the Provider Implementation and Customizing the Encryption Algorithm Providers Differs per platform; check the java.security Security Properties file. Specify the provider in the security.provider.n= line in the Security Properties file, where n is an integer whose value is equal or greater than 1.
ssl.KeyManagerFactory.algorithm Default key manager factory algorithm name (see Customizing the Default Key Managers and Trust Managers) SunX509 None
ssl.ServerSocketFactory.provider1 Default SSLServerSocketFactory implementation SSLServerSocketFactory implementation from Oracle None
ssl.SocketFactory.provider1 Default SSLSocketFactory implementation SSLSocketFactory implementation from Oracle None
ssl.TrustManagerFactory.algorithm Default trust manager factory algorithm name (see Customizing the Default Key Managers and Trust Managers) PKIX None

1This Security 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.

2The list of restricted, disabled, and legacy algorithms specified in these Security Properties may change; see the java.security file in your JDK installation for the latest values.

The following table shows items that are customized by setting a java.lang.System property.

System Property Customized Item Default Notes
com.sun.net.ssl.checkRevocation1 Revocation checking false You must enable revocation checking to enable client-driven OCSP; see Client-Driven OCSP and OCSP Stapling.
Customize via port field in the HTTPS URL* Default HTTPS port 443 None
https.cipherSuites1 Default cipher suites for HTTPS connections1 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[]) method. Note that this method sets the preference order of the ClientHello cipher suites directly from the String array passed to it.
https.protocols1 Default handshaking protocols for HTTPS connections. 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[]).
https.proxyHost1 Default proxy host None None
https.proxyPort1 Default proxy port 80 None
java.protocol.handler.pkgs Specifying an Alternative HTTPS Protocol Implementation Implementation from Oracle None
javax.net.ssl.keyStore1 Default keystore; see Customizing the Default Keystores and Truststores, Store Types, and Store Passwords 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.keyStorePassword1 Default keystore password; see Customizing the Default Keystores and Truststores, Store Types, and Store Passwords 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.keyStoreProvider1 Default keystore provider; see Customizing the Default Keystores and Truststores, Store Types, and Store Passwords None None
javax.net.ssl.keyStoreType1 Default keystore type; see Customizing the Default Keystores and Truststores, Store Types, and Store Passwords KeyStore.getDefaultType() None
javax.net.ssl.sessionCacheSize (since JDK 8u261) Default value for the maximum number of entries in the SSL session cache 20480 The session cache size can be set by calling the SSLSessionContext.setSessionCacheSize method or by setting the javax.net.ssl.sessionCachSize system property. If the cache size is not set, the default value is used.
javax.net.ssl.trustStore1 Default truststore; see Customizing the Default Keystores and Truststores, Store Types, and Store Passwords jssecacerts, if it exists; otherwise, cacerts 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).
javax.net.ssl.trustStorePassword1 Default truststore password; see Customizing the Default Keystores and Truststores, Store Types, and Store Passwords 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.trustStoreProvider1 Default truststore provider; see Customizing the Default Keystores and Truststores, Store Types, and Store Passwords None None
javax.net.ssl.trustStoreType1 Default truststore type; see Customizing the Default Keystores and Truststores, Store Types, and Store Passwords KeyStore.getDefaultType() None
jdk.tls.acknowledgeCloseNotify1 (since JDK 8u261) Specifying that close_notify Alert Is Sent When One Is Received false If the system property is set to true, then when the client or server receives a close_notify alert, it sends a corresponding close_notify alert and the connection is duplex closed.
jdk.tls.client.cipherSuites1 Client-side default enabled cipher suites; see Specifying Default Enabled Cipher Suites. See SunJSSE Cipher Suites for a list of currently implemented SunJSSE cipher suites for this JDK release, sorted by order of preference. Caution: These system properties can be used to configure weak cipher suites, or the configured cipher suites may be weak in the future. It is not recommended that you use these system properties without understanding the risks.
jdk.tls.client.disableExtensions1 Configuring Default Extensions None Blocks extensions used on the client side.
jdk.tls.client.protocols1 Default handshaking protocols for TLS clients. See The SunJSSE Provider. 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, TLSv1.3, and SSLv2Hello are not enabled.
jdk.tls.client.SignatureSchemes1 Contains a comma-separated list of supported signature scheme names that specifies the signature schemes that could be used for TLS connections on the client side. None Unrecognized or unsupported signature scheme names specified in the property are ignored. If this system property is not defined or empty, then the provider-specific default is used. The names are not case sensitive. For a list of signature scheme names, see Appendix D: Signature Schemes.
jdk.tls.ephemeralDHKeySize1 Customizing the Size of Ephemeral Diffie-Hellman Keys 2048 bits None
jdk.tls.namedGroups1 Customizing the supported named groups for TLS key exchange If this system property is not defined or the value is empty, then the implementation default groups and preferences will be used. This contains a comma-separated list within quotation marks of enabled named groups in preference order. For example: jdk.tls.namedGroups="secp521r1,secp256r1,ffdhe2048"
jdk.tls.rejectClientInitiatedRenegotiation1 Rejects client-initiated renegotiation on the server side. If this system property is true, then the server will not accept client initiated renegotiations and will fail with a fatal handshake_failure alert. Rejects server-side client-initialized renegotiation. false None
jdk.tls.server.cipherSuites1 Server-side default enabled cipher suites. See Specifying Default Enabled Cipher Suites See SunJSSE Cipher Suites to determine which cipher suites are enabled by default Caution: These system properties can be used to configure weak cipher suites, or the configured cipher suites may be weak in the future. It is not recommended that you use these system properties without understanding the risks.
jdk.tls.server.disableExtensions1 Configuring Default Extensions None Blocks extensions used on the server side.
jdk.tls.server.protocols1 (since JDK 8u261) Default handshaking protocols for TLS servers. See The SunJSSE Provider. None To configure the default enabled protocol suite in the server side of a SunJSSE provider, specify the protocols in a comma-separated list within quotation marks. The protocols in this list are standard SSL protocol names as described in Java Security Standard Algorithms. Note that this system property impacts only the default protocol suite (SSLContext of the algorithms SSL and TLS). If an application uses a version-specific SSLContext (SSLv3, TLSv1, TLSv1.1, TLSv1.2, or TLSv1.3), or sets the enabled protocol version explicitly, this system property has no impact.
jdk.tls.server.SignatureSchemes1 Contains a comma-separated list of supported signature scheme names that specifies the signature schemes that could be used for TLS connections on the server side. None Unrecognized or unsupported signature scheme names specified in the property are ignored. If this system property is not defined or empty, then the provider-specific default is used. The names are not case sensitive. For a list of signature scheme names, see Appendix D: Signature Schemes.
jsse.enableFFDHEExtension1 (since JDK 8u261) Enables or disables Finite Field Diffie-Hellman Ephemeral (FFDHE) parameters for TLS key exchange true FFDHE is a TLS extension defined in RFC 7919. It enables TLS connections to use known finite field Diffie-Hellman groups. Some very old TLS vendors may not be able handle TLS extensions. In this case, set this property to false to disable the FFDHE extension.
jsse.enableMFLNExtension1 (since JDK 8u261) Customizing Maximum Fragment Length Negotiation (MFLN) Extension false None
jsse.enableSNIExtension1 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 TLS vendors may not be able handle TLS extensions. In this case, set this property to false to disable the SNI extension
jsse.SSLEngine.acceptLargeFragments1 Default sizing buffers for large TLS packets None Setting this system property to true, SSLSession will size buffers to handle large data packets by default (see the note in SSLSession and ExtendedSSLSession. This may cause applications to allocate unnecessarily large SSLEngine buffers. Instead, applications should dynamically check for buffer overflow conditions and resize buffers as appropriate (see Understanding SSLEngine Operation Statuses).
jdk.tls.client.enableStatusRequestExtension1 Setting up a Java Client to use Client-Driven OCSP false If true, then the status_request and status_request_v2 extensions are enabled, and processing for CertificateStatus messages sent by the server is enabled.
jdk.tls.server.enableStatusRequestExtension1 Setting Up a Java Server to Use OCSP Stapling false If true, then server-side support for OCSP stapling is enabled
sun.security.ssl.allowLegacyHelloMessages Allow legacy Hello Messages (Renegotiations) true If true, then allow the peer to handshake without requiring the proper RFC 5746 messages. See Description of the Phase 2 Fix in Transport Layer Security (TLS) Renegotiation Issue for more information.
sun.security.ssl.allowUnsafeRenegotiation Allow unsafe SSL/TLS renegotiations false If true, then permit full (unsafe) legacy negotiation. See Description of the Phase 2 Fix in Transport Layer Security (TLS) Renegotiation Issue for more information.

1This system 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.security.Security Property

You can customize some aspects of JSSE by setting security properties. You can set a Security Property either statically or dynamically:

How to Specify a java.lang.System Property

You can customize some aspects of JSSE by setting system properties. There are several ways to set these properties: