X509ExtendedTrustManager Class

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

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

You can retrieve the ExtendedSSLSession by calling the SSLSocket.getHandshakeSession() method or the SSLEngine.getHandshakeSession() method.

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

In addition to TLS 1.2 support, the X509ExtendedTrustManager class also supports algorithm constraints and SSL layer hostname verification. For JSSE providers and trust manager implementations, the X509ExtendedTrustManager class is highly recommended rather than the legacy X509TrustManager interface.

Creating an X509ExtendedTrustManager subclass

You can either create an X509ExtendedTrustManager subclass yourself, as described in the following section, or obtain one from a provider-based TrustManagerFactory class, such as that supplied by the IBMJSSE2 provider. The PKIX or IbmX509TrustManagerFactory class returns an X509ExtendedTrustManager instance.

Creating your own X509ExtendedTrustManager subclass

This section describes how to create a subclass of the X509ExtendedTrustManager class. The method is very similar to the method described for the X509TrustManager class.
The following class uses the "PKIX" TrustManagerFactory class to locate a default X509ExtendedTrustManager object that will be used to make decisions about trust. If the default trust manager fails, the subclass can add other behavior. In the example, these locations are indicated by comments in the catch clauses.
import java.io.*;
import java.net.*;

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

public class MyX509ExtendedTrustManager extends X509ExtendedTrustManager {

	 /*
	  * The default PKIX X509ExtendedTrustManager.  We'll delegate
	  * decisions to it, and fall back to the logic in this class if the
	  * default X509ExtendedTrustManager doesn't 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 trustmanagers, look
		  * for an instance of X509TrustManager.  If found,
		  * use that as our "default" trust manager.
		  */
		 for (int i = 0; i <= dedTrustManager) 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();
	 }
}