You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法验证ECDH ServerKeyExchange签名问题排查求助

阿里云云鉴权initFaceVerify接口SSL握手异常排查方案

问题描述

调用阿里云云鉴权initFaceVerify接口时出现SSL握手异常,错误提示为无法验证ECDH ServerKeyExchange签名。

环境信息

  • 目标域名:cloudauth.aliyuncs.com
  • 依赖组件:
    • okhttp-3.12.13.jar
    • tea-util-0.2.21.jar
    • tea-1.2.0.jar
  • 操作系统:Alpine 3.9.4
  • OpenJDK版本:1.8.0_275

异常栈信息

com.aliyun.tea.TeaUnretryableException: 无法验证ECDH ServerKeyExchange签名
    at com.aliyun.teaopenapi.Client.doRequest(Client.java:865)
    at com.aliyun.teaopenapi.Client.callApi(Client.java:1022)
    at com.aliyun.cloudauth20190307.Client.initFaceVerifyWithOptions(Client.java:893)
    at com.aliyun.cloudauth20190307.Client.initFaceVerify(Client.java:898)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: com.aliyun.tea.TeaRetryableException: 无法验证ECDH ServerKeyExchange签名
    at com.aliyun.tea.Tea.doAction(Tea.java:70)
    at com.aliyun.tea.Tea.doAction(Tea.java:82)
    at com.aliyun.teaopenapi.Client.doRequest(Client.java:784)
    ... 48 common frames omitted
Caused by: javax.net.ssl.SSLHandshakeException: 无法验证ECDH ServerKeyExchange签名
    at sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at sun.security.ssl.TransportContext.fatal(TransportContext.java:324)
    at sun.security.ssl.TransportContext.fatal(TransportContext.java:267)
    at sun.security.ssl.ECDHServerKeyExchange$ECDHServerKeyExchangeMessage.<init>(ECDHServerKeyExchange.java:325)
    at sun.security.ssl.ECDHServerKeyExchange$ECDHServerKeyExchangeConsumer.consume(ECDHServerKeyExchange.java:527)
    at sun.security.ssl.ServerKeyExchange$ServerKeyExchangeConsumer.consume(ServerKeyExchange.java:111)
    at sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:377)
    at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)
    at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:422)
    at sun.security.ssl.TransportContext.dispatch(TransportContext.java:182)
    at sun.security.ssl.SSLTransport.decode(SSLTransport.java:149)
    at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1143)
    at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1054)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:394)
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:320)
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:284)
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:169)
    at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:258)
    at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
    at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:127)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:257)
    at okhttp3.RealCall.execute(RealCall.java:93)
    at com.aliyun.tea.Tea.doAction(Tea.java:67)
    ... 50 common frames omitted
Caused by: java.security.SignatureException: 无法验证签名
    at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:413)
    at java.security.Signature$Delegate.engineVerify(Signature.java:1394)
    at java.security.Signature.verify(Signature.java:771)
    at sun.security.ssl.ECDHServerKeyExchange$ECDHServerKeyExchangeMessage.<init>(ECDHServerKeyExchange.java:320)
    ... 83 common frames omitted
Caused by: java.security.InvalidAlgorithmParameterException: null
    at sun.security.ec.ECDSASignature.verifySignedDigest(Native Method)
    at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:408)
    ... 86 common frames omitted

排查解决方案

1. 升级OpenJDK版本

当前使用的OpenJDK 1.8.0_275存在ECDSA签名验证的已知缺陷,尤其在Alpine系统下表现明显。建议升级至OpenJDK 8u301或更高版本,该版本修复了相关算法参数验证问题。

2. 替换加密算法实现

Alpine默认采用musl libc,部分加密算法支持不完善。可尝试:

  • 切换至基于GNU libc的OpenJDK版本
  • 引入BouncyCastle加密库作为替代实现:
    1. 添加bcprov-jdk15on依赖包
    2. 在代码中注册提供者:
      import org.bouncycastle.jce.provider.BouncyCastleProvider;
      import java.security.Security;
      
      // 程序启动时注册
      Security.addProvider(new BouncyCastleProvider());
      

3. 调整OkHttp SSL配置

强制OkHttp使用TLS 1.2+版本,并过滤不兼容的ECDH曲线:

import okhttp3.ConnectionSpec;
import okhttp3.OkHttpClient;
import javax.net.ssl.SSLSocketFactory;
import java.util.Collections;

// 自定义SSLSocketFactory实现,过滤不兼容曲线
class SSLSocketFactoryCompat extends SSLSocketFactory {
    // 实现逻辑:包装默认工厂,移除不支持的ECDH曲线
}

OkHttpClient client = new OkHttpClient.Builder()
        .sslSocketFactory(new SSLSocketFactoryCompat(), X509TrustManagerUtil.getDefault())
        .connectionSpecs(Collections.singletonList(ConnectionSpec.MODERN_TLS))
        .build();

4. 升级依赖版本

  • 将tea-1.2.0.jar、tea-util-0.2.21.jar升级至阿里云SDK最新稳定版
  • OkHttp升级到3.14.x版本(兼容JDK8),该版本修复了部分TLS握手兼容性问题

5. 验证服务器EC曲线支持

使用openssl s_client -connect cloudauth.aliyuncs.com:443命令查看服务器使用的EC曲线,若当前JDK不支持该曲线,需升级JDK或通过JVM参数启用对应曲线支持。

内容的提问来源于stack exchange,提问作者t _ liang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 05:44:59