警告:未找到合适的证书 - 继续进行而不进行客户端身份验证。

16

团队,当我尝试使用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>

我的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;
}

}

我正在准备一个jar文件,并从UNIX机器上进行测试。
使用以下命令: java -Djavax.net.debug=ssl -cp snSSLclientTrustWithStoreCCC.jar cassandra.cass.ClientCustomSSL
我遵循了此帖子: 为什么Java在SSL握手期间不发送客户端证书? 并完成了Bruno提到的所有步骤。
我不确定我漏掉了什么。任何帮助将不胜感激。

1
各位,我怀疑 SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(clientKeyStore, "Hello1".toCharArray()).loadTrustMaterial(clientTrustStore,(TrustStrategy) new TrustSelfSignedStrategy()).build(); CloseableHttpClient httpclient = HttpClients.custom().setSSLContext(sslContext).build(); 没有添加来自 ClientTrustStore 的所有证书。有人遇到过这样的问题吗? - P.K
我前一天也遇到了同样的情况,我的解决方法是:调试并观察这些类:ClientHandshaker.serverHelloDone(),你会找到原因的!祝好运! - 邱鸿霖
我不明白邱鸿霖的建议,但我也遇到了同样的问题。(Java 7,TLS 1.2) - Sridhar Sarnobat
@P.K 你找到解决方案了吗? - Bernie Lenz
@BernieLenz 你找到解决方案了吗? - msbomrel
4个回答

13
  1. 客户端无法在其密钥库中找到由CertificateRequest消息中提到的任何签名者直接或间接签署的证书。
  2. 造成这种情况的原因是服务器在该消息中没有指定任何可信的签名者。
  3. 进而意味着服务器的信任库为空。

1
这实际上是TLS 1.0规范和TLS 1.1/1.2之间的一个区别。特别地,在TLS 1.1的第7.4.4节(证书请求)中添加了以下内容:
如果certificate_authorities列表为空,则客户端可以发送任何适当的ClientCertificateType证书,除非有相反的外部安排。
因此,空的证书颁发机构意味着客户端可以自由向服务器发送任何证书,这些证书可能会或可能不会被服务器的内部规则接受。

1
在我的情况下,问题是我在加载密钥库时将null作为密码传递进去了。
KeyStore keyStore = KeyStore.getInstance("PKCS12")
InputStream inputStream = new FileInputStream('/path/to/mykeystore.p12')

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

这段代码没有出现任何错误信息,但是它悄无声息地未能加载客户端密钥和证书
解决方法是传递密码:
keyStore.load(inputStream as InputStream, 'mypassword'.toCharArray());

如果pkcs12文件没有设置密码,则甚至需要添加一个空的byte[]。 - Vazul

1

我遇到了类似的问题。

服务器已发送“ServerHelloDone”消息
警告:未找到合适的证书 - 继续进行客户端身份验证
证书链:

对我来说,问题在于我错误地创建了密钥库:

keytool -importcert -keystore keystore.jks -alias client-cert -file client-cert.pem  -storepass password

我帮助的是:
openssl pkcs12 -export -chain -in client-cert.pem  -inkey client-key.pem  -out keystore.p12 -name client-cert -CAfile ca-cert.pem
keytool -importkeystore -destkeystore keystore.jks -srckeystore keystore.p12 -alias client-cert

我在这里找到了解决方案: https://blogs.oracle.com/jtc/installing-trusted-certificates-into-a-java-keystore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接