我目前正在开发一个在 Java 17 上运行的 QuickFIX/J 应用程序,旨在使用提供的 JKS 证书与外部方建立安全连接。尝试连接时,我遇到 java.security.cert.CertificateException 并显示消息
Certificates do not conform to algorithm constraints.
详情如下:
我已附上 QuickFIX/J 配置的相关部分和错误的堆栈跟踪。任何人都可以提供有关如何解决此证书问题的建议或建议任何可能防止此错误的配置吗?
非常感谢您提供的任何帮助!
ConnectionType=initiator
SocketConnectHost=my_ip
SocketConnectPort=my_port
SocketUseSSL=Y
CipherSuites=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
EnabledProtocols=TLSv1.2
SocketKeyStore=/path/cert.jks
SocketKeyStorePassword=my_passowrd
SocketTrustStore=/path-trust/truststore.jks
SocketTrustStorePassword=my_password
javax.net.ssl|ERROR|A2|NioProcessor-2|2024-05-08 16:28:46.528 BRT|TransportContext.java:370|Fatal (UNSUPPORTED_CERTIFICATE): Certificates do not conform to algorithm constraints (
"throwable" : {
java.security.cert.CertificateException: Certificates do not conform to algorithm constraints
at java.base/sun.security.ssl.AbstractTrustManagerWrapper.checkAlgorithmConstraints(SSLContextImpl.java:1573)
at java.base/sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(SSLContextImpl.java:1538)
at java.base/sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:1456)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:632)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:480)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1277)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1264)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:1209)
at org.apache.mina.filter.ssl.SslHandler.doTasks(SslHandler.java:816)
at org.apache.mina.filter.ssl.SslHandler.handshake(SslHandler.java:591)
at org.apache.mina.filter.ssl.SslHandler.messageReceived(SslHandler.java:356)
at org.apache.mina.filter.ssl.SslFilter.messageReceived(SslFilter.java:517)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:650)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:49)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1128)
at org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived(IoFilterAdapter.java:122)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:650)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireMessageReceived(DefaultIoFilterChain.java:643)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(AbstractPollingIoProcessor.java:539)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$1200(AbstractPollingIoProcessor.java:68)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.process(AbstractPollingIoProcessor.java:1224)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.process(AbstractPollingIoProcessor.java:1213)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:683)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: java.security.cert.CertPathValidatorException: Algorithm constraints check failed on signature algorithm: SHA1withRSA
at java.base/sun.security.provider.certpath.AlgorithmChecker.check(AlgorithmChecker.java:237)
at java.base/sun.security.ssl.AbstractTrustManagerWrapper.checkAlgorithmConstraints(SSLContextImpl.java:1569)
... 30 more}
以文本方式列出密码套件:
在这篇文章 QuickFIX/J CipherSuites 中,我收到了有关我需要通知哪些 CipherSuites 的提示。
感谢@ChristophJohn 和@dave_thompson_085 的帮助
我的任务是使用 JKS 证书与接受者建立连接。使用命令
keytool -list -v -keystore cert.jks -storepass my_password
检查证书后,我发现它采用了 SHA1withRSA
签名算法。
根据错误堆栈跟踪,我当前的 Java 安全策略不接受该算法。理想情况下,解决方案将涉及获取不使用 SHA1withRSA 的新证书。然而,由于我无法控制的限制,这是不可行的。因此,我不得不找到一种方法来调整我的 Java 安全属性以允许使用该算法。
java.security.properties
我使用企业 Java 映像在 Kubernetes 环境中运行我的应用程序。尽管多次尝试,我还是无法成功覆盖 java.security.properties 文件。
作为解决方法,我实现了一个运行时解决方案,其中涉及直接从代码动态修改 Java 安全设置。具体来说,我创建了两个在运行时传递的
List<String>
变量。这些列表用于以编程方式调整 jdk.certpath.disabledAlgorithms
属性中 jdk.tls.disabledAlgorithms
和 java.security.Security
中的条目。
对于这种特殊情况,我需要启用
SHA1withRSA
,它是禁用算法列表中找到的字符串 SHA1,
的一部分。以下是修改 jdk.certpath.disabledAlgorithms
属性的方法:
修改前:
MD2, SHA1, MD5, DSA, RSA keySize < 2048
修改后:
MD2, MD5, DSA, RSA keySize < 2048
此调整对于建立必要的连接至关重要,同时又不会过度损害周围基础设施的安全。
以下配置和代码片段演示了我如何在运行时调整 JVM 的安全设置以适应必要的算法。这是一种解决方法,应谨慎处理,因为它会削弱 JVM 的安全立场。
以下是我在
application.properties
文件中为开发和生产环境设置属性的方法:
# Default settings (effective in production)
app.list.jdk.certpath.disabledAlgorithms=empty,
app.list.jdk.tls.disabledAlgorithms=empty,
此 YAML 配置片段用于将环境变量传递给应用程序,指定要从禁用列表中删除哪些算法:
# Removing 'SHA1, '
- name: "app.list.jdk.certpath.disabledAlgorithms"
value: "SHA1\\, ,"
此 Java 方法在应用程序启动时执行,以根据提供的配置动态调整安全属性:
@ConfigProperty(name = "app.list.jdk.certpath.disabledAlgorithms")
List<String> appListJdkCertPathDisableAlgorithms;
@ConfigProperty(name = "app.list.jdk.tls.disabledAlgorithms")
List<String> appListJdkTlsDisableAlgorithms;
private void removeDisableAlgorithms() {
LOG.info("Original Certpath and TLS configuration");
LOG.info("Certpath disabled algorithms: " + Security.getProperty("jdk.certpath.disabledAlgorithms"));
LOG.info("TLS disabled algorithms: " + Security.getProperty("jdk.tls.disabledAlgorithms"));
LOG.info("Configured removals for Certpath: " + appListJdkCertPathDisableAlgorithms);
LOG.info("Configured removals for TLS: " + appListJdkTlsDisableAlgorithms);
String jdkCertPathDisabledAlgorithms = Security.getProperty("jdk.certpath.disabledAlgorithms");
for (String item : appListJdkCertPathDisableAlgorithms) {
jdkCertPathDisabledAlgorithms = jdkCertPathDisabledAlgorithms.replace(item, "");
}
Security.setProperty("jdk.certpath.disabledAlgorithms", jdkCertPathDisabledAlgorithms);
String jdkTlsDisabledAlgorithms = Security.getProperty("jdk.tls.disabledAlgorithms");
for (String item : appListJdkTlsDisableAlgorithms) {
jdkTlsDisabledAlgorithms = jdkTlsDisabledAlgorithms.replace(item, "");
}
Security.setProperty("jdk.tls.disabledAlgorithms", jdkTlsDisabledAlgorithms);
LOG.info("Updated Certpath and TLS configuration");
LOG.info("Certpath disabled algorithms: " + Security.getProperty("jdk.certpath.disabledAlgorithms"));
LOG.info("TLS disabled algorithms: " + Security.getProperty("jdk.tls.disabledAlgorithms"));
}
此方法会操纵 JVM 安全设置,因此应极其谨慎地使用,尤其是在生产环境中。在考虑此类修改时,请务必评估潜在风险并咨询安全专家。