Java SSL:400未发送所需的证书
代码和输入 我正在尝试建立SSL连接,并且从服务器收到Java SSL:400未发送所需的证书,java,oracle,ssl,Java,Oracle,Ssl,代码和输入 我正在尝试建立SSL连接,并且从服务器收到400未发送所需SSL证书的响应。我用一种标准的方式来做这件事,就像上面描述的那样;我运行Java8 我的代码示例如下: OkHttpClient client = new OkHttpClient(); KeyStore keyStoreClient = getClientKeyStore(); KeyStore keyStoreServer = getServerKeyStore(); String
400未发送所需SSL证书的响应。我用一种标准的方式来做这件事,就像上面描述的那样;我运行Java8
我的代码示例如下:
OkHttpClient client = new OkHttpClient();
KeyStore keyStoreClient = getClientKeyStore();
KeyStore keyStoreServer = getServerKeyStore();
String algorithm = ALGO_DEFAULT;//this is defined as "PKIX"
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
keyManagerFactory.init(keyStoreClient, PASSWORD_SERVER.toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
trustManagerFactory.init(keyStoreServer);
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
client.setSslSocketFactory(sslContext.getSocketFactory());
client.setConnectTimeout(32, TimeUnit.SECONDS); // connect timeout
client.setReadTimeout(32, TimeUnit.SECONDS); // socket timeout
return client;
下面是我用来发送GET请求的代码:
public String get(String url) throws IOException
{
String callUrl = URL_LIVE.concat(url);
Request request = new Request.Builder()
.url(callUrl)
.build();
Response response = this.client.newCall(request).execute();
return response.body().string();
}
我启用了:
System.setProperty("javax.net.debug", "ssl");
因此,要查看调试消息-但没有错误/警告/警报,唯一的事情是在最后:
main, called close()
main, called closeInternal(true)
main, SEND TLSv1.2 ALERT: warning, description = close_notify
main, WRITE: TLSv1.2 Alert, length = 26
main, called closeSocket(true)
这是我唯一可以视为“不正常”的东西(但我怀疑这是真的)
我试过:
- 不同的协议禁用/启用。例如,对套接字强制执行
TLSv1
/TLSv1.1
,但没有成功。为了尝试这一点,我将我的ssl工厂包装到另一个禁用/启用某些协议的工厂中
- 禁用
SSLv2Hello
——但不会改变画面李>
- 安装是因为之前有一些关于跳过的算法的通知,这次安装“解决”了这个问题,但总体结果仍然是一样的
- 设置
System.setProperty(“sun.security.ssl.allowUnsafeRenegotiation”,“true”)代码>-蹩脚,但除了日志中的消息之外,也没有更改任何内容允许不安全的重新协商:true
(显然是“false”)
- 使用
KeyManagerFactory.getDefaultAlgorithm()
作为KeyManagerFactory.getInstance()调用的algorithm
。这引发了异常Get Key失败:给定的最后一个块没有正确填充,据我所知,这是因为使用了错误的算法(读取)。我的默认算法是:SunX509
- 使用
keytool-importcert-file/path/to/certificate-keystore keystore.jks-alias“alias”
将证书直接添加到我的计算机,然后通过System.setProperty(“javax.net.ssl.trustStore”、“/path/to/keystore.jks”)在我的程序中使用它代码>设置密码:System.setProperty(“javax.net.ssl.trustStorePassword”、“mypassword”)代码>(我在keytool
中设置了密码,然后用yes
确认了可信证书);见和帖子。此问题未引发任何错误,但问题仍然存在
- 使用:
keytool-import-trustcacerts-keystore-cacerts-storepass changeit-noprompt-alias alias-file/PATH/to/certificate
将证书添加到全局密钥库(位于JAVA_PATH/jre/lib/security/cacerts
中);看起来导入操作已成功,但未更改图片
调试中还有一个注意事项:ssl:KeyMgr:choosing key:1(verified:OK)
-不确定它是否相关,因为我不是ssl专家
不幸的是,我看不到服务器端日志,因此无法观察完整的情况
问题
这400错误的原因是什么?我如何进一步(调试/尝试其他方法)?任何提示都将不胜感激。您的服务器正在请求客户端证书。您需要在客户端计算机上安装一个证书(由受信任的机构签名),并让您的程序知道它
通常,您的服务器有一个证书(密钥用途设置为“TLS服务器身份验证”),该证书由您的组织的IT安全部门或某个全球受信任的CA签署。您应该从同一来源获得“TLS客户端身份验证”证书
如果您在Wireshark中捕获TLS握手,您将看到ServerHello消息,后面是“客户端证书请求”,您将使用长度为0的“客户端证书”消息对其进行回复。您的服务器选择拒绝此操作。我有一个证书,我有:keytool-importcert-file/path/here-keystore keystore.jks-alias“alias”
,然后设置密码。在我的程序中,我做了:System.setProperty(“javax.net.ssl.trustStore”,“/path/to/jks”)
和System.setProperty(“javax.net.ssl.trustStorePassword”、“password”)代码>但我仍然有同样的问题。我做的对吗?从尝试,您没有客户端证书,除非您已创建(1)密钥对和(2)自签名证书或(3)CSR和(4)由CA签名,并且这些操作都无法在JDK的信任库中有效执行。我有pkcs12格式的客户端证书。我尝试导出它,但实际上成功地使用了keytool-importkeystore-destkeystore-srckeystore cert-srcstoretype PKCS12-srcstorepass certPass-alias 1
,我知道certPass
是有效的,因为我能够用它解锁PKCS12证书,并在其中看到证书+私钥。我发现了问题。就像@EJP说的,自签名证书。我现在已经修复了所有问题。