Java 警告:未找到合适的证书 - 无需客户端身份验证即可继续

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37869430/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:44:53  来源:igfitidea点击:

Warning: no suitable certificate found - continuing without client authentication

javasslmutual-authentication

提问by P.K

Team I am facing following issue when try to complete a mutual handshake using HTTPS

当我尝试使用 HTTPS 完成相互握手时,我面临以下问题

main, READ: TLSv1.2 Handshake, length = 30
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA1withRSA, SHA1withDSA, SHA1withECDSA, SHA256withRSA, Unknown (hash:0x4, signature:0x2), SHA256withECDSA, SHA384withRSA, Unknown (hash:0x5, signature:0x2), SHA384withECDSA
Cert Authorities:
<Empty>
main, READ: TLSv1.2 Handshake, length = 4
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>

My JAVA class is a follows

我的JAVA课程如下

public class ClientCustomSSL {

    @SuppressWarnings("deprecation")
    public final static void main(String[] args) throws Exception {
        // Trust own CA and all self-signed certs
        final String CLIENT_KEYSTORE = "yourkeystore.jks";
        final String CLIENT_TRUSTSTORE = "catruststore.jks";
        final char[] KEYPASS_AND_STOREPASS_VALUE = "Hello1".toCharArray();


        System.setProperty("https.protocols", "TLSv1");

        //SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keystore, keyPassword)(YK,"Hello1".toCharArray(),"Hello1".toCharArray()).loadTrustMaterial(CA, "Hello1".toCharArray(), (TrustStrategy) new TrustSelfSignedStrategy()).build();

        KeyStore clientTrustStore = getStore(CLIENT_TRUSTSTORE, KEYPASS_AND_STOREPASS_VALUE);
        KeyStore clientKeyStore = getStore(CLIENT_KEYSTORE, KEYPASS_AND_STOREPASS_VALUE);  


        SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(clientKeyStore, "Hello1".toCharArray()).loadTrustMaterial(clientTrustStore,(TrustStrategy) new TrustSelfSignedStrategy()).build();
       CloseableHttpClient httpclient = HttpClients.custom().setSSLContext(sslContext).build();

        System.out.println("SSLCONETXT   **** " + sslContext.getProvider());
        try {

            HttpGet httpget = new HttpGet("https://myserver:10220");

            CloseableHttpResponse response = httpclient.execute(httpget);

            try {
                System.out.println("Inside TRY blcok"); 
                HttpEntity entity = response.getEntity();
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                EntityUtils.consume(entity);

            } catch (Exception e) {
                e.getMessage();
                e.printStackTrace();
            }
            finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }


    public static KeyStore getStore(final String storeFileName, final char[] password) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException 
    {
        final String JAVA_KEYSTORE = "jks";
        final KeyStore store = KeyStore.getInstance(JAVA_KEYSTORE);
        URL url = ClientCustomSSL.class.getClassLoader().getResource(storeFileName);
        String workingDir = System.getProperty("user.dir");
        System.out.println("Current working directory : " + workingDir);

        System.out.println("Value of URL *** " + url);
        InputStream inputStream = url.openStream();
        try {
            store.load(inputStream, password);
} finally {
    inputStream.close();
}

return store;
}

}

I am preparing a jar file and testing this from UNIX box

我正在准备一个 jar 文件并从 UNIX 框中测试它

Using following command java -Djavax.net.debug=ssl -cp snSSLclientTrustWithStoreCCC.jar cassandra.cass.ClientCustomSSL

使用以下命令 java -Djavax.net.debug=ssl -cp snSSLclientTrustWithStoreCCC.jar cassandra.cass.ClientCustomSSL

I have followed post why doesn't java send the client certificate during SSL handshake?and also completed all the steps mentioned by Bruno.

我已经关注了 为什么在 SSL 握手期间 java 不发送客户端证书?并且也完成了布鲁诺提到的所有步骤。

I am not sure what I am missing here. Any help will be appreciated

我不确定我在这里缺少什么。任何帮助将不胜感激

回答by user207421

  1. The client was unable to find a certificate in its keystore that was signed directly or indirectly by any of the signers mentioned in the CertificateRequestmessage.
  2. The reason for that was that the server didn't specify any trusted signers in that message.
  3. Which in turn means that the server's truststore is empty.
  1. 客户端无法在其密钥库中找到由CertificateRequest消息中提到的任何签署者直接或间接签署的证书。
  2. 原因是服务器没有在该消息中指定任何受信任的签名者。
  3. 这反过来意味着服务器的信任库是空的。

回答by peak

This is actually an area where the TLS 1.0 specification and TLS 1.1/1.2 differ.

这实际上是 TLS 1.0 规范和 TLS 1.1/1.2 不同的地方。

In particular, the following was added to Section 7.4.4 (Certificate Request) in TLS 1.1:

特别是,在 TLS 1.1 的第 7.4.4 节(证书请求)中添加了以下内容:

If the certificate_authorities list is empty then the client MAY send any certificate of the appropriate ClientCertificateType, unless there is some external arrangement to the contrary.

如果certificate_authorities 列表为空,则客户端可以发送任何适当ClientCertificateType 的证书,除非有一些相反的外部安排。

So empty Cert Authorities just means client is free to send any certificates to the server, which may or may not be accepted by server's internal rules.

所以空的 Cert Authorities 只是意味着客户端可以自由地向服务器发送任何证书,这可能会或可能不会被服务器的内部规则接受。

回答by Sam

In my case, the problem turned out to be that I was passing in nullas the password when loading my key store:

在我的情况下,问题原来是我null在加载我的密钥库时作为密码传入:

KeyStore keyStore = KeyStore.getInstance("PKCS12")
InputStream inputStream = new FileInputStream('/path/to/mykeystore.p12')

try {
    keyStore.load(inputStream, null); // <-- PROBLEM HERE!
}
finally {
    inputStream.close();
}

This didn't produce any error messages, but it silently failed to load the client key & certificate.

这没有产生任何错误消息,但它静默地无法加载客户端密钥和证书

The solution was to pass in the password:

解决方案是传入密码:

keyStore.load(inputStream as InputStream, 'mypassword'.toCharArray());