WMQ JMS API SSL Sun JDK and SSL_RSA_WITH_AES_128_C

2020-06-28 16:09发布

问题:

How do I get a JMS Client using SSL_RSA_WITH_AES_128_CBC_SHA (in the queue connection factory) to connect to a server using TLS_RSA_WITH_AES_128_CBC_SHA

  • Client Sun JDK 7 win
  • Server IBM Power (i)
  • MQ version 7.1 on the server
  • MQ version 7.5.0.4 on the client
  • Connections with MQ Explorer works fine
  • the below code works with the ibm JDK C:\Program Files\IBM\WebSphere MQ Explorer\jre\jre\bin
  • the below code does not work with "C:\Program Files\Java\jdk1.7.0_67\bin with Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 7 Download installed

Code:

       // Instantiate the initial context
        String contextFactory = "com.sun.jndi.fscontext.RefFSContextFactory";
        Hashtable environment = new Hashtable();
        environment.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
        environment.put(Context.PROVIDER_URL, initialContextUrl);
        Context context = new InitialDirContext(environment);
        System.out.println("Initial context found!");

        String keystoreName = System.getProperty("javax.net.ssl.keyStore");
        System.out.println("keystoreName " + keystoreName + " canRead " + new File(keystoreName).canRead());
        String truststoreName = System.getProperty("javax.net.ssl.trustStore");
        System.out.println("truststoreName " + keystoreName + " canRead " + new File(truststoreName).canRead());


        // Lookup the connection factory
        JmsConnectionFactory cf = (JmsConnectionFactory) context.lookup(connectionFactoryFromJndi);


        System.out.println("CF = " + cf.getClass().getName());

        MQConnectionFactory mqcf = (MQConnectionFactory) cf;
        System.out.println("getSSLCipherSuite:" + mqcf.getSSLCipherSuite());
        System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());

        // Lookup the destination
        destination = (JmsDestination) context.lookup(destinationFromJndi);
        System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());

        // Create JMS objects
        connection = cf.createConnection();
        System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());

        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());

        consumer = session.createConsumer(destination);
        System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());

        // Start the connection

        connection.start();
        System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());

Gives me:

 Initial context found!
keystoreName C:/Users/...key.jks canRead true
truststoreName C:/Users/.../key.jks canRead true
CF = com.ibm.mq.jms.MQConnectionFactory
getSSLCipherSuite:SSL_RSA_WITH_AES_128_CBC_SHA
getSSLSocketFactory:null
getSSLSocketFactory:null
keyStore is : C:/Users/.../key.jks
keyStore type is : jks
keyStore provider is : 
init keystore
init keymanager of type SunX509
***
found key for : ibmwebspheremquserid
.....
  Valid from Mon May 14 23:59:46 CEST 2012 until Thu May 14 23:59:46 CEST 2015

trigger seeding of SecureRandom
done seeding SecureRandom
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
com.ibm.msg.client.jms.DetailedJMSException: JMSWMQ0018: Failed to connect to queue manager 'qm' with connection mode 'Client' and host name 'host(1414)'.
Check the queue manager is started and if running in client mode, check there is a listener running. Please see the linked exception for more information.
Inner exception(s):
com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2393' ('MQRC_SSL_INITIALIZATION_ERROR').
com.ibm.mq.jmqi.JmqiException: CC=2;RC=2393;AMQ9204: Connection to host 'host(1414)' rejected. [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2393;AMQ9771: SSL handshake failed. [1=java.lang.IllegalArgumentException[Unsupported ciphersuite SSL_RSA_WITH_AES_128_CBC_SHA],3=host/host:1414 (10.20.28.12),4=SSLSocket.createSocket,5=default]],3=host(1414),5=RemoteTCPConnection.makeSocketSecure]
com.ibm.mq.jmqi.JmqiException: CC=2;RC=2393;AMQ9771: SSL handshake failed. [1=java.lang.IllegalArgumentException[Unsupported ciphersuite SSL_RSA_WITH_AES_128_CBC_SHA],3=host/host:1414 (10.20.28.12),4=SSLSocket.createSocket,5=default]
java.lang.IllegalArgumentException: Unsupported ciphersuite SSL_RSA_WITH_AES_128_CBC_SHA
FAILURE

回答1:

Switch to the IBM JRE/JDK and it will work.



回答2:

Using SSL from the Oracle JVM (JSSE)

See also "What TLS cipherspecs/ciphersuites are supported when connecting from Oracle Java (non-IBM JRE) to MQ queue manager?"

In MQ Client version 8.0.0.2 there is a patch is included to use the TLS with Oracle JVM, this works with lanes answer above

The get this to work you will need the latest MQ Client that contains IV66840: WMQ V7 JAVA/JMS: ADD SUPPORT FOR SELECTED TLS CIPHERSPECS WHEN RUNNING IN NON-IBM JAVA RUNTIME ENVIRONMENT
http://www-01.ibm.com/support/docview.wss?uid=swg1IV66840
(download)

Depending on your location you may also need to install Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 8 (download)

To use this you have to configured by using the JVM argument:

  -Dcom.ibm.mq.cfg.useIBMCipherMappings=false

Note that the default security implementation behaviour differs between Oracle and IBM JVMs :

The Oracle JSSE Reference guide says:

If the KeyManager[] parameter is null, then an empty KeyManager will be defined for this context.

The IBM JSSE Reference guide says:

If the KeyManager[] paramater is null, the installed security providers will be searched for the highest-priority implementation of the KeyManagerFactory, from which an appropriate KeyManager will be obtained.

Which means that you have to setup your own ssl context

SSLContext  sslcontext = SSLContext.getInstance("TLS");
String  keyStore = System.getProperty("javax.net.ssl.keyStore");
String  keyStoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType());
String  keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword","");
KeyManager[]    kms = null;
if (keyStore != null)
{
    KeyManagerFactory   kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    KeyStore    ks = KeyStore.getInstance(keyStoreType);
    if (keyStore != null && !keyStore.equals("NONE")) {
        fs = new FileInputStream(keyStore);
    ks.load(fs, keyStorePassword.toCharArray());
    if (fs != null)
        fs.close();
    char[]  password = null;
    if (keyStorePassword.length() > 0)
        password = keyStorePassword.toCharArray();
    kmf.init(ks,password);
    kms = kmf.getKeyManagers();
}
sslcontext.init(kms,null,null);

And then supply that to the MQ JMS client:

    JmsConnectionFactory cf = ...                                                                     

    MQConnectionFactory mqcf = (MQConnectionFactory) cf;              
    mqcf.setSSLSocketFactory(sslcontext.getSocketFactory());  

If using a application server this might be handled by your application server.



标签: java ibm-mq