Data that travels across a network can easily be accessed bysomeone who is not the intended recipient. When the data includesprivate information, such as passwords and credit card numbers,steps must be taken to make the data unintelligible to unauthorizedparties. It is also important to ensure that the data has not beenmodified, either intentionally or unintentionally, duringtransport. The Secure Sockets Layer (SSL) and Transport LayerSecurity (TLS) protocols were designed to help protect the privacyand integrity of data while it is being transferred across anetwork.
The Java Secure Socket Extension (JSSE) enables secure Internetcommunications. It provides a framework and an implementation for aJava version of the SSL and TLS protocols and includesfunctionality for data encryption, server authentication, messageintegrity, and optional client authentication. Using JSSE,developers can provide for the secure passage of data between aclient and a server running any application protocol (such as HTTP,Telnet, or FTP) over TCP/IP. For an introduction to TLS, seeTransport Layer Security (TLS) Protocol Overview.
By abstracting the complex underlying security algorithms andhandshaking mechanisms, JSSE minimizes the risk of creating subtlebut dangerous security vulnerabilities. Furthermore, it simplifiesapplication development by serving as a building block thatdevelopers can integrate directly into their applications.
JSSE provides both an application programming interface (API)framework and an implementation of that API. The JSSE APIsupplements the core network and cryptographic services defined bythejava.security andjava.net packagesby providing extended networking socket classes, trust managers,key managers, SSL contexts, and a socket factory framework forencapsulating socket creation behavior. Because theSSLSocket class is based on a blocking I/O model, theJava Development Kit (JDK) includes a nonblockingSSLEngine class to enable implementations to choosetheir 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 isbased on the same design principles found elsewhere in theJava Cryptography Architecture(JCA) framework. This framework for cryptography-relatedsecurity components allows them to have implementation independenceand, whenever possible, algorithm independence. JSSE uses thecryptographicservice providers defined by the JCA framework.
Other security components in the Java SE platform include theJava Authentication andAuthorization Service (JAAS) and theJava Security Tools. JSSEencompasses many of the same concepts and algorithms as those inJCA but automatically applies them underneath a simple streamsocket API.
The JSSE API was designed to allow other SSL/TLS protocol andPublic Key Infrastructure (PKI) implementations to be plugged inseamlessly. Developers can also provide alternative logic todetermine if remote hosts should be trusted or what authenticationkey material should be sent to a remote host.
JSSE includes the following important features:
SSLSocket,SSLServerSocket, andSSLEngine)The JSSE standard API, available in thejavax.netandjavax.net.ssl packages, provides:
SSLEngine).Oracle's implementation of Java SE includes a JSSE providernamedSunJSSE, which comes preinstalled and preregisteredwith the JCA. This provider supplies the following cryptographicservices:
More information about this provider is available in theSunJSSE sectionof the Oracle Providers Documentation.
The following list contains links to online documentation andnames of books about related subjects:
Several terms relating to cryptography are used within thisdocument. This section defines some of these terms.
The process of confirming the identity of a party with whom oneis communicating.
A combination of cryptographic parameters that define thesecurity algorithms and key sizes used for authentication, keyagreement, encryption, and integrity protection.
A digitally signed statement vouching for the identity andpublic key of an entity (person, company, and so on). Certificatescan either be self-signed or issued by a Certificate Authority (CA)— an entity that is trusted to issue validcertificates for other entities. Well-known CAs include Comodo, DigiCert,and GoDaddy. X509 is a common certificate formatthat can be managed by the JDK'skeytool.
An algorithm that is used to produce a relatively smallfixed-size string of bits (called a hash) from an arbitrary blockof data. A cryptographic hash function is similar to a checksum andhas three primary characteristics: it is a one-way function,meaning that it is not possible to produce the original data fromthe hash; a small change in the original data produces a largechange in the resulting hash; and it does not require acryptographic key.
Sometimes referred to simply asproviderfor short, the Java Cryptography Architecture (JCA) defines it as apackage (or set of packages) that implements one or more engineclasses for specific cryptographic algorithms. An engine classdefines a cryptographic service in an abstract fashion without aconcrete implementation.
A digital equivalent of a handwritten signature. It is used toensure that data transmitted over a network was sent by whoeverclaims to have sent it and that the data has not been modified intransit. For example, an RSA-based digital signature is calculatedby first computing a cryptographic hash of the data and thenencrypting the hash with the sender's private key.
Encryption is the process of using a complex algorithm toconvert an original message (cleartext) to an encodedmessage (ciphertext) that is unintelligible unless it isdecrypted. Decryption is the inverse process of producing cleartextfrom ciphertext.
The algorithms used to encrypt and decrypt data typically comein two categories: secret key (symmetric) cryptographyand public key (asymmetric) cryptography.
The negotiation phase during which the two socket peers agree touse a new or existing session. The handshake protocol is a seriesof messages exchanged over the record protocol. At the end of thehandshake, new connection-specific encryption and integrityprotection keys are generated based on the key agreement secrets inthe session.
A method by which two parties cooperate to establish a commonkey. Each side generates some data, which is exchanged. These twopieces of data are then combined to generate a key. Only thoseholding the proper private initialization data can obtain the finalkey. Diffie-Hellman (DH) is the most common example of a keyagreement algorithm.
A method by which keys are exchanged. One side generates aprivate key and encrypts it using the peer's public key (typicallyRSA). The data is transmitted to the peer, who decrypts the keyusing the corresponding private key.
Key managers and trust managers use keystores for their keymaterial. A key manager manages a keystore and supplies public keysto others as needed (for example, for use in authenticating theuser to others). A trust manager decides who to trust based oninformation in the truststore it manages.
A keystore is a database of key material. Key material is usedfor a variety of purposes, including authentication and dataintegrity. Various types of keystores are available, includingPKCS12 and Oracle's JKS.
Generally speaking, keystore information can be grouped into twocategories: key entries and trusted certificate entries. A keyentry consists of an entity's identity and its private key, and canbe used for a variety of cryptographic purposes. In contrast, atrusted certificate entry contains only a public key in addition tothe entity's identity. Thus, a trusted certificate entry cannot beused where a private key is required, such as in ajavax.net.ssl.KeyManager. In the JDK implementation ofJKS, a keystore may contain both key entries and trustedcertificate entries.
A truststore is a keystore that is used when making decisionsabout what to trust. If you receive data from an entity that youalready trust, and if you can verify that the entity is the onethat it claims to be, then you can assume that the data really camefrom that entity.
An entry should only be added to a truststore if the user truststhat entity. By either generating a key pair or by importing acertificate, the user gives trust to that entry. Any entry in thetruststore is considered a trusted entry.
It may be useful to have two different keystore files: onecontaining just your key entries, and the other containing yourtrusted certificate entries, including CA certificates. The formercontains private information, whereas the latter does not. Usingtwo files instead of a single keystore file provides a cleanerseparation of the logical distinction between your own certificates(and corresponding private keys) and others' certificates. Toprovide more protection for your private keys, store them in akeystore with restricted access, and provide the trustedcertificates in a more publicly accessible keystore if needed.
Provides a way to check the integrity of information transmittedover or stored in an unreliable medium, based on a secret key.Typically, MACs are used between two parties that share a secretkey in order to validate information transmitted between theseparties.
A MAC mechanism that is based on cryptographic hash functions isreferred to as HMAC. HMAC can be used with any cryptographic hashfunction, such as Secure Hash Algorithm(SHA-256), in combination with a secret shared key. HMAC is specifiedin RFC 2104.
A cryptographic system that uses an encryption algorithm inwhich two keys are produced. One key is made public, whereas theother is kept private. The public key and the private key arecryptographic inverses; what one key encrypts only the other keycan decrypt. Public-key cryptography is also calledasymmetriccryptography.
A protocol that packages all data (whether application-level oras part of the handshake process) into discrete records of datamuch like a TCP stream socket converts an application byte streaminto network packets. The individual records are then protected bythe current encryption and integrity protection keys.
A cryptographic system that uses an encryption algorithm inwhich the same key is used both to encrypt and decrypt the data.Secret-key cryptography is also calledsymmetriccryptography.
A named collection of state information including authenticatedpeer identity, cipher suite, and key agreement secrets that arenegotiated through a secure socket handshake and that can be sharedamong multiple secure socket instances.
Transport Layer Security (TLS) is the most widely usedprotocol for implementing cryptography on the web. TLS uses acombination of cryptographic processes to provide securecommunication over a network. The pageTransport Layer Security (TLS) Protocol Overviewprovides an introduction to TLS and the cryptographic processes it uses.
To communicate securely, both sides of the connection must beSSL-enabled. In the JSSE API, the endpoint classes of theconnection areSSLSocket andSSLEngine.In the figureJSSE Classes Used to Create SSLSocket andSSLEngine, the major classes used to createSSLSocket andSSLEngine are laid out in alogical ordering. The text following the diagram, explains thecontents of the illustration.
AnSSLSocket is created either by anSSLSocketFactory or by anSSLServerSocketaccepting an inbound connection. In turn, anSSLServerSocket is created by anSSLServerSocketFactory. BothSSLSocketFactory andSSLServerSocketFactory objects are created by anSSLContext. AnSSLEngine is createddirectly by anSSLContext, and relies on theapplication to handle all I/O.
Note: When using rawSSLSocket orSSLEngine classes, you should always check the peer'scredentials before sending any data. Since JDK 7, endpointidentification/verification procedures can be handled duringSSL/TLS handshaking. See the methodSSLParameters.setEndpointIdentificationAlgorithm. Forexample, the host name in a URL should match the host name in thepeer's credentials. An application could be exploited with URLspoofing if the host name is not verified.
The core JSSE classes are part of thejavax.net andjavax.net.ssl packages.
The abstractjavax.net.SocketFactory class is usedto create sockets. Subclasses of this class are factories thatcreate particular subclasses of sockets and thus provide a generalframework for the addition of public socket-level functionality.For example, seeSSLSocketFactory andSSLServerSocketFactory.
The abstractjavax.net.ServerSocketFactory class isanalogous to theSocketFactory class, but is usedspecifically for creating server sockets.
Socket factories are a simple way to capture a variety ofpolicies related to the sockets being constructed, producing suchsockets in a way that does not require special configuration of thecode that asks for the sockets:
java.net.Socket (orjavax.net.ssl.SSLSocket), so that they can directlyexpose new APIs for features such as compression, security, recordmarking, statistics collection, or firewall tunneling.Thejavax.net.ssl.SSLSocketFactory class acts as afactory for creating secure sockets. This class is an abstractsubclass ofjavax.net.SocketFactory.
Secure socket factories encapsulate the details of creating andinitially configuring secure sockets. This includes authenticationkeys, peer certificate validation, enabled cipher suites, and thelike.
Thejavax.net.ssl.SSLServerSocketFactory class isanalogous to theSSLSocketFactory class, but is usedspecifically for creating server sockets.
The following ways can be used to obtain anSSLSocketFactory:
SSLSocketFactory.getDefault() static method.SSLSocketFactory parameter that can be called byclients to specify whichSSLSocketFactory to use whencreating sockets (for example,javax.net.ssl.HttpsURLConnection).The default factory is typically configured to support serverauthentication only so that sockets created by the default factorydo not leak any more information about the client than a normal TCPsocket would.
Many classes that create and use sockets do not need to know thedetails of socket creation behavior. Creating sockets through asocket factory passed in as a parameter is a good way of isolatingthe details of socket configuration, and increases the reusabilityof classes that create and use sockets.
You can create new socket factory instances either byimplementing your own socket factory subclass or by using anotherclass which acts as a factory for socket factories. One example ofsuch a class isSSLContext, which is provided with theJSSE implementation as a provider-based configuration class.
Thejavax.net.ssl.SSLSocket class is a subclass ofthe standard Javajava.net.Socket class. It supportsall of the standard socket methods and adds methods specific tosecure sockets. Instances of this class encapsulate theSSLContext under which they were created. Thereare APIs to control the creation of secure socket sessions for asocket instance, but trust and key management are not directlyexposed.
Thejavax.net.ssl.SSLServerSocket class isanalogous to theSSLSocket class, but is usedspecifically for creating server sockets.
To prevent peer spoofing, you should always verify the credentialspresented to anSSLSocket. SeeCipher Suite Choice and Remote EntityVerification.
Note: Due to the complexity of the SSL and TLSprotocols, it is difficult to predict whether incoming bytes on aconnection are handshake or application data, and how that datamight affect the current connection state (even causing the processto block). In the Oracle JSSE implementation, theavailable() method on the object obtained bySSLSocket.getInputStream() returns a count of thenumber of application data bytes successfully decrypted from theSSL connection but not yet read by the application.
SSLSocket can be obtained in one of thefollowing ways:SSLSocket can be created by an instance ofSSLSocketFactory via one of theseveralcreateSocket() methods of that class.SSLSocket can be created through theaccept() method of theSSLServerSocketclass.The SSL/TLS protocols define a specific series of steps to ensurea protected connection. However, the choice of cipher suite directlyaffects the type of security that the connection enjoys. For example,if an anonymous cipher suite is selected, then the application hasno way to verify the remote peer's identity. If a suite with noencryption is selected, then the privacy of the data cannot beprotected. Additionally, the SSL/TLS protocols do not specify thatthe credentials received must match those that peer might be expectedto send. If the connection were somehow redirected to a rogue peer,but the rogue's credentials were acceptable based on the currenttrust material, then the connection would be considered valid.
When using rawSSLSocket andSSLEngineclasses, you should always check the peer's credentials beforesending any data. TheSSLSocket andSSLEngineclasses do not automatically verify that the host name in a URLmatches the host name in the peer's credentials. An application couldbe exploited with URL spoofing if the host name is not verified.Since JDK 7, endpoint identification/verification procedures can behandled during SSL/TLS handshaking. See theSSLParameters.getEndpointIdentificationAlgorithm method.
Protocols such as HTTPS (HTTP Over TLS) do require host nameverification. Since JDK 7, the HTTPS endpoint identification isenforced during handshaking forHttpsURLConnection bydefault. See theSSLParameters.getEndpointIdentificationAlgorithm method.Alternatively, applications can use theHostnameVerifierinterface to override the default HTTPS host name rules.
TLS is becoming increasingly popular. It is being used in awide variety of applications across a wide range of computingplatforms and devices. Along with this popularity come demands touse TLS with different I/O and threading models to satisfy theapplications' performance, scalability, footprint, and otherrequirements. There are demands to use TLS with blocking andnonblocking I/O channels, asynchronous I/O, arbitrary input andoutput streams, and byte buffers. There are demands to use it inhighly scalable, performance-critical environments, requiringmanagement of thousands of network connections.
Abstraction of the I/O transport mechanism using theSSLEngine class in Java SE allows applications to usethe TLS protocol in a transport-independent way, and thusfrees application developers to choose transport and computingmodels that best meet their needs. Not only does this abstractionallow applications to use nonblocking I/O channels and other I/Omodels, it also accommodates different threading models. Thiseffectively leaves the I/O and threading decisions up to theapplication developer. Because of this flexibility, the applicationdeveloper must manage I/O and threading (complex topics in and ofthemselves), as well as have some understanding of the SSL/TLSprotocols. The abstraction is therefore an advanced API: beginnersshould useSSLSocket.
Users of other Java programming language APIs such as the JavaGeneric Security Services (Java GSS) and the Java SimpleAuthentication Security Layer (Java SASL) will notice similaritiesin that the application is also responsible for transportingdata.
The core class isjavax.net.ssl.SSLEngine.It encapsulates a TLS state machine and operates on inboundand outbound byte buffers supplied by the user of theSSLEngine class. The diagramFlow of Data Through SSLEngine illustrates theflow of data from the application, throughSSLEngine,to the transport mechanism, and back.
The application, shown on the left, supplies application(plaintext) data in an application buffer and passes it toSSLEngine. TheSSLEngine object processesthe data contained in the buffer, or any handshaking data, toproduce TLS encoded data and places it to the network buffersupplied by the application. The application is then responsiblefor using an appropriate transport (shown on the right) to send thecontents of the network buffer to its peer. Upon receiving TLSencoded data from its peer (via the transport), the applicationplaces the data into a network buffer and passes it toSSLEngine. TheSSLEngine object processesthe network buffer's contents to produce handshaking data orapplication data.
An instance of theSSLEngine class can be in one ofthe following states:
SSLEngine has been created andinitialized, but has not yet been used. During this phase, anapplication may set anySSLEngine-specific settings(enabled cipher suites, whether theSSLEngine shouldhandshake in client or server mode, and so on). Once handshaking hasbegun, though, any new settings (except client/server mode) will beused for the next handshake.SSLSession is established. Application data can't be sentduring this phase.SSLEngine. Outbound application messagesare encrypted and integrity protected, and inbound messages reversethe process.SSLEngine configuration settings won't be useduntil the next handshake.SSLEngine and shouldsend/receive any remaining messages to the peer before closing theunderlying transport mechanism. Once an engine is closed, it is notreusable: a newSSLEngine must be created.To indicate the status of the engine and what actions theapplication should take, theSSLEngine.wrap() andSSLEngine.unwrap() methods return anSSLEngineResult instance, as shown in the exampleUsing a Nonblocking SocketChannel. ThisSSLEngineResult object contains two pieces of statusinformation: the overall status of the engine and the handshakingstatus.
The possible overall statuses are represented by theSSLEngineResult.Status enum. The following statusesare available:
OKCLOSEDSSLEngine or the operationcould not be completed because it was already closed.BUFFER_UNDERFLOWBUFFER_OVERFLOWThe exampleHandling BUFFER_UNDERFLOW andBUFFER_OVERFLOW illustrates how to handle theBUFFER_UNDERFLOW andBUFFER_OVERFLOWstatuses of theSSLEngine.unwrap() method. It usesSSLSession.getApplicationBufferSize() andSSLSession.getPacketBufferSize() to determine howlarge 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 operationbreak;case BUFFER_UNDERFLOW:// Maybe need to enlarge the peer network packet bufferif (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 operationbreak;// Handle other status: CLOSED, OK...}The possible handshaking statuses are represented by theSSLEngineResult.HandshakeStatus enum. They representwhether handshaking has completed, whether the caller must obtainmore handshaking data from the peer or send more handshaking datato the peer, and so on. The following handshake statuses are available:
FINISHEDSSLEngine has just finished handshaking.NEED_TASKSSLEngine needs the results of one (or more)delegated tasks before handshaking can continue.NEED_UNWRAPSSLEngine needs to receive data from the remoteside before handshaking can continue.NEED_UNWRAP_AGAINSSLEngine needs to unwrap before handshaking cancontinue. This value indicates that not-yet-interpreted data hasbeen previously received from the remote side and does not needto be received again; the data has been brought into the JSSEframework but has not been processed yet.NEED_WRAPSSLEngine must send data to the remote sidebefore handshaking can continue, soSSLEngine.wrap()should be called.NOT_HANDSHAKINGSSLEngine is not currently handshaking.Having two statuses per result allows theSSLEngine toindicate that the application must take two actions: one in response tothe handshaking and one representing the overall status of thewrap() andunwrap() methods. For example,the engine might, as the result of a singleSSLEngine.unwrap() call, returnSSLEngineResult.Status.OK to indicate that the inputdata was processed successfully andSSLEngineResult.HandshakeStatus.NEED_UNWRAP toindicate that the application should obtain more TLS encodeddata from the peer and supply it toSSLEngine.unwrap()again so that handshaking can continue. As you can see, theprevious examples were greatly simplified; they would need to beexpanded significantly to properly handle all of thesestatuses.
The exampleChecking and Processing Handshaking Statuses and Overall Statuses illustrates how to processhandshaking data by checking handshaking status and the overallstatus of thewrap() andunwrap()methods.
void doHandshake(SocketChannel socketChannel, SSLEngine engine,ByteBuffer myNetData, ByteBuffer peerNetData) throws Exception {// Create byte buffers to use for holding application dataint appBufferSize = engine.getSession().getApplicationBufferSize();ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);// Begin handshakeengine.beginHandshake();SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();// Process handshaking messagewhile (hs != SSLEngineResult.HandshakeStatus.FINISHED &&hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {switch (hs) {case NEED_UNWRAP:// Receive handshaking data from peerif (socketChannel.read(peerNetData) < 0) {// The channel has reached end-of-stream}// Process incoming handshaking datapeerNetData.flip();SSLEngineResult res = engine.unwrap(peerNetData, peerAppData);peerNetData.compact();hs = res.getHandshakeStatus();// Check statusswitch (res.getStatus()) {case OK :// Handle OK statusbreak;// Handle other status: BUFFER_UNDERFLOW, BUFFER_OVERFLOW, CLOSED...}break;case NEED_WRAP :// Empty the local network packet buffer.myNetData.clear();// Generate handshaking datares = engine.wrap(myAppData, myNetData);hs = res.getHandshakeStatus();// Check statusswitch (res.getStatus()) {case OK :myNetData.flip();// Send the handshaking data to peerwhile (myNetData.hasRemaining()) {socketChannel.write(myNetData);}break;// Handle other status: BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED...}break;case NEED_TASK :// Handle blocking tasksbreak;// Handle other status: // FINISHED or NOT_HANDSHAKING...}}// Processes after handshaking...}This section shows you how to create an SSLEngine object and use it togenerate and process TLS data.
To create anSSLEngine object, you use theSSLContext.createSSLEngine() method. You mustconfigure the engine to act as a client or a server, and set otherconfiguration parameters, such as which cipher suites to use andwhether to require client authentication. TheSSLContext.createSSLEngine method creates ajavax.net.ssl.SSLEngine object.
The exampleCreating an SSLEngine Client for TLS with JKSas Keystore illustrates how to create anSSLEngine clientfor TLS that uses JKS as keystore.
Note: The server name and port number are notused for communicating with the server (all transport is theresponsibility of the application). They are hints to the JSSEprovider to use for SSL session caching, and for Kerberos-basedcipher suite implementations to determine which server credentialsshould be obtained.
import javax.net.ssl.*;import java.security.*;// Create and initialize the SSLContext with key materialchar[] passphrase = "passphrase".toCharArray();// First initialize the key and trust materialKeyStore 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 useKeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX");kmf.init(ksKeys, passphrase);// TrustManagers decide whether to allow connectionsTrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");tmf.init(ksTrust);// Get an instance of SSLContext for TLS protocolssslContext = SSLContext.getInstance("TLS");sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);// Create the engineSSLEngine engine = sslContext.createSSLengine(hostname, port);// Use as clientengine.setUseClientMode(true);The two mainSSLEngine methods arewrap() andunwrap(). They are responsiblefor generating and consuming network data respectively. Dependingon the state of theSSLEngine object, this data mightbe handshake or application data.
EachSSLEngine object has several phases during itslifetime. Before application data can be sent or received, theSSL/TLS protocol requires a handshake to establish cryptographicparameters. This handshake requires a series of back-and-forthsteps by theSSLEngine object.
During the initial handshaking, thewrap() andunwrap() methods generate and consume handshake data,and the application is responsible for transporting the data. Thewrap() andunwrap() method sequence isrepeated until the handshake is finished. EachSSLEngine operation generates an instance of theSSLEngineResult class, in which theSSLEngineResult.HandshakeStatus field is used todetermine what operation must occur next to move the handshakealong.
The figureState Machineduring TLS Handshake shows the state machine during a typicalTLS handshake, with corresponding messages and statuses:
The following steps are performed before the status of the handshake isdetermined:
This image illustrates some of the possible handshake statuses.The sectionUnderstanding SSLEngine OperationStatuses describes these statuses in more detail:
NEED_TASKNEED_WRAPNEED_UNWRAPFINISHEDWhen handshaking is complete, further calls towrap() will attempt to consume application data andpackage it for transport. Theunwrap() method willattempt the opposite.
To send data to the peer, the application first supplies thedata that it wants to send viaSSLEngine.wrap() toobtain the corresponding SSL/TLS encoded data. The application thensends the encoded data to the peer using its chosen transportmechanism. When the application receives the SSL/TLS encoded datafrom the peer via the transport mechanism, it supplies this data totheSSLEngine viaSSLEngine.unwrap() toobtain the plaintext data sent by the peer.
The exampleUsing a Nonblocking SocketChannel showsan SSL application that uses a nonblockingSocketChannel tocommunicate with its peer.
Note: The example can be made more robust andscalable by using aSelector with the nonblockingSocketChannel.
In the exampleUsing a Nonblocking SocketChannel,the stringhello is sent to the peer by encoding it using theSSLEngine created in the exampleCreating anSSLEngine Client for TLS with JKS as Keystore. It uses informationfrom theSSLSession to determine how large the byte buffersshould be.
// Create a nonblocking socket channelSocketChannel socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);socketChannel.connect(new InetSocketAddress(hostname, port));// Complete connectionwhile (!socketChannel.finishedConnect()) {// do something until connect completed}// Create byte buffers to use for holding application and encoded dataSSLSession 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 handshakedoHandshake(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 callif (res.getStatus() == SSLEngineResult.Status.OK) {myAppData.compact();// Send SSL/TLS encoded data to peerwhile(myNetData.hasRemaining()) {int num = socketChannel.write(myNetData);if (num == 0) {// no bytes written; try again later}}}// Handle other status: BUFFER_OVERFLOW, CLOSED...}The exampleReading Data From NonblockingSocketChannel illustrates how to read data from the same nonblockingSocketChannel and extract the plaintext data from it by usingtheSSLEngine created in the exampleCreatingan SSLEngine Client for TLS with JKS as Keystore. Each iteration ofthis code may or may not produce plaintext data, depending on whetherhandshaking is in progress.
// Read SSL/TLS encoded data from peerint 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 datapeerNetData.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...}During handshaking, anSSLEngine might encountertasks that can block or take a long time. For example, aTrustManager may need to connect to a remotecertificate validation service, or aKeyManager mightneed to prompt a user to determine which certificate to use as partof client authentication. To preserve the nonblocking nature ofSSLEngine, when the engine encounters such a task, itwill returnSSLEngineResult.HandshakeStatus.NEED_TASK.Upon receiving this status, the application should invokeSSLEngine.getDelegatedTask() to get the task, andthen, using the threading model appropriate for its requirements,process the task. The application might, for example, obtainthreads from a thread pool to process the tasks, while the mainthread handles other I/O.
The following code executes each task in a newly createdthread:
if (res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) {Runnable task;while ((task = engine.getDelegatedTask()) != null) {new Thread(task).start();}}TheSSLEngine will block futurewrap()andunwrap() calls until all of the outstanding tasksare completed.
For an orderly shutdown of an SSL/TLS connection, the SSL/TLSprotocols require transmission of close messages. Therefore, whenan application is done with the SSL/TLS connection, it should firstobtain the close messages from theSSLEngine, thentransmit them to the peer using its transport mechanism, andfinally shut down the transport mechanism.Example6 illustrates this.
// Indicate that application is done with engineengine.closeOutbound();while (!engine.isOutboundDone()) {// Get close messageSSLEngineResult res = engine.wrap(empty, myNetData);// Check res statuses// Send close message to peerwhile(myNetData.hasRemaining()) {int num = socketChannel.write(myNetData);if (num == 0) {// no bytes written; try again later}myNetData().compact();}}// Close transportsocketChannel.close();In addition to an application explicitly closing theSSLEngine, theSSLEngine might be closedby the peer (via receipt of a close message while it is processinghandshake data), or by theSSLEngine encountering anerror while processing application or handshake data, indicated bythrowing anSSLException. In such cases, theapplication should invokeSSLEngine.wrap() to get theclose message and send it to the peer untilSSLEngine.isOutboundDone() returnstrue(as shown inExample 6), or until theSSLEngineResult.getStatus() returnsCLOSED.
In addition to orderly shutdowns, there can also be unexpectedshutdowns when the transport link is severed before close messagesare exchanged. In the previous examples, the application might get-1 orIOException when trying to read fromthe nonblockingSocketChannel, or getIOException when trying to write to the non-blockingSocketChannel. When you get to the end of your input data,you should callengine.closeInbound(), which willverify with theSSLEngine that the remote peer hasclosed cleanly from the SSL/TLS perspective. Then the applicationshould still try to shut down cleanly by using the procedure inExample 6. Obviously, unlikeSSLSocket, the application usingSSLEngine must deal with more state transitions,statuses, and programming. For more information about writing anSSLEngine-based application, seeSample Code Illustrating the Use of anSSLEngine.
Thejavax.net.ssl.SSLSession interface represents asecurity context negotiated between the two peers of anSSLSocket orSSLEngine connection. Aftera session has been arranged, it can be shared by futureSSLSocket orSSLEngine objects connectedbetween the same two peers.
In some cases, parameters negotiated during the handshake areneeded later in the handshake to make decisions about trust. Forexample, the list of valid signature algorithms might restrict thecertificate types that can be used for authentication. TheSSLSession can be retrievedduring thehandshake by callinggetHandshakeSession() on anSSLSocket orSSLEngine. ImplementationsofTrustManager orKeyManager can use thegetHandshakeSession() method to get information aboutsession parameters to help them make decisions.
A fully initializedSSLSession contains the ciphersuite that will be used for communications over a secure socket aswell as a nonauthoritative hint as to the network address of theremote peer, and management information such as the time ofcreation and last use. A session also contains a shared mastersecret negotiated between the peers that is used to createcryptographic keys for encrypting and guaranteeing the integrity ofthe communications over anSSLSocket orSSLEngine connection. The value of this master secretis known only to the underlying secure socket implementation and isnot exposed through theSSLSession API.
In Java SE, a TLS 1.2 session is represented byExtendedSSLSession, an implementation ofSSLSession. TheExtendedSSLSession classadds methods that describe the signature algorithms that aresupported by the local implementation and the peer. ThegetRequestedServerNames() method called on anExtendedSSLSession instance is used to obtain a listofSNIServerName objects in the requestedServer Name Indication (SNI) extension. Theserver should use the requested server names to guide its selectionof an appropriate authentication certificate, and/or other aspectsof the security policy. The client should use the requested servernames to guide its endpoint identification of the peer's identity,and/or other aspects of the security policy.
Calls to thegetPacketBufferSize() andgetApplicationBufferSize() methods onSSLSession are used to determine the appropriatebuffer sizes used bySSLEngine.
Note: The SSL/TLS protocols specify thatimplementations are to produce packets containing at most 16kilobytes (KB) of plain text. However, some implementations violatethe specification and generate large records up to 32 KB. If theSSLEngine.unwrap() code detects large inbound packets,then the buffer sizes returned bySSLSession will beupdated dynamically. Applications should alwayscheck theBUFFER_OVERFLOW andBUFFER_UNDERFLOW statuses and enlarge thecorresponding buffers if necessary.SunJSSE will always sendstandard compliant 16 KB records and allow incoming 32 KB records.For a workaround, see the system propertyjsse.SSLEngine.acceptLargeFragments inCustomizing JSSE.
The HTTPS protocol is similar to HTTP, but HTTPS firstestablishes a secure channel via SSL/TLS sockets and thenverifies the identity of the peer beforerequesting or receiving data. Thejavax.net.ssl.HttpsURLConnection class extends thejava.net.HttpsURLConnection class and adds support forHTTPS-specific features. For more information about how HTTPS URLsare constructed and used, see the API specification sections aboutthejava.net.URL,java.net.URLConnection,java.net.HttpURLConnection,andjavax.net.ssl.HttpURLConnectionclasses.
Upon obtaining anHttpsURLConnection instance, youcan configure a number of HTTP and HTTPS parameters before actuallyinitiating the network connection via theURLConnection.connect() method. Of particular interestare:
In some situations, it is desirable to specify theSSLSocketFactory that anHttpsURLConnection instance uses. For example, youmight want to tunnel through a proxy type that is not supported bythe default implementation. The newSSLSocketFactorycould return sockets that have already performed all necessarytunneling, thus allowingHttpsURLConnection to useadditional proxies.
TheHttpsURLConnection class has a defaultSSLSocketFactory that is assigned when the class isloaded (this is the factory returned by theSSLSocketFactory.getDefault() method). Futureinstances ofHttpsURLConnection will inherit thecurrent defaultSSLSocketFactory until a new defaultSSLSocketFactory is assigned to the class via thestaticHttpsURLConnection.setDefaultSSLSocketFactory()method. Once an instance ofHttpsURLConnection hasbeen created, the inheritedSSLSocketFactory on thisinstance can be overridden with a call to thesetSSLSocketFactory() method.
Note: Changing the default staticSSLSocketFactory has no effect on existing instancesofHttpsURLConnection. A call to thesetSSLSocketFactory() method is necessary to changethe existing instances.
You can obtain the per-instance or per-classSSLSocketFactory by making a call to thegetSSLSocketFactory() orgetDefaultSSLSocketFactory() method, respectively.
If the host name of the URL does not match the host name in thecredentials received as part of the SSL/TLS handshake, then it ispossible that URL spoofing has occurred. If the implementationcannot determine a host name match with reasonable certainty, thenthe SSL implementation performs a callback to the instance'sassignedHostnameVerifier for further checking. Thehost name verifier can take whatever steps are necessary to makethe determination, such as performing host name pattern matching orperhaps opening an interactive dialog box. An unsuccessfulverification by the host name verifier closes the connection. Formore information regarding host name verification, seeRFC 2818.
ThesetHostnameVerifier() andsetDefaultHostnameVerifier() methods operate in asimilar manner to thesetSSLSocketFactory() andsetDefaultSSLSocketFactory() methods, in thatHostnameVerifier objects are assigned on aper-instance and per-class basis, and the current values can beobtained by a call to thegetHostnameVerifier() orgetDefaultHostnameVerifier() method.
The classes and interfaces in this section are provided tosupport the creation and initialization ofSSLContextobjects, which are used to createSSLSocketFactory,SSLServerSocketFactory, andSSLEngineobjects. The support classes and interfaces are part of thejavax.net.ssl package.
Three of the classes described in this section (SSLContext,KeyManagerFactory, andTrustManagerFactory) areengine classes. An engine class is an API class forspecific algorithms (or protocols, in the case ofSSLContext), for which implementations may be providedin one or more Cryptographic Service Provider (provider) packages.For more information about providers and engine classes, see the"Design Principles" and "Concepts" sections of theJava Cryptography ArchitectureReference Guide.
TheSunJSSE provider that comes standard with JSSE providesSSLContext,KeyManagerFactory, andTrustManagerFactory implementations, as well asimplementations for engine classes in the standardjava.security API. The following table listsimplementations supplied bySunJSSE.
| 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) |
Thejavax.net.ssl.SSLContext class is an engineclass for an implementation of a secure socket protocol. Aninstance of this class acts as a factory for SSL socket factoriesand SSL engines. AnSSLContext object holds all of thestate information shared across all objects created under thatcontext. For example, session state is associated with theSSLContext when it is negotiated through the handshakeprotocol by sockets created by socket factories provided by thecontext. These cached sessions can be reused and shared by othersockets created under the same context.
Each instance is configured through itsinit methodwith the keys, certificate chains, and trusted root CA certificatesthat it needs to perform authentication. This configuration isprovided in the form of key and trust managers. These managersprovide support for the authentication and key agreement aspects ofthe cipher suites supported by the context.
Currently, only X.509-based managers are supported.
There are two ways to obtain and initialize anSSLContext:
getDefault() method on either theSSLSocketFactory orSSLServerSocketFactory class. This method creates adefaultSSLContext with a defaultKeyManager,TrustManager, andSecureRandom (a secure random number generator). AdefaultKeyManagerFactory andTrustManagerFactory are used to create theKeyManager andTrustManager,respectively. The key material used is found in the defaultkeystore and truststore, as determined by system propertiesdescribed inCustomizing the DefaultKeystores and Truststores, Store Types, and StorePasswords.getInstance() on theSSLContext class,and then initialize the context by calling the instance's properinit() method. One variant of theinit()method takes three arguments: an array ofKeyManagerobjects, an array ofTrustManager objects, and aSecureRandom object. TheKeyManager andTrustManager objects are created by eitherimplementing the appropriate interfaces or using theKeyManagerFactory andTrustManagerFactoryclasses to generate implementations. TheKeyManagerFactory andTrustManagerFactorycan then each be initialized with key material contained in theKeyStore passed as an argument to theinit() method of theTrustManagerFactoryorKeyManagerFactory classes. Finally, thegetTrustManagers() method (inTrustManagerFactory) andgetKeyManagers()method (inKeyManagerFactory) can be called to obtainthe array of trust managers or key managers, one for each type oftrust or key material.Once an SSL connection is established, anSSLSession is created which contains variousinformation, such as identities established and cipher suite used.TheSSLSession is then used to describe an ongoingrelationship and state information between two entities. Each SSLconnection involves one session at a time, but that session may beused on many connections between those entities, simultaneously orsequentially.
Like other JCA provider-based engine classes,SSLContext objects are created using thegetInstance() factory methods of theSSLContext class. These static methods each return aninstance that implementsat least the requested securesocket protocol. The returned instance may implement otherprotocols, too. For example,getInstance("TLSv1.2") mayreturn an instance that implements TLSv1, TLSv1.1, and TLSv1.2. ThegetSupportedProtocols() method returns a list ofsupported protocols when anSSLSocket,SSLServerSocket, orSSLEngine is createdfrom this context. You can control which protocols are actuallyenabled for an SSL connection by using thesetEnabledProtocols(String[] protocols) method.
Note: AnSSLContext object isautomatically created, initialized, and statically assigned to theSSLSocketFactory class when you call theSSLSocketFactory.getDefault() method. Therefore, youdo not have to directly create and initialize anSSLContext object (unless you want to override thedefault behavior).
To create anSSLContext object by calling thegetInstance() factory method, you must specify theprotocol name. You may also specify which provider you want tosupply the implementation of the requested protocol:
public static SSLContext getInstance(Stringprotocol);public static SSLContext getInstance(String protocol,String provider);public static SSLContext getInstance(String protocol,Provider provider);If just a protocol name is specified, then the system willdetermine whether an implementation of the requested protocol isavailable in the environment. If there is more than oneimplementation, then it will determine whether there is a preferredone.
If both a protocol name and a provider are specified, then thesystem will determine whether an implementation of the requestedprotocol is in the provider requested. If there is noimplementation, an exception will be thrown.
A protocol is a string (such as"TLS") thatdescribes the secure socket protocol desired. Common protocol namesforSSLContext objects are defined inAppendix A.
AnSSLContext can be obtained as follows:
SSLContext sc = SSLContext.getInstance("TLS");A newly createdSSLContext should be initialized bycalling theinit method:
public void init(KeyManager[] km, TrustManager[] tm, SecureRandom random);
If theKeyManager[] parameter is null, then anemptyKeyManager will be defined for this context. IftheTrustManager[] parameter is null, then theinstalled security providers will be searched for thehighest-priority implementation of theTrustManagerFactory, fromwhich an appropriateTrustManager will be obtained.Likewise, theSecureRandom parameter may be null, inwhich case a default implementation will be used.
If the internal default context is used, (for example, anSSLContext is created bySSLSocketFactory.getDefault() orSSLServerSocketFactory.getDefault()), then adefaultKeyManager andTrustManager are created. The defaultSecureRandom implementation is also chosen.
The primary responsibility of theTrustManager isto determine whether the presented authentication credentialsshould be trusted. If the credentials are not trusted, then theconnection will be terminated. To authenticate the remote identityof a secure socket peer, you must initialize anSSLContext object with one or moreTrustManager objects. You must pass oneTrustManager for each authentication mechanism that issupported. If null is passed into theSSLContextinitialization, then a trust manager will be created for you.Typically, a single trust manager supports authentication based onX.509 public key certificates (for example,X509TrustManager). Some secure socket implementationsmay also support authentication based on shared secret keys,Kerberos, or other mechanisms.
TrustManager objects are created either by aTrustManagerFactory, or by providing a concreteimplementation of the interface.
Thejavax.net.ssl.TrustManagerFactory is an engineclass for a provider-based service that acts as a factory for oneor more types ofTrustManager objects. Because it isprovider-based, additional factories can be implemented andconfigured to provide additional or alternative trust managers thatprovide more sophisticated services or that implementinstallation-specific authentication policies.
SSLContext, except for passing an algorithm namestring instead of a protocol name to thegetInstance()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 theSunJSSE provider'sPKIX trust manager factory. This factory can be used to createtrust managers that provide X.509 PKIX-based certification pathvalidity checking.
When initializing anSSLContext, you can use trustmanagers created from a trust manager factory, or you can writeyour own trust manager, for example, using theCertPathAPI. For details, see theJava PKI Programmer'sGuide. You do not need to use a trust manager factory if youimplement a trust manager using theX509TrustManagerinterface.
A newly created factory should be initialized by calling one oftheinit() methods:
public void init(KeyStore ks);public void init(ManagerFactoryParameters spec);
Call whicheverinit() method is appropriate for theTrustManagerFactory you are using. If you are notsure, then ask the provider vendor.
For many factories, such as the SunX509TrustManagerFactory from theSunJSSE provider, theKeyStore is the only information required toinitialize theTrustManagerFactory and thus the firstinit method is the appropriate one to call. TheTrustManagerFactory will query theKeyStore for information about which remotecertificates should be trusted during authorization checks.
Sometimes, initialization parameters other than aKeyStore are needed by a provider. Users of thatprovider are expected to pass an implementation of the appropriateManagerFactoryParameters as defined by the provider.The provider can then call the specified methods in theManagerFactoryParameters implementation to obtain theneeded information.
For example, suppose theTrustManagerFactoryprovider requires initialization parameters B, R, and S from anyapplication that wants to use that provider. Like all providersthat require initialization parameters other than aKeyStore, the provider requires the application toprovide an instance of a class that implements a particularManagerFactoryParameters subinterface. In the example,suppose that the provider requires the calling application toimplement and create an instance ofMyTrustManagerFactoryParams and pass it to the secondinit() method. The following example illustrates whatMyTrustManagerFactoryParams 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 beingexplicitly initialized with aKeyStore object or anyother parameters. For example, they may access trust material froma local directory service via LDAP, use a remote online certificatestatus checking server, or access default trust material from astandard local location.
The default trust manager algorithm is PKIX. It can be changedby editing thessl.TrustManagerFactory.algorithmproperty in thejava.security file.
The PKIX trust manager factory uses theCertPath PKIXimplementation from an installed security provider. The trustmanager factory can be initialized using the normalinit(KeyStore ks) method, or by passing CertPathparameters to the the PKIX trust manager using thejavax.net.ssl.CertPathTrustManagerParametersclass.
The following example illustrates how to get the trust managerto use a particular LDAP certificate store and enable revocationchecking:
import javax.net.ssl.*;import java.security.cert.*;import java.security.KeyStore;import java.io.FileInputStream;...// Obtain Keystore passwordchar[] pass = System.console().readPassword("Password: ");// Create PKIX parametersKeyStore anchors = KeyStore.getInstance("PKCS12");anchors.load(new FileInputStream(anchorsFile, pass));PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(anchors, new X509CertSelector());// Specify LDAP certificate store to useLDAPCertStoreParameters lcsp = new LDAPCertStoreParameters("ldap.imc.org", 389);pkixParams.addCertStore(CertStore.getInstance("LDAP", lcsp));// Specify that revocation checking is to be enabledpkixParams.setRevocationEnabled(true);// Wrap PKIX parameters as trust manager parametersManagerFactoryParameters trustParams = new CertPathTrustManagerParameters(pkixParams);// Create TrustManagerFactory for PKIX-compliant trust managersTrustManagerFactory factory = TrustManagerFactory.getInstance("PKIX");// Pass parameters to factory to be passed to CertPath implementationfactory.init(trustParams);// Use factorySSLContext ctx = SSLContext.getInstance("TLS");ctx.init(null, factory.getTrustManagers(), null);If theinit(KeyStore ks) method is used, thendefault PKIX parameters are used with the exception that revocationchecking is disabled. It can be enabled by setting thecom.sun.net.ssl.checkRevocation system property totrue. This setting requires that the CertPathimplementation can locate revocation information by itself. ThePKIX implementation in the provider can do this in many cases butrequires that the system propertycom.sun.security.enableCRLDP be set totrue.
For more information about PKIX and the CertPath API, see theJava PKI Programmer'sGuide.
Thejavax.net.ssl.X509TrustManager interfaceextends the generalTrustManager interface. It must beimplemented by a trust manager when using X.509-basedauthentication.
To support X.509 authentication of remote socket peers throughJSSE, an instance of this interface must be passed to theinit method of anSSLContext object.
You can either implement this interface directly yourself orobtain one from a provider-basedTrustManagerFactory(such as that supplied by theSunJSSE provider). You could alsoimplement your own interface that delegates to a factory-generatedtrust manager. For example, you might do this to filter theresulting trust decisions and query an end-user through a graphicaluser interface.
Note: If a null KeyStore parameter is passed totheSunJSSE PKIX or SunX509TrustManagerFactory, thenthe factory uses the following process to try to find trustmaterial:
If thejavax.net.ssl.trustStore property isdefined, then theTrustManagerFactory attempts to finda file using the file name specified by that system property, anduses that file for the KeyStore parameter. If thejavax.net.ssl.trustStorePassword system property isalso defined, then its value is used to check the integrity of thedata in the truststore before opening it.
If thejavax.net.ssl.trustStore property is definedbut the specified file does not exist, then a defaultTrustManager using an empty keystore is created.
javax.net.ssl.trustStore system propertywas not specified, then:java-home/lib/security/jssecacerts exists,that file is used;java-home/lib/security/cacerts exists, thatfile is used;The factory looks for a file specified via thejavax.net.ssl.trustStore Security Property or for thejssecacerts file before checking for acacerts file.Therefore, you can provide a JSSE-specific set of trusted rootcertificates separate from ones that might be present in cacertsfor code-signing purposes.
If the suppliedX509TrustManager behavior is notsuitable for your situation, then you can create your ownX509TrustManager by either creating and registeringyour ownTrustManagerFactory or by implementing theX509TrustManager interface directly.
The following example illustrates aMyX509TrustManager class that enhances the defaultSunJSSEX509TrustManager behavior by providingalternative authentication logic when the defaultX509TrustManager 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 anSSLContext via theinit() method, as inthe following example. FutureSocketFactories createdfrom thisSSLContext will use your newTrustManager when making trust decisions.
TrustManager[] myTMs = new TrustManager[] { new MyX509TrustManager() };SSLContext ctx = SSLContext.getInstance("TLS");ctx.init(null, myTMs, null);You can enhanceMyX509TrustManager to handledynamic keystore updates. When acheckClientTrusted orcheckServerTrusted test fails and does not establish atrusted certificate chain, you can add the required trustedcertificate to the keystore. You must create a newpkixTrustManager from theTrustManagerFactory initialized with the updatedkeystore. When you establish a new connection (using the previouslyinitializedSSLContext), the newly added certificatewill be used when making trust decisions.
TheX509ExtendedTrustManager class is an abstractimplementation of theX509TrustManager interface. Itadds methods for connection-sensitive trust management. Inaddition, it enables endpoint verification at the TLS layer.
In TLS 1.2 and later, both client and server can specify whichhash and signature algorithms they will accept. To authenticate theremote side, authentication decisions must be based on both X509certificates and the local accepted hash and signature algorithms.The local accepted hash and signature algorithms can be obtainedusing theExtendedSSLSession.getLocalSupportedSignatureAlgorithms()method.
TheExtendedSSLSession object can be retrieved bycalling theSSLSocket.getHandshakeSession() method ortheSSLEngine.getHandshakeSession() method.
TheX509TrustManager interface is notconnection-sensitive. It provides no way to accessSSLSocket orSSLEngine sessionproperties.
Besides TLS 1.2 support, theX509ExtendedTrustManager class also supports algorithmconstraints and SSL layer host name verification. For JSSEproviders and trust manager implementations, theX509ExtendedTrustManager class is highly recommendedover the legacyX509TrustManager interface.
You can either create anX509ExtendedTrustManagersubclass yourself (which is outlined in the following section) orobtain one from a provider-basedTrustManagerFactory(such as that supplied by theSunJSSE provider). In Java SE 7, thePKIX or SunX509TrustManagerFactory returns anX509ExtendedTrustManager instance.
This section outlines how to create a subclass ofX509ExtendedTrustManager in nearly the same way asdescribed forX509TrustManager.
The following example illustrates how to create a class thatuses the PKIXTrustManagerFactory to locate a defaultX509ExtendedTrustManager that will be used to makedecisions about trust. If the default trust manager fails for anyreason, then the subclass is can add other behavior. In theexample, these locations are indicated by comments in thecatch 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 primary responsibility of theKeyManager is toselect the authentication credentials that will eventually be sentto the remote host. To authenticate yourself (a local secure socketpeer) to a remote peer, you must initialize anSSLContext object with one or moreKeyManager objects. You must pass oneKeyManager for each different authentication mechanismthat will be supported. If null is passed into theSSLContext initialization, then an emptyKeyManager will be created. If the internal defaultcontext is used (for example, anSSLContext created bySSLSocketFactory.getDefault() orSSLServerSocketFactory.getDefault()), then adefaultKeyManager iscreated. Typically, a single key manager supports authenticationbased on X.509 public key certificates. Some secure socketimplementations may also support authentication based on sharedsecret keys, Kerberos, or other mechanisms.
KeyManager objects are created either by aKeyManagerFactory, or by providing a concreteimplementation of the interface.
Thejavax.net.ssl.KeyManagerFactory class is anengine class for a provider-based service that acts as a factoryfor one or more types ofKeyManager objects. TheSunJSSE provider implements a factory that can return a basic X.509key manager. Because it is provider-based, additional factories canbe implemented and configured to provide additional or alternativekey managers.
You create an instance of this class in a similar manner toSSLContext, except for passing an algorithm namestring instead of a protocol name to thegetInstance()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 theSunJSSE provider'sdefault key manager factory, which provides basic X.509-basedauthentication keys.
A newly created factory should be initialized by calling one oftheinit methods:
public void init(KeyStore ks, char[] password);public void init(ManagerFactoryParameters spec);
Call whicheverinit method is appropriate for theKeyManagerFactory you are using. If you are not sure,then ask the provider vendor.
For many factories, such as the default SunX509KeyManagerFactory from theSunJSSE provider, theKeyStore and password are the only informationrequired to initialize theKeyManagerFactory and thusthe firstinit method is the appropriate one to call.TheKeyManagerFactory will query theKeyStore for information about which private key andmatching public key certificates should be used for authenticatingto a remote socket peer. The password parameter specifies thepassword that will be used with the methods for accessing keys fromtheKeyStore. All keys in theKeyStoremust be protected by the same password.
Sometimes initialization parameters other than aKeyStore and password are needed by a provider. Usersof that provider are expected to pass an implementation of theappropriateManagerFactoryParameters as defined by theprovider. The provider can then call the specified methods in theManagerFactoryParameters implementation to obtain theneeded information.
Some factories can provide access to authentication materialwithout being initialized with aKeyStore object orany other parameters. For example, they may access key material aspart of a login mechanism such as one based on JAAS, the JavaAuthentication and Authorization Service.
As previously indicated, theSunJSSE provider supports a SunX509factory that must be initialized with aKeyStoreparameter.
Thejavax.net.ssl.X509KeyManager interface extendsthe generalKeyManager interface. It must beimplemented by a key manager for X.509-based authentication. Tosupport X.509 authentication to remote socket peers through JSSE,an instance of this interface must be passed to theinit() method of anSSLContextobject.
You can either implement this interface directly yourself orobtain one from a provider-basedKeyManagerFactory(such as that supplied by theSunJSSE provider). You could alsoimplement your own interface that delegates to a factory-generatedkey manager. For example, you might do this to filter the resultingkeys and query an end-user through a graphical user interface.
If the defaultX509KeyManager behavior is notsuitable for your situation, then you can create your ownX509KeyManager in a way similar to that shown inCreating Your Own X509TrustManager.
TheX509ExtendedKeyManager abstract class is animplementation of theX509KeyManager interface thatallows for connection-specific key selection. It adds two methodsthat select a key alias for client or server based on the key type,allowed issuers, and currentSSLEngine:
public String chooseEngineClientAlias(String[] keyType,Principal[] issuers, SSLEngine engine)public String chooseEngineServerAlias(String keyType,Principal[] issuers, SSLEngine engine)If a key manager is not an instance of theX509ExtendedKeyManager class, then it will not workwith theSSLEngine class.
For JSSE providers and key manager implementations, theX509ExtendedKeyManager class is highly recommendedover the legacyX509KeyManager interface.
In TLS 1.2 and later, both client and server can specify whichhash and signature algorithms they will accept. To pass theauthentication required by the remote side, local key selectiondecisions must be based on both X509 certificates and the remoteaccepted hash and signature algorithms. The remote accepted hashand signature algorithms can be retrieved using theExtendedSSLSession.getPeerSupportedSignatureAlgorithms()method.
You can create your ownX509ExtendedKeyManagersubclass in a way similar to that shown inCreating Your Own X509ExtendedTrustManager.
Support for theServer Name Indication(SNI) extension on the server side enables the key manager tocheck the server name and select the appropriate key accordingly.For example, suppose there are three key entries with certificatesin the keystore:
cn=www.example.comcn=www.example.orgcn=www.example.netIf the ClientHello message requests to connect towww.example.net in the SNI extension, then the servershould be able to select the certificate with subjectcn=www.example.net.
Historically, there has been confusion regarding thefunctionality of aTrustManager and aKeyManager.
ATrustManager determines whether the remoteauthentication credentials (and thus the connection) should betrusted.
AKeyManager determines which authenticationcredentials to send to the remote host.
These classes are provided as part of the JSSE API to supportthe creation, use, and management of secure sockets. They are lesslikely to be used by secure socket applications than are the coreand support classes. The secondary support classes and interfacesare part of thejavax.net.ssl andjavax.security.cert packages.
TheSSLParameters class encapsulates the followingparameters that affect a TLS connection:
You can retrieve the currentSSLParameters for anSSLSocket orSSLEngine by using thefollowing methods:
getSSLParameters() in anSSLSocket,SSLServerSocket, andSSLEnginegetDefaultSSLParameters() andgetSupportedSSLParamters() in anSSLContextYou can assignSSLParameters with thesetSSLParameters() method in anSSLSocket,SSLServerSocket andSSLEngine.
You can explicitly set the server name indication with theSSLParameters.setServerNames() method. The server nameindication in client mode also affects endpoint identification. Inthe implementation ofX509ExtendedTrustManager, ituses the server name indication retrieved by theExtendedSSLSession.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<SNIServerName> 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 nameindication (www.example.com) will be used to makeendpoint identification against the peer's identity presented inthe end-entity's X.509 certificate.
During TLS handshaking, the client requests to negotiate acipher suite from a list of cryptographic options that it supports,starting with its first preference. Then, the server selects asingle cipher suite from the list of cipher suites requested by theclient. The selection honors the server's preference by default, which is themost secure setting. However, the server can choose to honor the client'spreference rather than its own preference by invoking the methodSSLParameters.setUseCipherSuitesOrder(false).
Thejavax.net.ssl.SSLSessionContext interface is agrouping ofSSLSessionobjects associated with a single entity. For example, it could beassociated with a server or client that participates in manysessions concurrently. The methods in this interface enable theenumeration of all sessions in a context and allow lookup ofspecific sessions via their session IDs.
AnSSLSessionContext may optionally be obtainedfrom anSSLSession by calling the SSLSessiongetSessionContext() method. The context may beunavailable in some environments, in which case thegetSessionContext() method returns null.
Thejavax.net.ssl.SSLSessionBindingListenerinterface is implemented by objects that are notified when they arebeing bound or unbound from anSSLSession.
Thejavax.net.ssl.SSLSessionBindingEvent classdefines the event communicated to anSSLSessionBindingListenerwhen it is bound or unbound from anSSLSession.
Thejavax.net.ssl.HandShakeCompletedListenerinterface is an interface implemented by any class that is notifiedof the completion of an SSL protocol handshake on a givenSSLSocket connection.
Thejavax.net.ssl.HandShakeCompletedEvent classdefine the event communicated to aHandShakeCompletedListenerupon completion of an SSL protocol handshake on a givenSSLSocket connection.
If the SSL/TLS implementation's standard host name verificationlogic fails, then the implementation calls theverify() method of the class that implements thisinterface and is assigned to thisHttpsURLConnectioninstance. If the callback class can determine that the host name isacceptable given the parameters, it reports that the connectionshould be allowed. An unacceptable response causes the connectionto 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 logicif (good_address) {return true;} else {return false;}}}//...deleted...HttpsURLConnection urlc = (HttpsURLConnection)(new URL("https://www.example.com/")).openConnection();urlc.setHostnameVerifier(new MyHostnameVerifier());SeeThe HttpsURLConnectionClass for more information about how to assign theHostnameVerifier to theHttpsURLConnection.
Many secure socket protocols perform authentication using publickey certificates, also called X.509 certificates. This is thedefault authentication mechanism for the SSL/TLS protocols.
Thejava.security.cert.X509Certificate abstractclass provides a standard way to access the attributes of X.509certificates.
Note: Thejavax.security.cert.X509Certificate class is supportedonly for backward compatibility with previous (1.0.x and 1.1.x)versions of JSSE. New applications should use thejava.security.cert.X509Certificate class instead.
Thejava.security.AlgorithmConstraints interface isused for controlling allowed cryptographic algorithms.AlgorithmConstraints defines threepermits() methods. These methods tell whether analgorithm name or a key is permitted for certain cryptographicfunctions. Cryptographic functions are represented by a set ofCryptoPrimitive, which is an enumeration containingfields likeSTREAM_CIPHER,MESSAGE_DIGEST, andSIGNATURE.
Thus, anAlgorithmConstraints implementation cananswer questions like: Can I use this key with this algorithm forthe purpose of a cryptographic operation?
AnAlgorithmConstraints object can be associatedwith anSSLParameters object by using the newsetAlgorithmConstraints() method. The currentAlgorithmConstraints object for anSSLParameters object is retrieved using thegetAlgorithmConstraints() method.
TheStandardConstants class is used to representstandard constants definitions in JSSE.
StandardConstants.SNI_HOST_NAME represents a domainname server (DNS) host name in aServerName Indication (SNI) extension, which can be used wheninstantiating anSNIServerName orSNIMatcher object.
An instance of the abstractSNIServerName classrepresents a server name in theServer NameIndication (SNI) extension. It is instantiated using the typeand encoded value of the specified server name.
You can use thegetType() andgetEncoded() methods to return the server name typeand a copy of the encoded server name value, respectively. Theequals() method can be used to check if some otherobject is "equal" to this server name. ThehashCode()method returns a hash code value for this server name. To get astring representation of the server name (including the server nametype and encoded server name value), use thetoString() method.
An instance of the abstractSNIMatcher classperforms match operations on anSNIServerName object.Servers can use information from theServerName Indication (SNI) extension to decide if a specificSSLSocket orSSLEngine should accept aconnection. For example, when multiple "virtual" or "name-based"servers are hosted on a single underlying network address, theserver application can use SNI information to determine whetherthis server is the exact server that the client wants to access.Instances of this class can be used by a server to verify theacceptable server names of a particular type, such as hostnames.
TheSNIMatcher class is instantiated using thespecified server name type on which match operations will beperformed. To match a givenSNIServerName, use thematches() method. To return the server name type ofthe givenSNIMatcher object, use thegetType() method.
An instance of theSNIHostName class (which extendstheSNIServerName class) represents a server name oftype "host_name" (seeTheStandardConstants Class) in theServerName Indication (SNI) extension. To instantiate anSNIHostName, specify the fully qualified DNS host nameof the server (as understood by the client) as aString argument. The argument is illegal in thefollowing cases:
You can also instantiate anSNIHostName byspecifying the encoded host name value as a byte array. This methodis typically used to parse the encoded name value in a requestedSNI extension. Otherwise, use theSNIHostName(Stringhostname) constructor. Theencoded argument isillegal in the following cases:
Note: Theencoded byte arraypassed in as an argument is cloned to protect against subsequentmodification.
To return the host name of anSNIHostName object inUS-ASCII encoding, use thegetAsciiName() method. Tocompare a server name to another object, use theequals() method (comparison isnotcase-sensitive). To return a hash code value of anSNIHostName, use thehashCode() method.To return a string representation of anSNIHostName,including the DNS host name, use thetoString()method.
You can create anSNIMatcher object for anSNIHostName object by passing a regular expressionrepresenting one or more host names to match to thecreateSNIMatcher() method.
JSSE includes a standard implementation that can be customizedby plugging in different implementations or specifying the defaultkeystore, and so on. The following tables summarize whichaspects can be customized, what the defaults are, and whichmechanisms are used to provide customization.
Some of the customizations are done by setting Security Propertyor system property values. Sections following the table explainhow to set such property values.
The following table shows items that are customized by setting ajava.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 theSunJSSE provider | Give alternative JCE algorithm providers a higher preference orderthan the SunJCE provider; seeCustomizing the EncryptionAlgorithm Providers. | SunJCE implementations | None |
jdk.certpath.disabledAlgorithms1 | Disabled certificate verification cryptographic algorithm (seeDisabled 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 forTLS connections, even if they are enabled explicitly in anapplication |
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 specificset of keys; once this limit is reached, a KeyUpdate post-handshakemessage is sent, which requests that the current set of keys beupdated. |
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, whichare not negotiated during TLS security parameters negotiationunless 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; seeSetting up a Java Client to use Client-Driven OCSP. |
security.provider.n | Cryptographic service provider; seeCustomizing theProvider Implementation andCustomizing the EncryptionAlgorithm Providers | Differs per platform; check thejava.security Security Properties file. | Specify the provider in thesecurity.provider.n=line in the Security Properties file, wheren is aninteger whose value is equal or greater than 1. |
ssl.KeyManagerFactory.algorithm | Default key manager factory algorithm name(seeCustomizing theDefault Key Managers and Trust Managers) | SunX509 | None |
ssl.ServerSocketFactory.provider1 | DefaultSSLServerSocketFactory implementation | SSLServerSocketFactory implementation from Oracle | None |
ssl.SocketFactory.provider1 | DefaultSSLSocketFactory implementation | SSLSocketFactory implementation from Oracle | None |
ssl.TrustManagerFactory.algorithm | Default trust manager factory algorithm name(seeCustomizing theDefault Key Managers and Trust Managers) | PKIX | None |
1This Security Property iscurrently used by the JSSE implementation, but it is not guaranteed to beexamined and used by other implementations. If it is examined by anotherimplementation, then that implementation should handle it in the same manneras the JSSE implementation does. There is no guarantee the property willcontinue to exist or be of the same type (system or Security) in futurereleases.
2The list of restricted,disabled, and legacy algorithms specified in these Security Properties maychange; see thejava.security file in your JDK installationfor the latest values.
The following table shows items that are customized by setting ajava.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;seeClient-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 namesspecifying which cipher suites to enable for use on thisHttpsURLConnection. See theSSLSocket.setEnabledCipherSuites(String[])method. Note that this method sets the preference order of theClientHello 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 namesspecifying which protocol suites to enable on thisHttpsURLConnection.SeeSSLSocket.setEnabledProtocols(String[]). |
https.proxyHost1 | Default proxy host | None | None |
https.proxyPort1 | Default proxy port | 80 | None |
java.protocol.handler.pkgs | Specifying an AlternativeHTTPS Protocol Implementation | Implementation from Oracle | None |
javax.net.ssl.keyStore1 | Default keystore; seeCustomizingthe Default Keystores and Truststores, Store Types, and StorePasswords | NONE | The valueNONE may be specified. This setting is appropriate ifthe keystore is not file-based (for example, it resides in a hardwaretoken). |
javax.net.ssl.keyStorePassword1 | Default keystore password; seeCustomizingthe Default Keystores and Truststores, Store Types, and StorePasswords | None | It is inadvisable to specify the password in a way that exposes itto discovery by other users. For example, specifying the password on thecommand line. To keep the password secure, have the application promptfor the password, or specify the password in a properly protected optionfile. |
javax.net.ssl.keyStoreProvider1 | Default keystore provider; seeCustomizingthe Default Keystores and Truststores, Store Types, and StorePasswords | None | None |
javax.net.ssl.keyStoreType1 | Default keystore type; seeCustomizingthe Default Keystores and Truststores, Store Types, and StorePasswords | KeyStore.getDefaultType() | None |
javax.net.ssl.sessionCacheSize (since JDK 8u261) | Default value for the maximum number of entries in the SSL sessioncache | 20480 | The session cache size can be set by calling theSSLSessionContext.setSessionCacheSize method or by setting thejavax.net.ssl.sessionCachSize system property. If the cache size isnot set, the default value is used. |
javax.net.ssl.trustStore1 | Default truststore; seeCustomizing the Default Keystores and Truststores, Store Types, and Store Passwords | jssecacerts, if it exists; otherwise,cacerts | The valueNONE may be specified. This setting is appropriate ifthe truststore is not file-based (for example, it resides in ahardware token). |
javax.net.ssl.trustStorePassword1 | Default truststore password; seeCustomizing the Default Keystores and Truststores, Store Types, and Store Passwords | None | It is inadvisable to specify the password in a way that exposes itto discovery by other users. For example, specifying the password onthe command line. To keep the password secure, have the applicationprompt for the password, or specify the password in a properlyprotected option file. |
javax.net.ssl.trustStoreProvider1 | Default truststore provider; seeCustomizing the Default Keystores and Truststores, Store Types, and Store Passwords | None | None |
javax.net.ssl.trustStoreType1 | Default truststore type; seeCustomizing 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 orserver receives a close_notify alert, it sends a correspondingclose_notify alert and the connection is duplex closed. |
jdk.tls.client.cipherSuites1 | Client-side default enabled cipher suites; seeSpecifying Default Enabled Cipher Suites. | SeeSunJSSE Cipher Suites for a list of currently implementedSunJSSE cipher suites for this JDK release, sorted by order ofpreference. | Caution: These system properties can be used to configure weakcipher suites, or the configured cipher suites may be weak in thefuture. It is not recommended that you use these system propertieswithout 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. SeeThe SunJSSE Provider. | None | To enable specificSunJSSE protocols on the client, specify themin a comma-separated list within quotation marks; all other supportedprotocols are not enabled on the client. For example,ifjdk.tls.client.protocols="TLSv1,TLSv1.1", then thedefault protocol settings on the client for TLSv1 and TLSv1.1 areenabled, while SSLv3, TLSv1.2, TLSv1.3, and SSLv2Hello are notenabled. |
jdk.tls.client.SignatureSchemes1 | Contains a comma-separated list of supported signature scheme names thatspecifies the signature schemes that could be used for TLS connections onthe client side. | None | Unrecognized or unsupported signature scheme names specified in theproperty are ignored. If this system property is not defined or empty, thenthe provider-specific default is used. The names are not case sensitive. Fora list of signature scheme names, seeAppendix 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, thenthe implementation default groups and preferences will be used. | This contains a comma-separated list within quotation marks ofenabled 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 systemproperty istrue, then the server will not accept client initiatedrenegotiations and will fail with a fatalhandshake_failure alert.Rejects server-side client-initialized renegotiation. | false | None |
jdk.tls.server.cipherSuites1 | Server-side default enabled cipher suites. SeeSpecifying Default Enabled Cipher Suites | SeeSunJSSE Cipher Suitesto determine which cipher suites areenabled by default | Caution: These system properties can be used to configure weakcipher suites, or the configured cipher suites may be weak in thefuture. It is not recommended that you use these system propertieswithout 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. SeeThe SunJSSE Provider. | None | To configure the default enabled protocol suite in the server sideof aSunJSSE provider, specify the protocols in a comma-separated listwithin quotation marks. The protocols in this list are standard SSLprotocol names as described inJava Cryptography Architecture (JCA) Standard Algorithm Name Documentation for JDK 8.Note that this system property impacts only the default protocol suite(SSLContext of the algorithms SSL and TLS). If an applicationuses a version-specificSSLContext (SSLv3, TLSv1, TLSv1.1, TLSv1.2, or TLSv1.3), or sets the enabled protocol versionexplicitly, this system property has no impact. |
jdk.tls.server.SignatureSchemes1 | Contains a comma-separated list of supported signature scheme names thatspecifies the signature schemes that could be used for TLS connections onthe server side. | None | Unrecognized or unsupported signature scheme names specified in theproperty are ignored. If this system property is not defined or empty, thenthe provider-specific default is used. The names are not case sensitive. Fora list of signature scheme names, seeAppendix 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 enablesTLS connections to use known finite field Diffie-Hellman groups.Some very old TLS vendors may not be able handle TLS extensions. Inthis 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 RFC6066. It enables TLS connections to virtual servers, in which multipleservers for different network names are hosted at a single underlyingnetwork address. Some very old TLS vendors may not be able handle TLSextensions. In this case, set this property to false to disable theSNI extension |
jsse.SSLEngine.acceptLargeFragments1 | Default sizing buffers for large TLS packets | None | Setting this system property to true,SSLSession will size buffersto handle large data packets by default (see the note inSSLSession and ExtendedSSLSession.This may cause applicationsto allocate unnecessarily largeSSLEngine buffers. Instead,applications should dynamically check for buffer overflow conditionsand resize buffers as appropriate (seeUnderstanding 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 extensionsare enabled, and processing for CertificateStatus messages sent by theserver 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 theproper RFC 5746 messages. SeeDescription of the Phase 2 FixinTransportLayer 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. SeeDescription of the Phase 2 FixinTransportLayer Security (TLS) Renegotiation Issue for more information. |
1This system propertyis currently used by the JSSE implementation, but it is not guaranteed tobe examined and used by other implementations. If it is examined byanother implementation, then that implementation should handle it in thesame manner as the JSSE implementation does. There is no guarantee theproperty will continue to exist or be of the same type (system orSecurity) in future releases.
You can customize some aspects of JSSE by setting securityproperties. You can set a Security Property either statically ordynamically:
To set a Security Property statically, add a line to theSecurity Properties file. The Security Properties file is locatedatjava-home/lib/security/java.security.
java-home refers to the directory where the JRE isinstalled.
To specify a Security Property value in the Security Propertiesfile, you add a line of the following form:
propertyName=propertyValue
For example, suppose that you want to specify a different keymanager factory algorithm name than the default SunX509. You dothis by specifying the algorithm name as the value of a securityproperty namedssl.KeyManagerFactory.algorithm. Forexample, to set the value to MyX509, add the following line to theSecurity Properties file:
ssl.KeyManagerFactory.algorithm=MyX509
To set a Security Property dynamically, call thejava.security.Security.setProperty method in yourcode:
Security.setProperty("propertyName," "propertyValue");For example, a call to thesetProperty() methodcorresponding to the previous example for specifying the keymanager factory algorithm name would be:
Security.setProperty("ssl.KeyManagerFactory.algorithm", "MyX509");You can customize some aspects of JSSE by setting systemproperties. There are several ways to set these properties:
To set a system property statically, use the-Doption of thejava command. For example, to run anapplication named MyApp and set thejavax.net.ssl.trustStore system property to specify atruststore named MyCacertsFile,enter the following:
java -Djavax.net.ssl.trustStore=MyCacertsFile MyApp
To set a system property dynamically, call thejava.lang.System.setProperty() method in yourcode:
System.setProperty("propertyName", "propertyValue");For example, asetProperty() call corresponding tothe previous example for setting thejavax.net.ssl.trustStore system property to specify atruststore named "MyCacertsFile" would be:
System.setProperty("javax.net.ssl.trustStore", "MyCacertsFile");In the Java Deployment environment (Plug-In/Web Start), thereare several ways to set the system properties. For moreinformation, seeJava Platform,Standard Edition Deployment Guide.
Use the Java Control Panel to set the Runtime EnvironmentProperty on a local or per-VM basis. This creates a localdeployment.properties file. Deployers can alsodistribute an enterprise widedeployment.propertiesfile by using thedeployment.config mechanism. Formore information, seeDeployment Configuration File andProperties.
To set a property for a specific applet, use the HTML subtag<PARAM> "java_arguments" within the<APPLET> tag. For more information, see theCommand-lineArguments section of theJava Platform, Standard EditionDeployment Guide.
To set the property in a specific Java Web Start application orapplet using Java Plug-in, use the JNLPproperty sub-elementof theresources element. For more information, seetheresourcesElement section of theJava Web Start Guide.
JDK 8u261 and later includes an implementation of the Transport LayerSecurity (TLS) 1.3 specification (RFC 8446).
TLS 1.3 is enabled for the defaultSSLContext (SSLorTLS) at the client endpoint.
TLS 1.3 is not directly compatible with previous versions. Although TLS 1.3 can be implemented with a backward-compatibility mode, there are still several compatibility risks to consider when upgrading to TLS 1.3:
TLS 1.3 uses a half-close policy, while TLS 1.2 and earlier use aduplex-close policy. For applications that depend on the duplex-close policy,there may be compatibility issues when upgrading to TLS 1.3.
The signature_algorithms_cert extension requires that pre-defined signaturealgorithms are used for certificate authentication. In practice, however,an application may use unsupported signature algorithms.
The DSA signature algorithm is not supported in TLS 1.3. If a server isconfigured to only use DSA certificates, it cannot negotiate a TLS 1.3 connection.
The supported cipher suites for TLS 1.3 are not the same as TLS 1.2 andearlier. If an application hardcodes cipher suites that are no longer supported,it may not be able to use TLS 1.3 without modifications to its code, for example TLS_AES_128_GCM_SHA256 (1.3 and later) versus TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(1.2 and earlier).
The TLS 1.3 session resumption and key update behaviors are different fromTLS 1.2 and earlier. The compatibility impact should be minimal, but it could bea risk if an application depends on the handshake details of the TLS protocols.
The X509Certificate implementation returned by theX509Certificate.getInstance() method is by default theimplementation from the JSSE implementation.
You can optionally cause a different implementation to bereturned. To do so, specify the name (and package) of the otherimplementation's class as the value of aSecurity Property namedcert.provider.x509v1. For example, if the class iscalledMyX509CertificateImpl and it appears in thecom.cryptox package, then you should add the followingline to the Security Properties file:
cert.provider.x509v1=com.cryptox.MyX509CertificateImpl
You can specify the default enabled cipher suites in yourapplication or with the system propertiesjdk.tls.client.cipherSuites andjdk.tls.server.cipherSuites.
Note: The actual use of enabled cipher suites is restricted by algorithm constraints.
The set of cipher suites to enable by default is determined by one of the following ways in this order of preference:
For example, explicitly setting the default enabled cipher suites in your application overrides settings specified injdk.tls.client.cipherSuites orjdk.tls.server.cipherSuites as well as JSSE provider defaults.
You can set which cipher suites are enabled with one of the following methods:
SSLSocket.setEnabledCipherSuites(String[])SSLEngine.setEnabledCipherSuites(String[])SSLServerSocket.setEnabledCipherSuites(String[])SSLParameters(String[] cipherSuites)SSLParameters(String[] cipherSuites, String[] protocols)SSLParameters.setCipherSuites(String[])https.cipherSuites system property forHttpsURLConnectionThe system propertyjdk.tls.client.cipherSuitesspecifies the default enabled cipher suites on the client side;jdk.tls.server.cipherSuites specifies those on theserver side.
The syntax of the value of these two system properties is acomma-separated list of supported cipher suite names.Unrecognized or unsupported cipher suite names that are specifiedin these properties are ignored. SeeJava Cryptography Architecture (JCA) Standard Algorithm Name Documentation for JDK 8 forstandard JSSE cipher suite names.
Note: These system properties are currently supported by Oracle JDK. They are not guaranteed to be supported by other JDK implementations.
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.
Each JSSE provider has its own default enabled cipher suites.SeeThe SunJSSEProvider inJava Cryptography Architecture OracleProviders Documentation for JDK 8 for the cipher suite namessupported by theSunJSSE provider and which ones that are enabledby default.
You can communicate securely with an SSL-enabled web server byusing the HTTPS URL scheme for thejava.net.URL class.The JDK provides a default HTTPS URL implementation.
If you want an alternative HTTPS protocol implementation to beused, set thejava.protocol.handler.pkgs system property toinclude the new class name.This action causes the specified classes to be found and loadedbefore the JDK default classes. See thejava.net.URLclass documentation for details.
Note: In past JSSE releases, you had to set thejava.protocol.handler.pkgs system property during JSSEinstallation. This step is no longer required unless you want toobtain an instance ofcom.sun.net.ssl.HttpsURLConnection. For moreinformation, seeCode Using theHttpsURLConnection Class in the "Troubleshooting" section.
JDK 1.4 and later releases come standard with a JSSECryptographic Service Provider, orprovider for short, namedSunJSSE. Providers are essentially packages that implement one ormore engine classes for specific cryptographic algorithms. The JSSEengine classes areSSLContext,KeyManagerFactory, andTrustManagerFactory. For more information aboutproviders and engine classes, see theJava Cryptography ArchitectureReference Guide.
Note: The transformation strings used whenSunJSSE callsCipher.getInstance() are"RSA/ECB/PKCS1Padding", "RC4", "DES/CBC/NoPadding", and"DESede/CBC/NoPadding". For further information about theCipher class and transformation strings see theJava Cryptography ArchitectureReference Guide.
Before it can be used, a provider must be registered, eitherstatically or dynamically. You do not need to register the SunJSSEprovider because it is preregistered. If you want to use otherproviders, read the following sections to see how to registerthem.
You register a provider statically by adding a line of thefollowing form to theSecurity Propertiesfile:
security.provider.n=providerClassName
This declares a provider, and specifies its preference ordern. The preference order is the order in whichproviders are searched for requested algorithms (when no specificprovider is requested). "1" is the most preferred, followed by "2",and so on.
TheproviderClassName is the fully qualified name of theprovider class. You obtain this name from the provider vendor.
The standard security provider and the SunJSSE provider shippedwith JDK 6 are automatically registered for you; the followinglines appear in thejava.security Security Propertiesfile to register theSunJCE security provider withpreference order 5 and the SunJSSE provider with preference order4:
security.provider.1=sun.security.pkcs11.SunPKCS11 \${java.home}/lib/security/sunpkcs11-solaris.cfgsecurity.provider.2=sun.security.provider.Sunsecurity.provider.3=sun.security.rsa.SunRsaSignsecurity.provider.4=com.sun.net.ssl.internal.ssl.Providersecurity.provider.5=com.sun.crypto.provider.SunJCEsecurity.provider.6=sun.security.jgss.SunProvidersecurity.provider.7=com.sun.security.sasl.ProviderTo use another JSSE provider, add a line registering the otherprovider, giving it whatever preference order you prefer.
You can have more than one JSSE provider registered at the sametime. The registered providers may include differentimplementations for different algorithms for different engineclasses, or they may have support for some or all of the same typesof algorithms and engine classes. When a particular engine classimplementation for a particular algorithm is searched for, if nospecific provider is specified for the search, then the providersare searched in preference order and the implementation from thefirst provider that supplies an implementation for the specifiedalgorithm is used.
Instead of registering a provider statically, you can add theprovider dynamically at runtime by calling theSecurity.addProvider() method at the beginning of yourprogram. For example, to dynamically add a provider whose providerclass name isMyProvider and whoseMyProvider class resides in thecom.ABCpackage, you would call:
Security.addProvider(new com.ABC.MyProvider());
TheSecurity.addProvider() method adds thespecified provider to the next available preference position.
This type of registration is not persistent and can only be doneby a program with sufficient permissions.
Whenever a defaultSSLSocketFactory orSSLServerSocketFactory is created (via a call toSSLSocketFactory.getDefault orSSLServerSocketFactory.getDefault), and this defaultSSLSocketFactory (orSSLServerSocketFactory) comes from the JSSE referenceimplementation, a defaultSSLContext is associatedwith the socket factory. (The default socket factory will come fromthe JSSE implementation.)
This defaultSSLContext is initialized with adefaultKeyManager and a defaultTrustManager. If a keystore is specified by thejavax.net.ssl.keyStore systemproperty and an appropriatejavax.net.ssl.keyStorePassword system property, then theKeyManager created by the defaultSSLContext will be aKeyManagerimplementation for managing the specified keystore. (The actualimplementation will be as specified inCustomizing the Default Key and TrustManagers.) If no such system property is specified, then thekeystore managed by theKeyManager will be a new emptykeystore.
Generally, the peer acting as the server in the handshake willneed a keystore for its KeyManager in order to obtain credentialsfor authentication to the client. However, if one of the anonymouscipher suites is selected, then the server'sKeyManager keystore is not necessary. And, unless theserver requires client authentication, the peer acting as theclient does not need aKeyManager keystore. Thus, inthese situations it may be OK if nojavax.net.ssl.keyStore system property value isdefined.
Similarly, if a truststore is specified by thejavax.net.ssl.trustStore system property, then theTrustManager created by the defaultSSLContext will be aTrustManagerimplementation for managing the specified truststore. In this case,if such a property exists but the file it specifies does not, thenno truststore is used. If nojavax.net.ssl.trustStoreproperty exists, then a default truststore is searched for. If atruststore namedjava-home/lib/security/jssecacerts isfound, it is used. If not, then a truststore namedjava-home/lib/security/cacerts is searched for and used(if it exists). Finally, ifa truststore is still not found, then the truststore managed by theTrustManager will be a new empty truststore.
Note: The JDK ships with a limited number oftrusted root certificates in thejava-home/lib/security/cacerts file. As documented inkeytool referencepages, it is your responsibility to maintain (that is, add andremove) the certificates contained in this file if you use thisfile as a truststore.
Depending on the certificate configuration of the servers thatyou contact, you may need to add additional root certificates.Obtain the needed specific root certificates from the appropriatevendor.
If thejavax.net.ssl.keyStoreType and/orjavax.net.ssl.keyStorePassword system properties arealso specified, then they are treated as the defaultKeyManager keystore type and password, respectively.If no type is specified, then the default type is that returned bytheKeyStore.getDefaultType() method, which is thevalue of thekeystore.type Security Property, or "jks"if no such Security Property is specified. If no keystore passwordis specified, then it is assumed to be a blank string "".
Similarly, if thejavax.net.ssl.trustStoreTypeand/orjavax.net.ssl.trustStorePassword systemproperties are also specified, then they are treated as the defaulttruststore type and password, respectively. If no type isspecified, then the default type is that returned by theKeyStore.getDefaultType() method. If no truststorepassword is specified, then it is assumed to be a blank string"".
Note: This section describes the current JSSEreference implementation behavior. The system properties describedin this section are not guaranteed to continue to have the samenames and types (system or security) or even to exist at all infuture releases. They are also not guaranteed to be examined andused by any other JSSE implementations. If theyare examinedby an implementation, then that implementation should handle themin the same manner as the JSSE reference implementation does, asdescribed herein.
As noted inCustomizing the DefaultKeystores and Truststores, Store Types, and Store Passwords,whenever a defaultSSLSocketFactory orSSLServerSocketFactory is created, and this defaultSSLSocketFactory (orSSLServerSocketFactory) comes from the JSSE referenceimplementation, a defaultSSLContext is associatedwith the socket factory.
This defaultSSLContext is initialized with aKeyManager and aTrustManager. TheKeyManager and/orTrustManager suppliedto the defaultSSLContext will be an implementationfor managing the specified keystore or truststore, as described inthe aforementioned section.
TheKeyManager implementation chosen is determinedby first examining thessl.KeyManagerFactory.algorithmSecurity Property. If such a propertyvalue is specified, then aKeyManagerFactoryimplementation for the specified algorithm is searched for. Theimplementation from the first provider that supplies animplementation is used. ItsgetKeyManagers() method iscalled to determine theKeyManager to supply to thedefaultSSLContext. Technically,getKeyManagers() returns an array ofKeyManager objects, oneKeyManager foreach type of key material. If no such Security Property value isspecified, then the default value of SunX509 is used to perform thesearch.
Note: AKeyManagerFactoryimplementation for the SunX509 algorithm is supplied by the SunJSSEprovider. TheKeyManager that it specifies is ajavax.net.ssl.X509KeyManager implementation.
Similarly, theTrustManager implementation chosenis determined by first examining thessl.TrustManagerFactory.algorithm Security Property.If such a property value is specified, then aTrustManagerFactory implementation for the specifiedalgorithm is searched for. The implementation from the firstprovider that supplies an implementation is used. ItsgetTrustManagers() method is called to determine theTrustManager to supply to the defaultSSLContext. Technically,getTrustManagers() returns an array ofTrustManager objects, oneTrustManagerfor each type of trust material. If no such Security Property valueis specified, then the default value of PKIX is used to perform thesearch.
Note: ATrustManagerFactoryimplementation for the PKIX algorithm is supplied by the SunJSSEprovider. TheTrustManager that it specifies is ajavax.net.ssl.X509TrustManager implementation.
Note: This section describes the current JSSEreference implementation behavior. The system properties describedin this section are not guaranteed to continue to have the samenames and types (system or security) or even to exist at all infuture releases. They are also not guaranteed to be examined andused by any other JSSE implementations. If theyare examinedby an implementation, then that implementation should handle themin the same manner as the JSSE reference implementation does, asdescribed herein.
In some environments, certain algorithms or key lengths may be undesirablewhen using TLS. The Oracle JDK uses thejdk.certpath.disabledAlgorithms andjdk.tls.disabledAlgorithm Security Properties to disable algorithms during TLS protocol negotiation, including version negotiation, cipher suites selection, peer authentication, and key exchange mechanisms. Note that these Security Properties are not guaranteed to be used by other JDK implementations. See the<java-home>/lib/security/java.security file forinformation about the syntax of these Security Properties and their currentactive values.
jdk.certpath.disabledAlgorithms Property: CertPath code uses this Security Property to determine which algorithms should not be allowed during CertPath checking. For example, when a TLS server sends an identifying certificate chain, a client TrustManager that uses a CertPath implementation to verify the received chain will not allow the stated conditions. For example, the following line blocks any MD2-based certificate, as well as SHA1 TLSServer certificates that chain to trust anchors that are pre-installed in the cacaerts keystore. Likewise, this line blocks any RSA key less than 1024 bits.
jdk.certpath.disabledAlgorithms=MD2, SHA1 jdkCA & usage TLSServer, RSA keySize < 1024
jdk.tls.disabledAlgorithms Property: SunJSSE code uses thisSecurity Property to disable TLS protocols, cipher suites, keys, and so on. The syntax is similar to thejdk.certpath.disabledAlgorithms Security Property. For example, the following line disables the SSLv3 algorithm and all of the TLS_*_RC4_* cipher suites:
jdk.tls.disabledAlgorithms=SSLv3, RC4
If you require a particular condition, you can reactivate it by eitherremoving the associated value in the Security Property in thejava.security file or dynamically setting the proper SecurityProperty before JSSE is initialized.
Note that these Security Properties effectively create a third set of cipher suites, Disabled. The following list describes these three sets:
jdk.tls.disabledAlgorithms Security Property), then that cipher suite is disabled and will not be considered for a connection handshake.setEnabledCipherSuites orsetSSLParameters methods.In some environments, a certain algorithm may be undesirable but it cannot bedisabled because of its use in legacy applications. Legacy algorithms may still be supported, but applications should not use them as the security strength of legacy algorithms is usually not strong enough. During TLS security parameters negotiation, legacy algorithms are not negotiated unless there are no other candidates. The Security Propertyjdk.tls.legacyAlgorithmsspecifies which algorithms the Oracle JDK considers as legacy algorithms. See the<java-home>/lib/security/java.security file for the syntax ofthis Security Property.
Note:
jdk.tls.disabledAlgorithms property or thejava.security.AlgorithmConstraints API (see the methodjavax.net.ssl.SSLParameters.setAlgorithmConstraints), then the algorithm is completely disabled and will not be negotiated.jdk.tls.legacyAlgorithms, use an alternative algorithm as soon as possible; a future JDK release may specify a legacy algorithm as a restricted algorithm.The SunJSSE provider uses the SunJCE implementation for all itscryptographic needs. Although it is recommended that you leave theprovider at its regular position, you can use implementations fromother JCA or JCE providers by registering thembefore theSunJCE provider. Thestandard JCAmechanism can be used to configure providers, either staticallyvia the Security Properties filejava-home/lib/security/java.security, or dynamically viatheaddProvider() orinsertProviderAt()method in thejava.security.Security class.
In TLS connections, ephemeral Diffie-Hellman (DH) keys may be usedinternally during the handshaking. The SunJSSE provider provides a flexibleapproach to customize the strength of the ephemeral DH key size during TLShandshaking.
Diffie-Hellman (DH) keys of sizes less than 2048 bits have been deprecatedbecause of their insufficient strength. You can customize the ephemeral DH keysize with the system propertyjdk.tls.ephemeralDHKeySize. Thissystem property does not impact DH key sizes inServerKeyExchangemessages for exportable cipher suites. It impacts only the DHE_RSA, DHE_DSS, andDH_anon-based cipher suites in the JSSE Oracle provider.
You can specify one of the following values for this property:
Undefined: A DH key of size 2048 bits will be used always for non-exportable cipher suites. This is the default value for this property.
legacy: The JSSE Oracle provider preserves the legacy behavior (for example, using ephemeral DH keys of sizes 512 bits and 768 bits) of JDK 7 and earlier releases.
matched:
For non-exportable anonymous cipher suites, the DH key size inServerKeyExchange messages is 2048 bits.
For X.509 certificate-based authentication (of non-exportable cipher suites), the DH key size matching the corresponding authentication key is used, except that a fixed size of 1024 bits is used for any key smaller than 1024 bits, and a fixed size of 2048 bits is used for any key larger than 2048 bits.
For example, if the public key size of an authentication certificate is 2048 bits, then the ephemeral DH key size is 2048 bits unless the cipher suite is exportable. This key sizing scheme keeps the cryptographic strength consistent between authentication keys and key-exchange keys.
A valid integer between 1024 and 8192 in multiples of 64, inclusively: A fixed ephemeral DH key size of the specified value, in bits, will be used for non-exportable cipher suites.
The following table summarizes the minimum and maximum acceptable DH keysizes for each of the possible values for the system propertyjdk.tls.ephemeralDHKeySize:
Value ofjdk.tls.ephemeralDHKeySize | Undefined | legacy | matched | Integer value (fixed) |
|---|---|---|---|---|
| Exportable DH key size | 512 | 512 | 512 | 512 |
| Non-exportable anonymous cipher suites | 2048 | 768 | 2048 | A valid integer between 1024 and 8192 in multiples of 64, inclusively: Afixed ephemeral DH key size of the specified value, in bits, will be used fornon-exportable cipher suites. |
| Authentication certificate | 2048 | 768 | The key size is the same as the authentication certificate unless the key isless than 1024 bits or greater than 2048 bits. If the key is less than 1024bits, then a DH key of 1024 bits is used. If the key is greater than 2048 bits,then a DH key of 2048 bits is used. Consequently, you may use the values 1024 or 2048 only. | The fixed key size is specified by a valid integer property value, whichmust be between 1024 and 8192 in multiples of 64, inclusively. |
In order to negotiate smaller maximum fragment lengths, clients have anoption to include an extension of type max_fragment_length in theClientHello message. A system property,jsse.enableMFLNExtension,can be used to enable or disable the MFLN extension for TLS.
It may be desirable for constrained TLS clients to negotiate asmaller maximum fragment length due to memory limitations or bandwidthlimitations. In order to negotiate smaller maximum fragment lengths,clients have an option to include an extension of typemax_fragment_length in the (extended) ClientHello message. See RFC 6066.
Once a maximum fragment length has been successfully negotiated, theTLS client and server can immediately begin fragmenting messages(including handshake messages) to ensure that no fragment larger than thenegotiated length is sent.
A system propertyjsse.enableMFLNExtension is defined toenable or disable the MFLN extension. Thejsse.enableMFLNExtensionis disabled by default.
The value of the system property can be set as follows:
| System Property | Description |
|---|---|
jsse.enableMFLNExtension=true | Enable the MFLN extension. If the returned value ofSSLParameters.getMaximumPacketSize()is less than (212 + header-size) the maximum fragment lengthnegotiation extension would be enabled. |
jsse.enableMFLNExtension=false | Disable the MFLN extension. |
You can specify a limit on the amount of data an algorithm may encrypt witha specific set of keys with thejdk.tls.keyLimits SecurityProperty. Once this limit is reached, a KeyUpdate post-handshake message issent, which requests that the current set of keys be updated. This SecurityProperty is only for symmetrical ciphers with TLS 1.3.
The syntax for this property is as follows:
jdk.tls.keyLimits=KeyLimit { ,KeyLimit }KeyLimit:AlgorithmNameKeyUpdateLengthAlgorithmName: A full algorithm transformationLength: The amount of encrypted data in a session before a KeyUpdate message is sent. This value may be an integer value in bytes or as a power of two, for example, 2^37.For example, the following specifies that a KeyUpdate message is sent once the algorithm AES/GCM/NoPadding has encrypted 237 bytes:
jdk.tls.keyLimits=AES/GCM/NoPadding KeyUpdate 2^37
If thejdk.tls.acknowledgeCloseNotify system property isset to true, then when the client or server receives a close_notifyalert, it sends a corresponding close_notify alert and the connection isduplex closed.
TLS 1.2 and earlier versions use a duplex-close policy. However, TLS1.3 uses a half-close policy, which means that the inbound and theoutbound close_notify alerts are independent. When upgrading to TLS 1.3,unexpected behavior can occur if your application shuts down theTLS connection by using only one of theSSLEngine.closeInbound()orSSLEngine.closeOutbound() methods but not both on eachside of the connection. If your application unexpectedly hangs or timesout when the underlying TLS transportation is not duplex closed,you may need to set this property to true.
Note that when a TLS connection is no longer needed, the clientand server applications should each close both sides of their respectiveconnection.
Some TLS implementations may not handle unknown extensions properly. As a result, you might encounter unexpected interoperability issues when the JDK introduces new extensions. Two system properties enable you to customize default extensions:
jdk.tls.client.disableExtensions: Blocks extensions used on the client side.jdk.tls.server.disableExtensions: Blocks extensions used on the server side.If an extension is disabled, then it won't be produced nor processed in handshake messages.
The value of these system properties is a list of comma-separated standard TLS extension names. SeeTransport Layer Security (TLS) Extensions for a list of these names. Extension names are case-sensitive, and unknown, unsupported misspelled and duplicated names are ignored.
Note: Although system properties exist that enable and disable specific TLS extensions, such asjsse.enableMFLNExtension,jsse.enableSNIExtension, andjsse.enableSNIExtension, an extension won't be enabled if it's disabled throughjdk.tls.client.disableExtensions orjdk.tls.server.disableExtensions, even though it could be enabled though the corresponding system property.
Use the Online Certificate Status Protocol (OCSP) to determine theX.509 certificate revocation status during the Transport Layer Security(TLS) handshake. SeeClient-Driven OCSP and OCSP Stapling.
TheJava CryptographyArchitecture (JCA) is a set of packages that provides aframework and implementations for encryption, key generation andkey agreement, and message authentication code (MAC) algorithms.The SunJSSE provider uses JCA exclusively for all of itscryptographic operations and can automatically take advantage ofJCE features and enhancements, including JCA's support for PKCS#11. Thissupport enables the SunJSSE provider to use hardware cryptographicaccelerators for significant performance improvements and to usesmartcards as keystores for greater flexibility in key and trustmanagement.
Use of hardware cryptographic accelerators is automatic if JCAhas been configured to use the Oracle PKCS#11 provider, which inturn has been configured to use the underlying acceleratorhardware. The provider must be configured before any other JCAproviders in the provider list. For details on how to configure theOracle PKCS#11 provider, see thePKCS#11Guide.
Support for PKCS#11 in JCA also enables access to smartcards asa keystore. For details on how to configure the type and locationof the keystores to be used by JSSE, see theCustomizing JSSE section. Touse a smartcard as a keystore or truststore, set thejavax.net.ssl.keyStoreType andjavax.net.ssl.trustStoreType system properties,respectively, topkcs11, and set thejavax.net.ssl.keyStore andjavax.net.ssl.trustStore system properties,respectively, toNONE. To specify the use of aspecific provider, use thejavax.net.ssl.keyStoreProvider andjavax.net.ssl.trustStoreProvider system properties(for example, set them toSunPKCS11-joe). By usingthese properties, you can configure an application that previouslydepended on these properties to access a file-based keystore to usea smartcard keystore with no changes to the application.
Some applications request the use of keystores programmatically.These applications can continue to use the existing APIs toinstantiate aKeystore and pass it to its key managerand trust manager. If theKeystore instance refers toa PKCS#11 keystore backed by a Smartcard, then the JSSE applicationwill have access to the keys on the smartcard.
smartcards (and other removable tokens) have additionalrequirements for anX509KeyManager. Differentsmartcards can be present in a smartcard reader during the lifetimeof a Java application, and they can be protected using differentpasswords.
Thejava.security.KeyStore.Builderclass abstracts the construction and initialization of aKeyStore object. It supports the use ofCallbackHandler for password prompting, and itssubclasses can be used to support additional features as desired byan application. For example, it is possible to implement aBuilder that allows individualKeyStoreentries to be protected with different passwords. Thejavax.net.ssl.KeyStoreBuilderParameters class then canbe used to initialize a KeyManagerFactory using one or more oftheseBuilder objects.
AX509KeyManager implementation in the SunJSSEprovider called NewSunX509 supports these parameters. If multiplecertificates are available, it attempts to pick a certificate withthe appropriate key usage and prefers valid to expiredcertificates.
The following example illustrates how to tell JSSE to use both aPKCS#11 keystore (which might in turn use a smartcard) and aPKCS#12 file-based keystore.
import javax.net.ssl.*;import java.security.KeyStore.*;...// Specify keystore builder parameters for PKCS#11 keystoresBuilder scBuilder = Builder.newInstance("PKCS11", null,new CallbackHandlerProtection(myGuiCallbackHandler));// Specify keystore builder parameters for a specific PKCS#12 keystoreBuilder fsBuilder = Builder.newInstance("PKCS12", null,new File(pkcsFileName), new PasswordProtection(pkcsKsPassword));// Wrap them as key manager parametersManagerFactoryParameters ksParams = new KeyStoreBuilderParameters(Arrays.asList(new Builder[] { scBuilder, fsBuilder }) );// Create KeyManagerFactoryKeyManagerFactory factory = KeyManagerFactory.getInstance("NewSunX509");// Pass builder parameters to factoryfactory.init(ksParams);// Use factorySSLContext ctx = SSLContext.getInstance("TLS");ctx.init(factory.getKeyManagers(), null, null);The SunJSSE provider has support for Kerberos cipher suites, asdescribed inRFC2712. The following cipher suites are supported but not enabledby default:
To enable the use of these cipher suites, you must do soexplicitly. For more information, see the API documentation for theSSLEngine.setEnabledCipherSuites() andSSLSocket.setEnabledCipherSuites() methods. Aswith all other SSL/TLS cipher suites, if a cipher suite is notsupported by the peer, then it will not be selected during ciphernegotiation. Furthermore, if the application and/or server cannotacquire the necessary Kerberos credentials, then the Kerberoscipher suites also will not be selected.
The following is an example of a TLS client that will only usetheTLS_KRB5_WITH_DES_CBC_SHA cipher suite:
// Create socketSSLSocketFactory sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault();SSLSocket sslSocket = (SSLSocket) sslsf.createSocket(tlsServer, serverPort);// Enable only one cipher suiteString enabledSuites[] = { "TLS_KRB5_WITH_DES_CBC_SHA" };sslSocket.setEnabledCipherSuites(enabledSuites);You must have the Kerberos infrastructure set up in yourdeployment environment before you can use the Kerberos ciphersuites with JSSE. In particular, both the TLS client and servermust have accounts set up with the Kerberos Key Distribution Center(KDC). At runtime, if one or more of the Kerberos cipher suiteshave been enabled, then the TLS client and server will acquiretheir Kerberos credentials associated with their respective accountfrom the KDC. For example, a TLS server running on the machinemach1.imc.org in the Kerberos realmIMC.ORG must have an account with the namehost/mach1.imc.org@IMC.ORG and be configured to usethe KDC forIMC.ORG. For information about usingKerberos with Java SE, see theKerberos Requirementsdocument.
An application can acquire its Kerberos credentials by using theJava Authentication andAuthorization Service (JAAS) and a Kerberos login module. TheJDK comes with aKerberos login module. You can use the Kerberos cipher suiteswith JSSE with or without JAAS programming, similar to how you canuse theJava GenericSecurity Services (Java GSS) with or without JAASprogramming.
To use the Kerberos cipher suites with JSSE without JAASprogramming, you must use the index namescom.sun.net.ssl.server orother for theTLS server JAAS configuration entry, andcom.sun.net.ssl.client orother for theTLS client, and set thejavax.security.auth.useSubjectCredsOnly systemproperty to false. For example, a TLS server that is not using JAASprogramming might have the following JAAS configuration file:
com.sun.net.ssl.server {com.sun.security.auth.module.Krb5LoginModule requiredprincipal="host/mach1.imc.org@IMC.ORG"useKeyTab=truekeyTab=mach1.keytabstoreKey=true;};An example of how to use Java GSS and Kerberos without JAASprogramming is described in theJava GSS Tutorial.You can adapt it to use JSSE by replacing Java GSS calls with JSSEcalls.
To use the Kerberos cipher suites with JAAS programming, you canuse any index name because your application is responsible forcreating the JAASLoginContext using the index name,and then wrapping the JSSE calls inside of aSubject.doAs() orSubject.doAsPrivileged() call. An example of how touse JAAS with Java GSS and Kerberos is described in theJava GSS Tutorial. Youcan adapt it to use JSSE by replacing Java GSS calls with JSSEcalls.
If you have trouble using or configuring the JSSE application touse Kerberos, see theTroubleshootingsection of the Java GSS Tutorial.
To determine the identity of the peer of an SSL connection, usethegetPeerPrincipal() method in the followingclasses:
javax.net.ssl.SSLSessionjavax.net.ssl.HttpsURLConnectionjavax.net.HandshakeCompletedEventSimilarly, to get the identity that was sent to the peer (toidentify the local entity), use thegetLocalPrincipal() method in these classes. ForX509-based cipher suites, these methods will return an instance ofjavax.security.auth.x500.X500Principal; for Kerberoscipher suites, these methods will return an instance ofjavax.security.auth.kerberos.KerberosPrincipal.
JSSE applications usegetPeerCertificates() andsimilar methods injavax.net.ssl.SSLSession,javax.net.ssl.HttpsURLConnection, andjavax.net.HandshakeCompletedEvent classes to obtaininformation about the peer. When the peer does not have anycertificates,SSLPeerUnverifiedException isthrown.
If the application must determine only the identity of the peeror identity sent to the peer, then it should use thegetPeerPrincipal() andgetLocalPrincipal() methods, respectively. It shouldusegetPeerCertificates() andgetLocalCertificates() methods only if it must examinethe contents of those certificates. Furthermore, the applicationmust be prepared to handle the case where an authenticated peermight not have any certificate.
When the security manager has been enabled, in addition to theSocketPermission needed to communicate with the peer,a TLS client application that uses the Kerberos cipher suites alsoneeds the following permission:
javax.security.auth.kerberos.ServicePermission(serverPrincipal, "initiate");
In the preceding code,serverPrincipal is the Kerberosprincipal name of the TLS server that the TLS client will becommunicating with (such ashost/mach1.imc.org@IMC.ORG). A TLS server applicationneeds the following permission:
javax.security.auth.kerberos.ServicePermission(serverPrincipal, "accept");
In the preceding code,serverPrincipal is the Kerberosprincipal name of the TLS server (such ashost/mach1.imc.org@IMC.ORG). If the server or clientmust contact the KDC (for example, if its credentials are notcached locally), then it also needs the following permission:
javax.security.auth.kerberos.ServicePermission(tgtPrincipal, "initiate");In the preceding code,tgtPrincipal is the principal name ofthe KDC (such as
krbtgt/IMC.ORG@IMC.ORG).The PKCS#12 (PersonalInformation Exchange Syntax Standard) specifies a portableformat for storage and/or transport of a user's private keys,certificates, miscellaneous secrets, and other items. The SunJSSEprovider supplies a complete implementation of the PKCS12java.security.KeyStore format for reading and writingPKCS12 files. This format is also supported by other toolkits andapplications for importing and exporting keys and certificates,such as Netscape/Mozilla, Microsoft's Internet Explorer, andOpenSSL. For example, these implementations can export clientcertificates and keys into a file using the.p12 file nameextension.
With the SunJSSE provider, you can access PKCS12 keys throughtheKeyStore API with a keystore type of PKCS12. Inaddition, you can list the installed keys and associatedcertificates by using thekeytool command with the-storetype option set topkcs12. For moreinformation aboutkeytool, seeSecurity Tools.
Note: Unlike the JKS store format, to access a PKCS#12store, you must supply it with a password.
The SNI extension is a feature that extends the SSL/TLSprotocols to indicate what server name the client is attempting toconnect to during handshaking. Servers can use server nameindication information to decide if specificSSLSocketorSSLEngine instances should accept a connection. Forexample, when multiple virtual or name-based servers are hosted ona single underlying network address, the server application can useSNI information to determine whether this server is the exactserver that the client wants to access. Instances of this class canbe used by a server to verify the acceptable server names of aparticular type, such as host names. For more information, seesection 3 ofTLSExtensions (RFC 6066).
Developers of client applications can explicitly set the servername indication using theSSLParameters.setServerNames(List<SNIServerName>serverNames) method. The following example illustrates thisfunctionality:
SSLSocketFactory factory = ...SSLSocket sslSocket = factory.createSocket("172.16.10.6", 443);// SSLEngine sslEngine = sslContext.createSSLEngine("172.16.10.6", 443);SNIHostName serverName = new SNIHostName("www.example.com");List<SNIServerName> serverNames = new ArrayList<>(1);serverNames.add(serverName);SSLParameters params = sslSocket.getSSLParameters();params.setServerNames(serverNames);sslSocket.setSSLParameters(params);// sslEngine.setSSLParameters(params);Developers of server applications can use theSNIMatcher class to decide how to recognize servername indication. The following two examples illustrate thisfunctionality:
Example 1
SSLSocket sslSocket = sslServerSocket.accept();SNIMatcher matcher = SNIHostName.createSNIMatcher("www\\.example\\.(com|org)");Collection<SNIMatcher> matchers = new ArrayList<>(1);matchers.add(matcher);SSLParameters params = sslSocket.getSSLParameters();params.setSNIMatchers(matchers);sslSocket.setSSLParameters(params);Example 2
SSLServerSocket sslServerSocket = ...;SNIMatcher matcher = SNIHostName.createSNIMatcher("www\\.example\\.(com|org)");Collection<SNIMatcher> matchers = new ArrayList<>(1);matchers.add(matcher);SSLParameters params = sslServerSocket.getSSLParameters();params.setSNIMatchers(matchers);sslServerSocket.setSSLParameters(params);SSLSocket sslSocket = sslServerSocket.accept();The following list provides examples for the behavior of theSNIMatcher when receiving various server nameindication requests in the ClientHello message:
Matcher configured towww\\.example\\.com:
www.example.com,then it will be accepted and a confirmation will be sent in theServerHello message.www.example.org,then it will be rejected with anunrecognized_namefatal error.Matcher configured towww\\.invalid\\.com:
www.example.com,then it will be rejected with anunrecognized_namefatal error.www.example.org,then it will be accepted and a confirmation will be sent in theServerHello message.Matcher is not configured:
Any requested host name will be accepted but no confirmationwill be sent in the ServerHello message.
For descriptions of new classes that implement the SNIextension, see:
For examples, seeUsing the Server NameIndication (SNI) Extension.
In JDK 8u251 and later, Application Layer Protocol Negotiation (ALPN) enablesyou to negotiate an application protocol for a TLS connection;see TLS Application Layer Protocol Negotiation.
This section contains information for troubleshooting JSSE.First, it provides some commonconfiguration problems and ways to solve them,and then it describes helpfuldebuggingutilities.
This section describes some common configuration problems thatmight arise when you use JSSE.
Problem: When negotiating an SSL connection, the clientor server throws aCertificateException.
Cause 1: This is generally caused by the remote sidesending a certificate that is unknown to the local side.
Solution 1: The best way to debug this type of problem isto turn on debugging (seeDebugging Utilities)and watch as certificates are loaded and when certificates arereceived via the network connection. Most likely, the receivedcertificate is unknown to the trust mechanism because the wrongtrust file was loaded. Refer to the following sections for moreinformation:
Cause 2: The system clock is not set correctly. In thiscase, the perceived time may be outside the validity period on oneof the certificates, and unless the certificate can be replacedwith a valid one from a truststore, the system must assume that thecertificate is invalid, and therefore throw the exception.
Solution 2: Correct the system clock time.
Problem: Attempt to store trusted certificates in PKCS12keystore throwsjava.security.KeyStoreException:TrustedCertEntry not supported.
Cause: Storing trusted certificates in a PKCS12 keystoreis not supported. PKCS12 is mainly used to deliver private keyswith the associated certificate chains. It does not have any notionof "trusted" certificates. In terms of interoperability, otherPKCS12 vendors have the same restriction. Browsers such as Mozillaand Internet Explorer do not accept a PKCS12 file with only trustedcertificates.
Solution: Use the JKS keystore for storing trustedcertificates.
Problem: When running a program that uses JSSE, anexception occurs indicating that an SSL service is not available.For example, an exception similar to one of the following isthrown:
Exception in thread "main" java.net.SocketException:no SSL Server SocketsException in thread "main":SSL implementation not available
Cause: There was a problem withSSLContextinitialization, for example, due to an incorrect password on akeystore or a corrupted keystore (a JDK vendor once shipped akeystore in an unknown format, and that caused this type oferror).
Solution: Check initialization parameters. Ensure thatany keystores specified are valid and that the passwords specifiedare correct. One way that you can check this is by trying to usethekeytoolcommand-line utility to examine the keystores and the relevantcontents.
Problem: When trying to run a simple SSL server program,the following exception is thrown:
Exception in thread "main" javax.net.ssl.SSLException:No available certificate corresponding to the SSL cipher suites which are enabled...
Cause: Various cipher suites require certain types of keymaterial. For example, if an RSA cipher suite is enabled, then anRSAkeyEntry must be available in the keystore. If nosuch key is available, then this cipher suite cannot be used. Thisexception is thrown if there are no available key entries for allof the cipher suites enabled.
Solution: Create key entries for the various cipher suitetypes, or use an anonymous suite. Anonymous cipher suites areinherently dangerous because they are vulnerable to MITM(man-in-the-middle) attacks. For more information, seeRFC 2246.
Refer to the following sections to learn how to pass the correctkeystore and certificates:
Problem 1: When handshaking, the client and/or serverthrow this exception.
Cause 1: Both sides of an SSL connection must agree on acommon cipher suite. If the intersection of the client's ciphersuite set with the server's cipher suite set is empty, then youwill see this exception.
Solution 1: Configure the enabled cipher suites toinclude common cipher suites, and be sure to provide an appropriatekeyEntry for asymmetric cipher suites. Also seeRuntime Exception: "No availablecertificate..." in this section.)
Problem 2: When using Netscape Navigator or MicrosoftInternet Explorer to access files on a server that only hasDSA-based certificates, a runtime exception occurs indicating thatthere are no cipher suites in common.
Cause 2: By default,keyEntries created withkeytool use DSA public keys. If only DSAkeyEntries exist in the keystore, then only DSA-basedcipher suites can be used. By default, Navigator and InternetExplorer send only RSA-based cipher suites. Because theintersection of client and server cipher suite sets is empty, thisexception is thrown.
Solution 2: To interact with Navigator or InternetExplorer, you should create certificates that use RSA-based keys.To do this, specify the-keyalg RSA option when usingkeytool. For example:
keytool -genkeypair -alias duke -keystore testkeys -keyalg rsa
Problem: JSSE seems to stall on first access.
Cause: JSSE must have a secure source of random numbers.The initialization takes a while.
Solution: Provide an alternative generator of randomnumbers, or initialize ahead of time when the overhead will not benoticed:
SecureRandom sr = new SecureRandom();sr.nextInt();SSLContext.init(..., ..., sr);
Thejava-home/lib/security/java.security file alsoprovides a way to specify the source of seed data forSecureRandom. See the contents of the file for moreinformation.
Problem: The following code snippet was written usingcom.sun.net.ssl.HttpsURLConnection in JSSE 1.0.x:
import com.sun.net.ssl.*;...deleted...HttpsURLConnection urlc = new URL("https://example.com/").openConnection();When running under JSSE 1.0.x, this code returns ajavax.net.ssl.HttpsURLConnection object and throws aClassCastException.
Cause: By default, opening an HTTPS URL will create ajavax.net.ssl.HttpsURLConnection.
Solution: Previous releases of the JDK (release 6 andearlier) did not ship with an HTTPS URL implementation. The JSSE1.0.x implementation did provide such an HTTPS URL handler, and theinstallation guide described how to set the URL handler search pathto obtain a JSSE 1.0.xcom.sun.net.ssl.HttpsURLConnection implementation.
In the JDK, there is an HTTPS handler in the default URL handlersearch path. It returns an instance ofjavax.net.ssl.HttpsURLConnection. By prepending theold JSSE 1.0.x implementation path to the URL search path via thejava.protocol.handler.pkgs variable, you can stillobtain acom.sun.net.ssl.HttpsURLConnection, and thecode will no longer throw cast exceptions.
% java -Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol YourClass
System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");Problem: A socket attempts to connect, sends aClientHello message, and is immediately disconnected.
Cause: Some SSL/TLS servers will disconnect if aClientHello message is received in a format they do not understandor with a protocol version number that they do not support.
Solution: Try adjusting the enabled protocolson the client side. This involves modifying or invoking some of thefollowing system properties and methods:
https.protocols for theHttpsURLConnectionclassjdk.tls.client.protocolsSSLContext.getInstance methodSSLEngine.setEnabledProtocols methodSSLSocket.setEnabledProtocols methodSSLParameters.setProtocols andSSLEngine.setSSLParameters methodsSSLParameters.setProtocols andSSLSocket.setSSLParameters methodsFor backwards compatibility, some SSL/TLS implementations (suchasSunJSSE) can send SSL/TLS ClientHello messages encapsulated inthe SSLv2 ClientHello format. TheSunJSSE provider supports thisfeature. If you want to use this feature, add the "SSLv2Hello"protocol to the enabled protocol list, if necessary. (Also see theProtocolssection, which lists the protocols that are enabled by default fortheSunJSSE provider.)
The SSL/TLS RFC standards require that implementations negotiateto the latest version both sides speak, but some non-conformingimplementation simply hang up if presented with a version theydon't understand. For example, some older server implementationsthat speak only SSLv3 will shutdown if TLSv1.2 is requested. Inthis situation, consider using a SSL/TLS version fallbackscheme:
For example, if the enabled protocol list on the client isTLSv1, TLSv1.1, and TLSv1.2, a typical SSL/TLS version fallbackscheme may look like:
Note: A fallback to a previous version normallymeans security strength downgrading to a weaker protocol. It is notsuggested to use a fallback scheme unless it is really necessary,and you clearly know that the server does not support a higherprotocol version.
Note: As part of disabling SSLv3, some servershave also disabled SSLv2Hello, which means communications withSSLv2Hello-active clients (e.g. JDK 1.5/6) will fail. Starting withJDK 7, SSLv2Hello default to disabled on clients, enabled onservers.
Problem: A handshake is attempted and fails when itcannot find a required algorithm. Examples might include:
Exception in thread ...deleted......deleted...Caused by java.security.NoSuchAlgorithmException: Cannot find anyprovider supporting RSA/ECB/PKCS1Paddingor
Caused by java.security.NoSuchAlgorithmException: Cannot find anyprovider supporting AES/CBC/NoPadding
Cause:SunJSSE uses JCE for all its cryptographicalgorithms. By default, the Oracle JDK will use the StandardExtension ClassLoader to load the SunJCE provider located injava-home/lib/ext/sunjce_provider.jar. If the filecannot be found or loaded, or if the SunJCE provider has beenderegistered from theProvider mechanism and analternative implementation from JCE is not available, then thisexception will be thrown.
Solution: Ensure that the SunJCE is available by checkingthat the file is loadable and that the provider is registered withtheProvider interface. Try to run the following codein the context of your SSL connection:
import javax.crypto.*;System.out.println("=====Where did you get AES=====");Cipher c = Cipher.getInstance("AES/CBC/NoPadding");System.out.println(c.getProvider());Problem: If you receive acom.sun.deploy.net.FailedDownloadException when tryingto obtain application resources from your web server over SSL, andyour web server uses the virtual host with Server Name Indication(SNI) extension (such as Apache HTTP Server), then you may have notconfigured your web server correctly.
Cause: Because Java SE 7 supports the SNI extension inthe JSSE client, the requested host name of the virtual server isincluded in the first message sent from the client to the serverduring the SSL handshake. The server may deny the client's requestfor a connection if the requested host name (the server nameindication) does not match the expected server name, which shouldbe specified in the virtual host's configuration. This triggers anSSL handshake unrecognized name alert, which results in aFailedDownloadException being thrown.
Solution: To better diagnose the problem, enable tracingthrough the Java Console. SeeJava Console, Tracing, andLogging for more information. If the cause of the problem isjavax.net.ssl.SSLProtocolException: handshake alert:unrecognized_name, it is likely that the virtual hostconfiguration for SNI is incorrect. If you are using Apache HTTPServer, seeName-basedVirtual Host Support for information about configuring virtualhosts. In particular, ensure that theServerNamedirective is configured properly in a<VirtualHost> block.
For more information, see the following:
JSSE provides dynamic debug tracing support. This is similar tothe support used for debugging access control failures in the JavaSE platform. The generic Java dynamic debug tracing support isaccessed with thejava.security.debug system property,whereas the JSSE-specific dynamic debug tracing support is accessedwith thejavax.net.debug system property.
Note: Thedebug utility is not anofficially supported feature of JSSE.
To view the options of the JSSE dynamic debug utility, use thefollowing command-line option on thejava command:
-Djavax.net.debug=help
Note: If you specify the valuehelp with either dynamic debug utility when running aprogram that does not use any classes that the utility was designedto debug, you will not get the debugging options.
The following complete example shows how to get a list of thedebug options for an application namedMyApp that usessome of the JSSE classes:
java -Djavax.net.debug=help MyApp
TheMyApp application will not run after the debughelp information is printed, as the help code causes theapplication to exit.
Current options are:
all: Turn on all debuggingssl: Turn on SSL debuggingThe following can be used with thessl option:
record: Enable per-record tracinghandshake: Print each handshake messagekeygen: Print key generation datasession: Print session activitydefaultctx: Print default SSL initializationsslctx: PrintSSLContext tracingsessioncache: Print session cache tracingkeymanager: Print key manager tracingtrustmanager: Print trust manager tracingMessages generated from thehandshake option can bewidened with these options:
data: Hex dump of each handshake messageverbose: Verbose handshake message printingMessages generated from therecord option can bewidened with these options:
plaintext: Hex dump of record plaintextpacket: Print raw SSL/TLS packetsThejavax.net.debug property value must be eitherall orssl, optionally followed by debugspecifiers. You can use one or more options. You donot haveto have a separator between options, although a separator such as acolon (:) or a comma (,) helps readability. It does not matter whatseparators you use, and the ordering of the option keywords is alsonot important.
For an introduction to reading this debug information, see theguide,Debugging TLSConnections.
The following are examples of using thejavax.net.debug property:
To view all debugging messages:
java -Djavax.net.debug=all MyApp
To view the hexadecimal dumps of each handshake message, enterthe following (the colons are optional):
java -Djavax.net.debug=ssl:handshake:data MyApp
To view the hexadecimal dumps of each handshake message, and toprint trust manager tracing, enter the following (the commas areoptional):
java -Djavax.net.debug=SSL,handshake,data,trustmanager MyApp
The following code examples are included in this section:
This section provides examples of source code that illustratehow to use JSSE to convert an unsecure socket connection to asecure socket connection. The code in this section is excerptedfrom the bookJava SE 6 Network Security by MarcoPistoia, et. al.
First, "Socket Example Without SSL" shows sample code that canbe used to set up communication between a client and a server usingunsecure sockets. This code is then modified in "Socket Examplewith SSL" to use JSSE to set up secure socket communication.
The following examples demonstrates server-side and client-sidecode for setting up an unsecure socket connection.
In a Java program that acts as a server and communicates with aclient using sockets, the socket communication is set up with codesimilar to the following:
import java.io.*;import java.net.*;. . .int port = availablePortNumber;ServerSocket s;try {s = new ServerSocket(port);Socket c = s.accept();OutputStream out = c.getOutputStream();InputStream in = c.getInputStream();// Send messages to the client through// the OutputStream// Receive messages from the client// through the InputStream} catch (IOException e) { }The client code to set up communication with a server usingsockets is similar to the following:
import java.io.*;import java.net.*;. . .int port = availablePortNumber;String host = "hostname";try {s = new Socket(host, port);OutputStream out = s.getOutputStream();InputStream in = s.getInputStream();// Send messages to the server through// the OutputStream// Receive messages from the server// through the InputStream} catch (IOException e) { }The following examples demonstrate server-side and client-sidecode for setting up a secure socket connection.
In a Java program that acts as a server and communicates with aclient using secure sockets, the socket communication is set upwith code similar to the following. Differences between thisprogram and the one for communication using unsecure sockets arehighlighted in bold.
import java.io.*;importjavax.net.ssl.*;. . .int port = availablePortNumber;SSLServerSocket s;try {SSLServerSocketFactory sslSrvFact =(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();s = (SSLServerSocket)sslSrvFact.createServerSocket(port);SSLSocket c =(SSLSocket)s.accept();OutputStream out = c.getOutputStream();InputStream in = c.getInputStream();// Send messages to the client through// the OutputStream// Receive messages from the client// through the InputStream}catch (IOException e) {}The client code to set up communication with a server usingsecure sockets is similar to the following, where differences withthe unsecure version are highlighted in bold:
import java.io.*;importjavax.net.ssl.*;. . .int port = availablePortNumber;String host = "hostname";try {SSLSocketFactory sslFact =(SSLSocketFactory)SSLSocketFactory.getDefault();SSLSocket s = (SSLSocket)sslFact.createSocket(host, port);OutputStream out = s.getOutputStream();InputStream in = s.getInputStream();// Send messages to the server through// the OutputStream// Receive messages from the server// through the InputStream}catch (IOException e) {}The JSSE sample programs illustrate how to use JSSE to:
When you use the sample code, be aware that the sample programsare designed to illustrate how to use JSSE. They are not designedto be robust applications.
Note: Setting up secure communications involvescomplex algorithms. The sample programs provide no feedback duringthe setup process. When you run the programs, be patient: you maynot see any output for a while. If you run the programs with thejavax.net.debug system property set toall, you will see more feedback. For an introductionto reading this debug information, see the guide,Debugging TLS Connections.
Most of the sample code is located in thesamples subdirectory of the same directoryas that containing the document you are reading. Follow that linkto see a listing of all the sample code files and text files. Thatpage also provides a link to a ZIP file that you can download toobtain all the sample code files, which is helpful if you areviewing this documentation from the web.
The following sections describe the samples. For moreinformation, seeREADME.txt.
The sample programs in thesamples/socketsdirectory illustrate how to set up a secure socket connectionbetween a client and a server.
When running the sample client programs, you can communicatewith an existing server, such as a commercial web server, or youcan communicate with the sample server program,ClassFileServer. You can run the sample client and thesample server programs on different machines connected to the samenetwork, or you can run them both on one machine but from differentterminal windows.
All the sampleSSLSocketClient* programs in thesamples/sockets/client directory (andURLReader*programs described inSample CodeIllustrating HTTPS Connections) can be run with theClassFileServer sample server program. An example ofhow to do this is shown inRunningSSLSocketClientWithClientAuth with ClassFileServer. You canmake similar changes to runURLReader,SSLSocketClient, orSSLSocketClientWithTunneling withClassFileServer.
If an authentication error occurs during communication betweenthe client and the server (whether using a web server orClassFileServer), it is most likely because thenecessary keys are not in thetruststore(trust key database). For example, theClassFileServeruses a keystore calledtestkeys containing the privatekey forlocalhost as needed during the SSL handshake.Thetestkeys keystore is included in the samesamples/sockets/server directory as theClassFileServer source. If the client cannot find acertificate for the corresponding public key oflocalhost in the truststore it consults, then anauthentication error will occur. Be sure to use thesamplecacerts truststore (which contains the publickey and certificate of thelocalhost), as described inthe next section.
When running the sample programs that create a secure socketconnection between a client and a server, you will need to make theappropriate certificates file (truststore) available. For both theclient and the server programs, you should use the certificatesfilesamplecacerts from thesamplesdirectory. Using this certificates file will allow the client toauthenticate the server. The file contains all the commonCertificate Authority (CA) certificates shipped with the JDK (inthe cacerts file), plus a certificate forlocalhostneeded by the client to authenticatelocalhost whencommunicating with the sample serverClassFileServer.TheClassFileServer uses a keystore containing theprivate key forlocalhost that corresponds to thepublic key insamplecacerts.
To make thesamplecacerts file available to boththe client and the server, you can either copy it to the filejava-home/lib/security/jssecacerts, rename it tocacerts, and use it to replace thejava-home/lib/security/cacerts file, or add thefollowing option to the command line when running thejava command for both the client and the server:
-Djavax.net.ssl.trustStore=path_to_samplecacerts_file
The password for thesamplecacerts truststore ischangeit. You can substitute your own certificates inthe samples by using thekeytool utility.
If you use a browser, such as Netscape Navigator or Microsoft'sInternet Explorer, to access the sample SSL server provided in theClassFileServer example, then a dialog box may pop upwith the message that it does not recognize the certificate. Thisis normal because the certificate used with the sample programs isself-signed and is for testing only. You can accept the certificatefor the current session. After testing the SSL server, you shouldexit the browser, which deletes the test certificate from thebrowser's namespace.
For client authentication, a separatedukecertificate is available in the appropriate directories. The publickey and certificate is also stored in thesamplecacerts file.
TheSSLSocketClient.javaprogram demonstrates how to create a client that uses anSSLSocket to send an HTTP request and to get aresponse from an HTTPS server. The output of this program is theHTML source forhttps://www.verisign.com/index.html.
You must not be behind a firewall to run this program asprovided. If you run it from behind a firewall, you will get anUnknownHostException because JSSE cannot find a paththrough your firewall towww.verisign.com. To createan equivalent client that can run from behind a firewall, set upproxy tunneling as illustrated in the sample programSSLSocketClientWithTunneling.
TheSSLSocketClientWithTunneling.javaprogram illustrates how to do proxy tunneling to access a secureweb server from behind a firewall. To run this program, you mustset the following Java system properties to the appropriatevalues:
java -Dhttps.proxyHost=webproxy-Dhttps.proxyPort=ProxyPortNumberSSLSocketClientWithTunneling
Note: Proxy specifications with the-D options are optional. Replacewebproxy withthe name of your proxy host andProxyPortNumber with theappropriate port number.
The program will return the HTML source file fromhttps://www.verisign.com/index.html.
TheSSLSocketClientWithClientAuth.javaprogram shows how to set up a key manager to do clientauthentication if required by a server. This program also assumesthat the client is not outside a firewall. You can modify theprogram to connect from inside a firewall by following the exampleinSSLSocketClientWithTunneling.
To run this program, you must specify three parameters: host,port, and requested file path. To mirror the previous examples, youcan run this program without client authentication by setting thehost towww.verisign.com, the port to443, and the requested file path tohttps://www.verisign.com/. The output when using theseparameters is the HTML for the websitehttps://www.verisign.com/.
To runSSLSocketClientWithClientAuth to do clientauthentication, you must access a server that requests clientauthentication. You can use the sample programClassFileServer as this server. This is described inthe following sections.
The program referred to herein asClassFileServeris made up of two files:ClassFileServer.javaandClassServer.java.
To execute them, runClassFileServer.class, whichrequires the following parameters:
port can be any available unused port number, forexample, you can use the number2001.docroot indicates the directory on the server thatcontains the file you want to retrieve. For example, on Solaris,you can use /home/userid/ (whereuserid refers toyour particular UID), whereas on Microsoft Windows systems, you canuse c:\.TLS is an optional parameter that indicates thatthe server is to use SSL or TLS.true is an optional parameter that indicates thatclient authentication is required. This parameter is only consultedif the TLS parameter is set.Note: TheTLS andtrue parameters are optional. If you omit them,indicating that an ordinary (not TLS) file server should be used,without authentication, then nothing happens. This is because oneside (the client) is trying to negotiate with TLS, while the other(the server) is not, so they cannot communicate.
Note: The server expects GET requests in theformGET /path_to_file.
You can use the sample programsSSLSocketClientWithClientAuthandClassFileServer to set up authenticatedcommunication, where the client and server are authenticated toeach other. You can run both sample programs on different machinesconnected to the same network, or you can run them both on onemachine but from different terminal windows or command promptwindows. To set up both the client and the server, do thefollowing:
ClassFileServer from one machineor terminal window, as described inRunningClassFileServer.SSLSocketClientWithClientAuth onanother machine or terminal window.SSLSocketClientWithClientAuth requires the followingparameters:host is the host name of the machine that you areusing to runClassFileServer.port is the same port that you specified forClassFileServer.requestedfilepath indicates the path to the filethat you want to retrieve from the server. You must give thisparameter as/filepath. Forward slashes are requiredin the file path because it is used as part of a GET statement,which requires forward slashes regardless of what type of operatingsystem you are running. The statement is formed as follows:
"GET " + requestedfilepath + " HTTP/1.0"
Note: You can modify the otherSSLClient* applications'GET commands toconnect to a local machine runningClassFileServer.
There are two primary APIs for accessing secure communicationsthrough JSSE. One way is through a socket-level API that can beused for arbitrary secure communications, as illustrated by theSSLSocketClient,SSLSocketClientWithTunneling, andSSLSocketClientWithClientAuth (with and withoutClassFileServer) sample programs.
A second, and often simpler, way is through the standard JavaURL API. You can communicate securely with an SSL-enabled webserver by using the HTTPS URL protocol or scheme using thejava.net.URL class.
Support for HTTPS URL schemes is implemented in many of thecommon browsers, which allows access to secured communicationswithout requiring the socket-level API provided with JSSE.
An example URL ishttps://www.verisign.com.
The trust and key management for the HTTPS URL implementation isenvironment-specific. The JSSE implementation provides an HTTPS URLimplementation. To use a different HTTPS protocol implementation,set thejava.protocol.handler.pkgs system property to the package name. See thejava.net.URL class documentation for details.
The samples that you can download with JSSE include two sampleprograms that illustrate how to create an HTTPS connection. Both ofthese sample programs (URLReader.java andURLReaderWithOptions.java)are in the samples/urls directory.
TheURLReader.javaprogram illustrates using the URL class to access a secure site.The output of this program is the HTML source forhttps://www.verisign.com/. By default, the HTTPSprotocol implementation included with JSSE is used. To use adifferent implementation, set the system propertyjava.protocol.handler.pkgs value to be the name of thepackage containing the implementation.
If you are running the sample code behind a firewall, then youmust set thehttps.proxyHost andhttps.proxyPort system properties. For example, to usethe proxy host "webproxy" on port 8080, you can use the followingoptions for thejava command:
-Dhttps.proxyHost=webproxy-Dhttps.proxyPort=8080
Alternatively, you can set the system properties within thesource code with thejava.lang.System methodsetProperty(). For example, instead of using thecommand-line options, you can include the following lines in yourprogram:
System.setProperty("java.protocol.handler.pkgs", "com.ABC.myhttpsprotocol");System.setProperty("https.proxyHost", "webproxy");System.setProperty("https.proxyPort", "8080");TheURLReaderWithOptions.javaprogram is essentially the same as the URLReader.java program,except that it allows you to optionally input any or all of thefollowing system properties as arguments to the program when yourun it:
java.protocol.handler.pkgshttps.proxyHosthttps.proxyPorthttps.cipherSuitesTo runURLReaderWithOptions, enter the followingcommand:
java URLReaderWithOptions [-hproxyhost -pproxyport] [-kprotocolhandlerpkgs] [-cciphersarray]
Note: Multiple protocol handlers can beincluded in theprotocolhandlerpkgs argument as a listwith items separated by vertical bars. Multiple SSL cipher suitenames can be included in theciphersarray argument asa list with items separated by commas. The possible cipher suitenames are the same as those returned by theSSLSocket.getSupportedCipherSuites() method. The suitenames are taken from the SSL and TLS protocol specifications.
You need aprotocolhandlerpkgs argument only if youwant to use an HTTPS protocol handler implementation other than thedefault one provided by Oracle.
If you are running the sample code behind a firewall, then youmust include arguments for the proxy host and the proxy port.Additionally, you can include a list of cipher suites toenable.
Here is an example of runningURLReaderWithOptionsand specifying the proxy host "webproxy" on port 8080:
java URLReaderWithOptions -h webproxy -p 8080
The sample code in the samples/rmi directory illustrates how tocreate a secure Java Remote Method Invocation (RMI) connection. Thesample code is based on anRMI example that isbasically a "Hello World" example modified to install and use acustom RMI socket factory.
For more information about Java RMI, see theJava RMI documentation. This web pagepoints to Java RMI tutorials and other information about JavaRMI.
SSLEngine gives application developers flexibilitywhen choosing I/O and compute strategies. Rather than tie theSSL/TLS implementation to a specific I/O abstraction (such assingle-threadedSSLSockets),SSLEngineremoves the I/O and compute constraints from the SSL/TLSimplementation.
As mentioned earlier,SSLEngine is an advanced API,and is not appropriate for casual use. Some introductory samplecode is provided here that helps illustrate its use. The first demoremoves most of the I/O and threading issues, and focuses on manyof the SSLEngine methods. The second demo is a more realisticexample showing howSSLEngine might be combined withJava NIO to create a rudimentary HTTP/HTTPS server.
TheSSLEngineSimpleDemois a very simple application that focuses on the operation of theSSLEngine while simplifying the I/O and threadingissues. This application creates twoSSLEngine objectsthat exchange SSL/TLS messages via commonByteBufferobjects. A single loop serially performs all of the engineoperations and demonstrates how a secure connection is established(handshaking), how application data is transferred, and how theengine is closed.
TheSSLEngineResult provides a great deal ofinformation about the current state of theSSLEngine.This example does not examine all of the states. It simplifies theI/O and threading issues to the point that this is not a goodexample for a production environment; nonetheless, it is useful todemonstrate the overall function of theSSLEngine.
This section demonstrates how you can use thekeytool utility to create a simple JKS keystoresuitable for use with JSSE. First you make akeyEntry(with public and private keys) in the keystore, and then you make acorrespondingtrustedCertEntry (public keys only) in atruststore. For client authentication, you follow a similar processfor the client's certificates.
Note: Storing trust anchors and secret keys inPKCS12 is supported since JDK 8.
Note: It is beyond the scope of this example toexplain each step in detail. For more information, see thekeytool documentation forSolaris, Linux, or macOSorMicrosoftWindows.
User input is shown in bold.
Create a new keystore and self-signed certificate withcorresponding public and private keys.
%keytool -genkeypair -alias duke -keyalg RSA -validity 7 -keystore keystoreEnter keystore password:passwordWhat is your first and last name?[Unknown]:DukeWhat is the name of your organizational unit?[Unknown]:Java SoftwareWhat is the name of your organization?[Unknown]:Oracle, Inc.What is the name of your City or Locality?[Unknown]:Palo AltoWhat is the name of your State or Province?[Unknown]:CAWhat is the two-letter country code for this unit?[Unknown]:USIs CN=Duke, OU=Java Software, O="Oracle, Inc.",L=Palo Alto, ST=CA, C=US correct?[no]:yesEnter key password for <duke>(RETURN if same as keystore password):<CR>
Examine the keystore. Notice that the entry type iskeyEntry, which means that this entry has a privatekey associated with it).
%keytool -list -v -keystore keystoreEnter keystore password:passwordKeystore type: jksKeystore provider: SUNYour keystore contains 1 entryAlias name: dukeCreation date: Dec 20, 2001Entry type: keyEntryCertificate chain length: 1Certificate[1]:Owner: CN=Duke, OU=Java Software, O="Oracle, Inc.",L=Palo Alto, ST=CA, C=USIssuer: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=USSerial number: 3c22adc1Valid from: Thu Dec 20 19:34:25 PST 2001 until: Thu Dec 27 19:34:25 PST 2001Certificate fingerprints:MD5: F1:5B:9B:A1:F7:16:CF:25:CF:F4:FF:35:3F:4C:9C:F0SHA1: B2:00:50:DD:B6:CC:35:66:21:45:0F:96:AA:AF:6A:3D:E4:03:7C:74
Export and examine the self-signed certificate.
%keytool -export -alias duke -keystore keystore -rfc -file duke.cerEnter keystore password:passwordCertificate stored in file <duke.cer>%cat duke.cer-----BEGIN CERTIFICATE-----MIICXjCCAccCBDwircEwDQYJKoZIhvcNAQEEBQAwdjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlQYWxvIEFsdG8xHzAdBgNVBAoTFlN1biBNaWNyb3N5c3RlbXMsIEluYy4xFjAUBgNVBAsTDUphdmEgU29mdHdhcmUxDTALBgNVBAMTBER1a2UwHhcNMDExMjIxMDMzNDI1WhcNMDExMjI4MDMzNDI1WjB2MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0bzEfMB0GA1UEChMWU3VuIE1pY3Jvc3lzdGVtcywgSW5jLjEWMBQGA1UECxMNSmF2YSBTb2Z0d2FyZTENMAsGA1UEAxMERHVrZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1loObJzNXsi5aSr8N4XzDksD6GjTHFeqG9DUFXKEOQetfYXvA8F9uWtz8WInrqskLTNzwXgmNeWkoM7mrPpK6Rf5M3G1NXtYzvxyi473Gh1h9k7tjJvqSVKO7E1oFkQYeUPYifxmjbSMVirWZgvo2UmA1c76oNK+NhoHJ4qjeCUCAwEAATANBgkqhkiG9w0BAQQFAAOBgQCRPoQYw9rWWvfLPQuPXowvFmuebsTc28qI7iFWm6BJTT/qdmzti7B5MHOt9BeVEft3mMeBU0CS2guaBjDpGlf+zsK/UUi1w9C4mnwGDZzqY/NKKWtLxabZ5M+4MAKLZ92ePPKGpobM2CPLfM8ap4IgAzCbBKd8+CMp8yFmifze9Q==-----END CERTIFICATE-----
Alternatively, you could generate a Certificate Signing Request(CSR) with-certreq and send that to a CertificateAuthority (CA) for signing, See the section "Request a Signed Certificate from aCA" (Solaris, Linux, or macOSorWindows) inthekeytool documentation.
Import the certificate into a new truststore.
%keytool -import -alias dukecert -file duke.cer -keystore truststoreEnter keystore password:trustwordOwner: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=USIssuer: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=USSerial number: 3c22adc1Valid from: Thu Dec 20 19:34:25 PST 2001 until: Thu Dec 27 19:34:25 PST 2001Certificate fingerprints:MD5: F1:5B:9B:A1:F7:16:CF:25:CF:F4:FF:35:3F:4C:9C:F0SHA1: B2:00:50:DD:B6:CC:35:66:21:45:0F:96:AA:AF:6A:3D:E4:03:7C:74Trust this certificate? [no]:yesCertificate was added to keystore
Examine the truststore. Note that the entry type istrustedCertEntry, which means that a private key isnot available for this entry. It also means that this file is notsuitable as a keystore of theKeyManager.
%keytool -list -v -keystore truststoreEnter keystore password:trustwordKeystore type: jksKeystore provider: SUNYour keystore contains 1 entryAlias name: dukecertCreation date: Dec 20, 2001Entry type: trustedCertEntryOwner: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=USIssuer: CN=Duke, OU=Java Software, O="Oracle, Inc.", L=Palo Alto, ST=CA, C=USSerial number: 3c22adc1Valid from: Thu Dec 20 19:34:25 PST 2001 until: Thu Dec 27 19:34:25 PST 2001Certificate fingerprints:MD5: F1:5B:9B:A1:F7:16:CF:25:CF:F4:FF:35:3F:4C:9C:F0SHA1: B2:00:50:DD:B6:CC:35:66:21:45:0F:96:AA:AF:6A:3D:E4:03:7C:74
Now run your applications with the appropriate keystores.Because this example assumes that the defaultX509KeyManager andX509TrustManager areused, you select the keystores using the system propertiesdescribed inCustomizingJSSE.
% java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password Server% java -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword Client
Note: This example authenticated the serveronly. For client authentication, provide a similar keystore for theclient's keys and an appropriate truststore for the server.
This section provides code examples that illustrate how you canuse theServer Name Indication (SNI)extension for client-side and server-side applications, and how itcan be applied to a virtual infrastructure.
For all examples in this section, to apply the parameters afteryou set them, call thesetSSLParameters(SSLParameters)method on the correspondingSSLSocket,SSLEngine, orSSLServerSocket object.
The following is a list of use cases that require understandingof the SNI extension for developing a client application:
Case 1. The client wants to accesswww.example.com.
Set the host name explicitly:
SNIHostName serverName = new SNIHostName("www.example.com");List<SNIServerName> serverNames = new ArrayList<>(1);serverNames.add(serverName);sslParameters.setServerNames(serverNames);The client should always specify the host name explicitly.
Case 2. The client does not want to use SNI because theserver does not support it.
Disable SNI with an empty server name list:
List<SNIServerName> serverNames = new ArrayList<>(1);sslParameters.setServerNames(serverNames);
Case 3. The client wants to access URLhttps://www.example.com.
Oracle providers will set the host name in the SNI extension bydefault, but third-party providers may not support the defaultserver name indication. To keep your applicationprovider-independent, always set the host name explicitly.
Case 4. The client wants to switch a socket from server modeto client mode.
First switch the mode with the following method:sslSocket.setUseClientMode(true). Then reset theserver name indication parameters on the socket.
The following is a list of use cases that require understandingof the SNI extension for developing a server application:
Case 1. The server wants to accept all server name indicationtypes.
If you do not have any code dealing with the SNI extension, thenthe server ignores all server name indication types.
Case 2. The server wants to deny all server name indicationsof typehost_name.
Set an invalid server name pattern forhost_name:
SNIMatcher matcher = SNIHostName.createSNIMatcher("");Collection<SNIMatcher> matchers = new ArrayList<>(1);matchers.add(matcher);sslParameters.setSNIMatchers(matchers);Another way is to create anSNIMatcher subclasswith amatches() method that always returnsfalse:
class DenialSNIMatcher extends SNIMatcher {DenialSNIMatcher() {super(StandardConstants.SNI_HOST_NAME);}@Overridepublic boolean matches(SNIServerName serverName) {return false;}}SNIMatcher matcher = new DenialSNIMatcher();Collection<SNIMatcher> matchers = new ArrayList<>(1);matchers.add(matcher);sslParameters.setSNIMatchers(matchers);Case 3. The server wants to accept connections to any hostnames in theexample.com domain.
Set the recognizable server name forhost_name as apattern that includes all*.example.com addresses:
SNIMatcher matcher = SNIHostName.createSNIMatcher("(.*\\.)*example\\.com");Collection<SNIMatcher> matchers = new ArrayList<>(1);matchers.add(matcher);sslParameters.setSNIMatchers(matchers);Case 4. The server wants to switch a socket from client modeto server mode.
First switch the mode with the following method:sslSocket.setUseClientMode(false). Then reset theserver name indication parameters on the socket.
This section describes how to use the Server Name Indication(SNI) extension from within a virtual infrastructure. Itillustrates how to create a parser for ClientHello messages from asocket, provides examples of virtual server dispatchers usingSSLSocket andSSLEngine, describes whathappens when the SNI extension is not available, and demonstrateshow to create a failoverSSLContext.
Applications must implement an API to parse the ClientHellomessages from a socket. The following examples illustrate theSSLCapabilities andSSLExplorer classesthat can perform these functions.
SSLCapabilities.javaencapsulates the SSL/TLS security capabilities during handshaking(that is, the list of cipher suites to be accepted in an SSL/TLShandshake, the record version, the hello version, and the servername indication). It can be retrieved by exploring the network dataof an SSL/TLS connection via theSSLExplorer.explore()method.
SSLExplorer.javaexplores the initial ClientHello message from a TLS client, but itdoes not initiate handshaking or consume network data. TheSSLExplorer.explore() method parses the ClientHellomessage, and retrieves the security parameters intoSSLCapabilities. The method must be called beforehandshaking occurs on any TLS connections.
This section describes the procedure for using a virtual serverdispatcher based onSSLSocket.
Register the server name handler.
At this step, the application may create differentSSLContext objects for different server nameindications, or link a certain server name indication to aspecified virtual machine or distributed system.
For example, if the server name iswww.example.org,then the registered server name handler may be for a local virtualhosting web service. The local virtual hosting web service will usethe specifiedSSLContext. If the server name iswww.example.com, then the registered server namehandler may be for a virtual machine hosting on10.0.0.36. The handler may map this connection to thevirtual machine.
Create aServerSocket and accept the newconnection.
ServerSocket serverSocket = new ServerSocket(serverPort);Socket socket = serverSocket.accept();
Read and buffer bytes from the socket input stream, and thenexplore the buffered bytes.
InputStream ins = socket.getInputStream();byte[] buffer = new byte[0xFF];int position = 0;SSLCapabilities capabilities = null;// Read the header of TLS recordwhile (position < SSLExplorer.RECORD_HEADER_SIZE) {int count = SSLExplorer.RECORD_HEADER_SIZE - position;int n = ins.read(buffer, position, count);if (n < 0) {throw new Exception("unexpected end of stream!");}position += n;}// Get the required size to explore the SSL capabilitiesint recordLength = SSLExplorer.getRequiredSize(buffer, 0, position);if (buffer.length < recordLength) {buffer = Arrays.copyOf(buffer, recordLength);}while (position < recordLength) {int count = recordLength - position;int n = ins.read(buffer, position, count);if (n < 0) {throw new Exception("unexpected end of stream!");}position += n;}// Explorecapabilities = SSLExplorer.explore(buffer, 0, recordLength);if (capabilities != null) {System.out.println("Record version: " + capabilities.getRecordVersion());System.out.println("Hello version: " + capabilities.getHelloVersion());}Get the requested server name from the exploredcapabilities.
List<SNIServerName> serverNames = capabilities.getServerNames();
Look for the registered server name handler for this servername indication.
If the service of the host name is resident in a virtual machineor another distributed system, then the application must forwardthe connection to the destination. The application will need toread and write the raw internet data, rather then the SSLapplication from the socket stream.
Socket destinationSocket = new Socket(serverName, 443);// Forward buffered bytes and network data from the current socket to thedestinationSocket.If the service of the host name is resident in the same process,and the host name service can use theSSLSocketdirectly, then the application will need to set theSSLSocket instance to the server:
// Get service context from registered handler// or create the contextSSLContext serviceContext = ...SSLSocketFactory serviceSocketFac = serviceContext.getSSLSocketFactory();// wrap the buffered bytesByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, position);SSLSocket serviceSocket = (SSLSocket)serviceSocketFac.createSocket(socket, bais, true);// Now the service can use serviceSocket as usual.
This section describes the procedure for using a virtual serverdispatcher based onSSLEngine.
Register the server name handler.
At this step, the application may create differentSSLContext objects for different server nameindications, or link a certain server name indication to aspecified virtual machine or distributed system.
For example, if the server name iswww.example.org,then the registered server name handler may be for a local virtualhosting web service. The local virtual hosting web service will usethe specifiedSSLContext. If the server name iswww.example.com, then the registered server namehandler may be for a virtual machine hosting on10.0.0.36. The handler may map this connection to thevirtual machine.
Create aServerSocket orServerSocketChannel and accept the newconnection.
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.bind(...);...SocketChannel socketChannel = serverSocketChannel.accept();
Read and buffer bytes from the socket input stream, and thenexplore the buffered bytes.
ByteBuffer buffer = ByteBuffer.allocate(0xFF);SSLCapabilities capabilities = null;while (true) {// ensure the capacityif (buffer.remaining() == 0) {ByteBuffer oldBuffer = buffer;buffer = ByteBuffer.allocate(buffer.capacity() + 0xFF);buffer.put(oldBuffer);}int n = sc.read(buffer);if (n < 0) {throw new Exception("unexpected end of stream!");}int position = buffer.position();buffer.flip();capabilities = explorer.explore(buffer);buffer.rewind();buffer.position(position);buffer.limit(buffer.capacity());if (capabilities != null) {System.out.println("Record version: " +capabilities.getRecordVersion());System.out.println("Hello version: " +capabilities.getHelloVersion());break;}}buffer.flip(); // reset the buffer position and limitationGet the requested server name from the exploredcapabilities.
List<SNIServerName> serverNames = capabilities.getServerNames();
Look for the registered server name handler for this servername indication.
If the service of the host name is resident in a virtual machineor another distributed system, then the application must forwardthe connection to the destination. The application will need toread and write the raw internet data, rather then the SSLapplication from the socket stream.
Socket destinationSocket = new Socket(serverName, 443);// Forward buffered bytes and network data from the current socket to thedestinationSocket.If the service of the host name is resident in the same process,and the host name service can use theSSLEnginedirectly, then the application will simply feed the net data to theSSLEngine instance:
// Get service context from registered handler// or create the contextSSLContext serviceContext = ...SSLEngine serviceEngine = serviceContext.createSSLEngine();// Now the service can use the buffered bytes and other byte buffer as usual.
If there is no server name indication in a ClientHello message,then there is no way to select the proper service according to SNI.For such cases, the application may need to specify a defaultservice, so that the connection can be delegated to it if there isno server name indication.
TheSSLExplorer.explore() method does not check thevalidity of SSL/TLS contents. If the record format does not complywith SSL/TLS specification, or theexplore() method isinvoked after handshaking has started, then the method may throw anIOException and be unable to produce network data. Insuch cases, handle the exception thrown bySSLExplorer.explore() by using a failoverSSLContext, which is not used to negotiate an SSL/TLSconnection, but to close the connection with the proper alertmessage. The following example illustrates a failoverSSLContext. You can find an example of theDenialSNIMatcher class in Case 2 of theTypical Server-Side Usage Examples.
byte[] buffer = ... // buffered network databoolean failed = true; // SSLExplorer.explore() throws an exceptionSSLContext context = SSLContext.getInstance("TLS");// the failover SSLContextcontext.init(null, null, null);SSLSocketFactory sslsf = context.getSocketFactory();ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, position);SSLSocket sslSocket = (SSLSocket)sslsf.createSocket(socket, bais, true);SNIMatcher matcher = new DenialSNIMatcher();Collection<SNIMatcher> matchers = new ArrayList<>(1);matchers.add(matcher);SSLParameters params = sslSocket.getSSLParameters();params.setSNIMatchers(matchers); // no recognizable server namesslSocket.setSSLParameters(params);try {InputStream sslIS = sslSocket.getInputStream();sslIS.read();} catch (Exception e) {System.out.println("Server exception " + e);} finally {sslSocket.close();}The JDK Security API requires and uses a set of standard namesfor algorithms, certificates and keystore types. The specificationnames previously found here in Appendix A and in the other securityspecifications (JCA, CertPath) have been combined inJava Cryptography Architecture (JCA) Standard Algorithm Name Documentation for JDK 8. Specificprovider information can be found inJava Cryptography Architecture (JCA) Oracle Providers Documentation for JDK 8.
JSSE is fully pluggable and does not restrict the use ofthird-party JSSE providers in any way.
In the fall of 2009, a flaw was discovered in the SSL/TLSprotocols. A fix to the protocol was developed by the IETF TLSWorking Group, and current versions of the JDK contain this fix.The pageTransport Layer Security (TLS) Renegotiation Issue describes the situation in much more detail, alongwith interoperability issues when communicating with olderimplementations that do not contain this protocol fix
The following table contains the standard signature scheme names, which arethe algorithms used in the digital signatures of TLS connections and are alsodefined in theSignatureScheme sectionof the IANA TLS Registry.
| Signature Scheme | Specification |
|---|---|
| ecdsa_secp256r1_sha256 | RFC 8446 |
| ecdsa_secp384r1_sha384 | RFC 8446 |
| ecdsa_secp521r1_sha512 | RFC 8446 |
| ecdsa_sha1 | RFC 8446 |
| ed25519 | RFC 8446 |
| ed448 | RFC 8446 |
| rsa_pkcs1_sha1 | RFC 8446 |
| rsa_pkcs1_sha256 | RFC 8446 |
| rsa_pkcs1_sha384 | RFC 8446 |
| rsa_pkcs1_sha512 | RFC 8446 |
| rsa_pss_pss_sha256 | RFC 8446 |
| rsa_pss_pss_sha384 | RFC 8446 |
| rsa_pss_pss_sha512 | RFC 8446 |
| rsa_pss_rsae_sha256 | RFC 8446 |
| rsa_pss_rsae_sha384 | RFC 8446 |
| rsa_pss_rsae_sha512 | RFC 8446 |