Java SSL双向握手报Invalidated cipher suites及handshake_failure求助
问题排查方案
- 密钥库用途配置错误:keystore和truststore的作用完全相反,你当前的配置逻辑不符合SSL双向认证的规则:
- keystore用于存放客户端自己的身份凭证(包含私钥的客户端p12证书),用来向服务端证明自身身份
- truststore用于存放你信任的服务端根证书/服务端公钥证书,用来验证服务端返回的证书合法性
你当前将服务端证书设为keystore、客户端证书设为truststore的操作是错误的,先调整配置再重试。
- TLS版本不兼容:从调试日志可以看出你当前使用的是TLSv1.1协议,目前绝大多数生产环境服务端都已禁用安全性不足的TLSv1.0、TLSv1.1版本,最低要求TLSv1.2及以上。你可以添加JVM启动参数强制启用高版本TLS:
-Dhttps.protocols=TLSv1.2,TLSv1.3,如果用Apache HttpComponents构造客户端,需要手动指定支持的协议列表为TLSv1.2、TLSv1.3。 - 证书链不完整:检查你导入truststore的证书是否覆盖了服务端证书的完整信任链:如果服务端证书是由中级CA签发,你只导入了叶子证书或者根证书,会导致信任链验证失败。需要将完整的根CA、中级CA证书都导入truststore。
- 加密套件不匹配:日志显示协商失败的加密套件为
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,如果服务端已禁用CBC模式的弱加密套件,会直接返回握手失败。可以升级JDK到8u291以上的版本,或者在构造SSLContext时手动指定符合服务端要求的高安全级别加密套件列表。 - cacerts导入操作校验:如果你要将服务端证书导入JDK默认的cacerts信任库,执行完导入操作后需要执行以下命令确认导入成功:
确认证书信息匹配、未被其他同名别名覆盖、有效期正常。keytool -list -alias 你导入时设置的别名 -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
内容的提问来源于stack exchange,提问作者k-wasilewski
相关产品推荐
相关产品推荐

