You do not state which version of IBM MQ or what JRE that you are using, if it is not the most current version of IBM MQ and is being used with an Oracle JRE then the APAR IT10837 may help here.
There is a good write up of the above APAR at the end of IBM developerWorks blog "MQ Java, TLS Ciphers, Non-IBM JREs & APARs IT06775, IV66840, IT09423, IT10837 -- HELP ME PLEASE!" posted by Tom Leend. He includes a work around for Java clients that do not have this fix.
APAR IT10837
I've got one final APAR to mention and that is IT10837 (targeted for V7.1.0.8 and V7.5.0.7 and shipped in V8.0.0.5). This APAR affects applications running within Oracle JREs that use TLS CipherSuites to connect to a queue manager where the server-connection channel being used has the SSLCAUTH attributed set to "REQUIRED" (the default value). This means that the client should pass a certificate to the queue manager such that the connecting client can be authenticated by the MQ server.
When the application was running in an Oracle JRE, the SunJSSE provider was not creating a default internal Key Manager object for TLS socket connections, meaning that the client's signed personal certificates were not available for client authentication during the handshake. The IBM JSSE provider does do this based off the information passed via the Java System Properties:
Because a KeyManager object was not created by default, the client certificate was not passed to the queue manager (GSKit) for authentication. As such, the connection from the application would failed. In this scenario, the queue manager would write the following error message into its error log file:
AMQ9637 (Channel is lacking a certificate)
The fix for this APAR is for the MQ classes for JMS and classes for Java to read a certificate keystore, based on the information in the two Java System Properties noted above, and create a KeyManager based on that information in the case when com.ibm.mq.cfg.useIBMCipherMappings is set to the value false in the JVM . This can then be used when the SSLContext is created (which is subsequently used to create an SSLSocketFactory and eventually a secure socket object).
There is a local workaround which is for the application itself to create
TrustManagerFactory and KeyManagerFactory factory objects for the appropriate certificate stores and to initialise an SSLContext object these objects. From this SSLContext object and SSLSocketFactory can be created and passed to the MQ classes for JMS (by setting it on the JMS Connection Factory) or to the classes for Java (by setting it on the MQEnvironment or in a Hashtable passed to the MQQueueManager constructor). For example:
---- Code Snippet Start ----
KeyStore keyStore = KeyStore.getInstance("JKS");
java.io.FileInputStream keyStoreInputStream = new java.io.FileInputStream("/home/tom/myKeyStore.jks");
keyStore.load (keyStoreInputStream, password_char_array);
KeyStore trustStore trustStore = KeyStore.getInstance ("JKS");
java.io.FileInputStream trustStoreInputStream = new java.io.FileInputStream("/home/tom/myTrustStore.jks");
trustStore.load (trustStoreInputStream, password_char_array);
keyStoreInputStream.close();
trustStoreInputStream.close();
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore,password);
trustManagerFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(keyManagerFactory.getKeyManagers(),
trustManagerFactory.getTrustManagers(),
null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
// classes for JMS
myJmsConnectionFactory.setObjectProperty(
WMQConstants.WMQ_SSL_SOCKET_FACTORY, sslSocketFactory);
// classes for Java
MQEnvironment.sslSocketFactory = sslSocketFactory;
---- Code Snippet End ----