SSL:400未发送所需证书

时间:2016-03-29 12:39:30

标签: java oracle ssl

代码和输入

我尝试建立SSL连接,并且我从服务器获得400 No required SSL certificate was sent响应。我是以标准方式执行此操作,例如here所描述的;我运行Java 8。

我的代码示例是:

    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 - 但它不会改变图片。
  • 安装Oracle policies因为在有关于某些跳过算法的通知之前,这个安装已经解决了#34;但总体结果仍然相同。
  • 设置System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true"); - 跛脚,但也没有改变日志Allow unsafe renegotiation: true中的消息(" false"显然)
  • 使用KeyManagerFactory.getDefaultAlgorithm()作为algorithm进行KeyManagerFactory.getInstance()通话。这引发了异常Get Key failed: Given final block not properly padded,据我所知,这是因为使用了错误的算法(阅读this)。我的默认算法是: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确认可信证书;查看thisthis个帖子。没有出现任何错误 - 但问题仍然存在。
  • 使用JAVA_PATH/jre/lib/security/cacerts将证书添加到全局密钥库(keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias Alias -file /path/to/certificate中的证书)(请参阅this);看起来导入操作是成功的,但它没有改变图片

调试中还注意到:ssl: KeyMgr: choosing key: 1 (verified: OK) - 不确定它是否相关,因为我不是SSL专家。

不幸的是我看不到服务器端的日志,所以我无法全面了解。

问题

这400错误的原因是什么?如何进一步发展(调试/尝试别的东西)?任何提示都将非常感激。

1 个答案:

答案 0 :(得分:3)

您的服务器要求提供客户端证书。您需要在客户端计算机上安装证书(由受信任的机构签名),并让您的程序了解它。

通常,您的服务器具有由组织的IT安全性或某些全球受信任的CA签名的证书(密钥用途设置为“TLS服务器身份验证”)。您应该从同一来源获得“TLS客户端身份验证”证书。

如果您在Wireshark中捕获TLS握手,您将看到ServerHello消息后跟“客户端证书请求”,您使用长度为0的“客户端证书”消息回复该消息。您的服务器选择拒绝此消息。