如何将 JVM 参数“-Dcom.ibm.mq.cfg.useIBMCipherMappings=false”添加到 IBM MQ?

How to add JVM argument `-Dcom.ibm.mq.cfg.useIBMCipherMappings=false` to IBM MQ?

最近我已经迁移到 IBM MQ v8 到 IBM MQ v9(特别是 v9.1.2.0)。我使用 SSL 与经纪人通信。因此,根据 Deprecated CipherSpecs 文档,IBM 已弃用 MQ 8 附带的密码套件数量,并且似乎我一直使用的所有密码套件都已在 v9 向上弃用。因此,我已经实施了新的 TLS 密码套件来与我在 Oracle JVM(版本 1.8.0_211)上运行的应用程序一起工作。自从我在应用程序中遇到异常以来;

com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2400'.
    at com.ibm.mq.MQManagedConnectionJ11.constructMQCD(MQManagedConnectionJ11.java:1437)
    at com.ibm.mq.MQManagedConnectionJ11.constructCNO(MQManagedConnectionJ11.java:1537)
    at com.ibm.mq.MQManagedConnectionJ11.<init>(MQManagedConnectionJ11.java:221)
    ... (Omitted the rest)

当我深入了解原因时,发现这是 IBM MQ 密码套件和 Oracle JRE 密码套件名称不匹配的问题。但我确实参考了 TLS CipherSpecs and CipherSuites in IBM MQ classes for JMS 文档来映射密码套件名称。我在我的应用程序中使用了一些在 IBM MQ 中也可用的 Equivalent CipherSuite (Oracle JRE) 列值。但仍然遇到问题。

在我发现 this answer 之后,建议将此 -Dcom.ibm.mq.cfg.useIBMCipherMappings=false 参数添加到 IBM MQ 的 JRE(据我所知)。这可能允许 IBM MQ 使用 Oracle 兼容的密码套件名称。我的问题是,

  1. 如何将此 JVM 参数 -Dcom.ibm.mq.cfg.useIBMCipherMappings=false 添加到 IBM MQ JRE?

这个 问题表明需要将相同的参数添加到应用程序作为系统 属性 System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false"),但它没有任何不同。

问题也说明了相同的解决方案,但没有提到如何将此 JVM 参数添加到 IBM MQ。

更新 1

我研究了如何向 IBM MQ 添加 JVM 参数。但我只能找到 Websphere 应用程序服务器的解决方案。

我目前在应用程序中使用的CipherSuite是;

TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (Oracle JRE complied)

IBM MQ 有相应的;

ECDHE_ECDSA_AES_128_CBC_SHA256 (IBM MQ complied)

更新 2

使用带有 stash 选项的 ikeyman 工具创建 key.kdb 文件后,队列管理器可以成功读取其中的证书。此外,我还包含了一个标有 ibmwebspheremq<lowercase_queue_manage_name> 的自签名证书。但是现在我在客户端遇到了不同的异常;

Exception in thread "main" com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2059'.
    at com.ibm.mq.MQManagedConnectionJ11.<init>(MQManagedConnectionJ11.java:255)
    at com.ibm.mq.MQClientManagedConnectionFactoryJ11._createManagedConnection(MQClientManagedConnectionFactoryJ11.java:450)
    at com.ibm.mq.MQClientManagedConnectionFactoryJ11.createManagedConnection(MQClientManagedConnectionFactoryJ11.java:487)
    at com.ibm.mq.StoredManagedConnection.<init>(StoredManagedConnection.java:97)

并且在 MQ 日志中我可以找到这个条目;

AMQ9637E: Channel is lacking a certificate.

有一些解释。

注意:在已删除的评论中添加答案以捕获提供给 OP 的信息。


请参阅以下 IBM MQ 知识中心页面,了解 table 显示证书类型与 MQ v9.1 的兼容性:

IBM MQ 9.1.x/IBM MQ/Securing/Confidentiality of messages/Enabling CipherSpecs

具有 ECDHE_ECDSA 的密码需要队列管理器的套件 b 证书。如果为您的应用程序使用客户端证书,它还需要是套件 b。

请注意,您可以将 ECDHE_RSA 密码与 non-suite b 证书一起使用。


队列管理器使用存储文件 (key.sth for example) 访问 kdb 文件。 java 在客户端的等价物是您指定 jks 密码。

经过一段时间的努力,我终于解决了这个问题。从一开始我就在应用程序端遇到了这个证书配置问题。即使在创建 self-signed 标记为 ibmwebspheremq<queue_manager_name> 的证书并使用 ikeyman 工具与客户端应用程序共享提取的证书后,AMQ9637E: Channel is lacking a certificate. 也发生了。

简而言之,为了完全解决这个问题,我做了以下工作;

将客户端 MQ 依赖项更新为 com.ibm.mq.allclient:v9.1.2.0。如果您使用的是 Maven,请使用以下依赖项 (MQC91: IBM MQ Clients).

<dependency>
    <groupId>com.ibm.mq</groupId>
    <artifactId>com.ibm.mq.allclient</artifactId>
    <version>9.1.2.0</version>
</dependency>

现在,如果应用程序在 Oracle JVM 上运行,我们应该说服 MQ 客户端库使用 Oracle JVM 兼容的密码套件名称。为此,请将此 -Dcom.ibm.mq.cfg.useIBMCipherMappings=false 添加为 JVM 标志或将此 System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false") 添加为系统 属性。

Select 用于与 MQ 通信的适当密码套件。此 TLS CipherSpecs and CipherSuites in IBM MQ classes for JMS document would be helpful as IBM has deprecated 数量的 密码规范 IBMMQ 9 及更高版本。

我建议使用 ECDHE_* 密码规范,因为它们提供 Ephemeral Keys to maintain Forward Secrecy

然后,使用 ikeyman GUI 工具,我创建了一个 self-signed 证书,在 ibmwebspheremq<queue_manager_name> 名称之后标记,而不是提取 .arm 文件,我将证书导出为.jks 个文件。 keystore.jkstruststore.jks 文件都从同一证书中导出。之后,使用系统属性将它们附加到应用程序;

System.setProperty("javax.net.ssl.trustStore", "truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "<password>");
System.setProperty("javax.net.ssl.keyStore", "keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "<password>");

使用此配置,SSL 握手问题消失了,但 IBM MQ 仍要求使用用户名和密码进行用户身份验证。为了提供它们,应将这些属性添加到 MQEnvironment

MQEnvironment.properties.put(com.ibm.mq.constants.CMQC.USER_ID_PROPERTY, "<user_name>");
MQEnvironment.properties.put(com.ibm.mq.constants.CMQC.PASSWORD_PROPERTY, "<password>");

在我的案例中,这些凭据是系统凭据。

如果您只是想像这样跳过用户身份验证,您可以像这样使用 runmqsc CLI 工具更新 IBMMQ 配置以跳过凭证检查(参考此 Turning on connection authentication on a queue manager 文档),

ALTER QMGR CONNAUTH(USE.PW)
DEFINE AUTHINFO(USE.PW) +
AUTHTYPE(IDPWOS) +
FAILDLAY(10) +
CHCKLOCL(OPTIONAL) +
CHCKCLNT(OPTIONAL)
REFRESH SECURITY TYPE(CONNAUTH)

请注意,需要将 CHCKCLNT 值设置为 OPTIONAL 以忽略客户端用户凭据检查。 IBM MQ 应该开始使用客户端应用程序,同时在这些配置后启用 SSL。

感谢@JoshMc 支持解决此问题。