4

I'm trying to connect my .NET (8.0) application to IBM MQ over TLS using X.509 certificate-based authentication, but running into issues during the SSL handshake.

Using Python + pymqi, I was able to successfully establish a secure connection with IBM MQ using TLS. IBM provides the GSKit-based .kdb keystore mechanism. The connection uses a .kdb trust store generated from .pem files and works well with the pymqi library and the underlying GSKit.

Here’s a simplified version of my working Python setup:

 cd = pymqi.CD() cd.ChannelName = b'SSL.CHANNEL' cd.ConnectionName = b'mqhost.example.com(1414)' cd.SSLCipherSpec = b'TLS_RSA_WITH_AES_128_CBC_SHA256' cd.ChannelType = pymqi.CMQC.MQCHT_CLNTCONN cd.TransportType = pymqi.CMQC.MQXPT_TCP sco = pymqi.SCO() sco.KeyRepository = b'/path/to/keystore' # .kdb, .rdb, .sth files qmgr = pymqi.QueueManager(None) qmgr.connect_with_options(b'QM1', cd, sco, user=b'mquser', password=b'securepass') queue = pymqi.Queue(qmgr, b'TEST.QUEUE') queue.put(b'Hello from Python!') queue.close() qmgr.disconnect()* 

In .NET 8, the IBM MQ client does not use GSKit the same way. Instead, it relies on the Windows certificate store (or .pfx files) for managing X.509 certificates.

Here’s what I’ve tried:

Installed the root and intermediate certificates in the CurrentUser store.

Set up SSL_CIPHER_SPEC and basic connection properties.

Verified the certs are visible in the Windows store.

Yet, the .NET client fails during the TLS handshake, with generic errors — possibly due to missing private key linkage, or incompatible keystore handling.

Here’s the representative code:

using IBM.WMQ; using System.Collections; using System.Security.Cryptography.X509Certificates; X509Store rootStore = new X509Store(StoreName.Root, StoreLocation.CurrentUser); rootStore.Open(OpenFlags.ReadWrite); rootStore.Add(new X509Certificate2("path/to/root.crt")); rootStore.Close(); X509Store caStore = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser); caStore.Open(OpenFlags.ReadWrite); caStore.Add(new X509Certificate2("path/to/intermediate.crt")); caStore.Close(); Hashtable queueProperties = new Hashtable { { MQC.HOST_NAME_PROPERTY, "mqhost.example.com" }, { MQC.CHANNEL_PROPERTY, "SSL.CHANNEL" }, { MQC.PORT_PROPERTY, 1414 }, { MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED }, { MQC.SSL_CIPHER_SPEC_PROPERTY, "TLS_RSA_WITH_AES_128_CBC_SHA256" } }; using var queueManager = new MQQueueManager("QM1", queueProperties); // Receive or send logic here... 

Python (via pymqi) uses IBM's GSKit and .kdb file for SSL trust configuration. .NET does not use .kdb, instead expects certs in Windows/ User cert store or PKCS#12 (.pfx) format if done programmatically.

There’s no built-in way to load .kdb directly in .NET using IBM’s client (unlike Python).

How can I successfully connect a .NET Core / .NET 8 application to IBM MQ using X.509 certificates? I need to resolve these TLS handshake or trust issues.

Edit 1

Since our application is containerized, running on a Linux distro, we have tried two separate mechanisms to register the certificate:

FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base COPY /keystore/aa_root.crt /usr/local/share/ca-certificates/ COPY /keystore/aa_intermediate.crt /usr/local/share/ca-certificates/ RUN chmod 644 /usr/local/share/ca-certificates/aa_root.crt RUN chmod 644 /usr/local/share/ca-certificates/aa_intermediate.crt RUN update-ca-certificates USER $APP_UID WORKDIR /app 

To the user certificates in the deployment script

 X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadWrite); store.Add(new X509Certificate2(X509Certificate2.CreateFromCertFile("./keystore/aa_root.crt"))); store.Close(); store = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadWrite); store.Add(new X509Certificate2(X509Certificate2.CreateFromCertFile("./keystore/aa_intermediate.crt"))); store.Close(); 

We have also tried setting some of the extended SSL properties as below with no luck:

 string strQueueManagerName = "QM1"; string strChannelName = "DEV.APP.SVRCONN"; string strQueueName = "DEV.QUEUE.1"; string strServerName = "192.168.1.13"; string strUserID = "app"; string strPassword = "passw0rd"; int intPort = 1414; /*string strQueueManagerName = "EMQSCGW1"; string strChannelName = "UNILODE.01"; string strQueueName = "CGOOPSHDLG.UNILODE.OPSDATA.01"; string strServerName = "mqiptstage.aa.com"; string strUserID = ""; string strPassword = ""; int intPort = 1442;*/ var factoryFactory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ); var cf = factoryFactory.CreateConnectionFactory(); cf.SetStringProperty(XMSC.WMQ_HOST_NAME, strServerName); cf.SetStringProperty(XMSC.USERID, strUserID); cf.SetStringProperty(XMSC.PASSWORD, strPassword); cf.SetIntProperty(XMSC.WMQ_PORT, intPort); cf.SetStringProperty(XMSC.WMQ_CHANNEL, strChannelName); cf.SetIntProperty(XMSC.WMQ_CONNECTION_MODE, XMSC.WMQ_CM_CLIENT); cf.SetIntProperty(XMSC.WMQ_CLIENT_RECONNECT_OPTIONS, XMSC.WMQ_CLIENT_RECONNECT_Q_MGR); cf.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, strQueueManagerName); //cf.SetStringProperty(XMSC.WMQ_SSL_CIPHER_SPEC, "TLS_RSA_WITH_AES_128_CBC_SHA256"); 
6
  • Have you loaded the private key into the USER keystore? You would not use X509Store to do that, those would be used with .NET 8 on Linux. You would add { MQC.SSL_CERT_STORE_PROPERTY, "*USER" } to your queueProperties. You can use the export option of your kdb tool to export the private key to a pkcs12 format which can be imported into windows by opening the file with a pfx extension. Commented Jul 27 at 17:57
  • Yes, this application run in docker in a Linux-based container, using a Debian-based .NET 8 runtime image from Microsoft's official container registry. ``` FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base COPY /keystore/aa_root.crt /usr/local/share/ca-certificates/ RUN chmod 644 /usr/local/share/ca-certificates/aa_root.crt RUN update-ca-certificates ``` Commented Jul 27 at 19:53
  • Even if you use X509Store on Linux you still need to add { MQC.SSL_CERT_STORE_PROPERTY, "*USER" } to your queueProperties. Commented Jul 28 at 5:40
  • @JoshMc I have edited the question for your consideration Commented Jul 29 at 21:43
  • 1
    @halfer, have removed the images and updated the post. thanks Commented Jul 30 at 5:35

1 Answer 1

1

Just an update folks,
our .NET managed client was attempting to negotiate a higher CipherSpec than what the MQ channel on their end was initially configured to support.
cf.SetStringProperty(XMSC.WMQ_SSL_CIPHER_SPEC, "TLS_RSA_WITH_AES_128_CBC_SHA256");
`

by updating the MQ channel configuration to use ANY_TLS12_OR_HIGHER, it resolved the issue.
The logs were quite visible at MQ queue manager level but on .NET side the logs were quite generic, strange.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.