有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java当存在多个匹配证书时,如何选择SSL客户端证书?

这不是设计上应该发生的事情,但出于安全考虑,我想知道,假设有多个证书符合由某个CA签名的要求,那么“正确”的证书将如何发送到服务器

我正在使用一个简单的ssljava示例客户端,连接到apachehttpd

我试着用4个证书进行测试,每次删除选中的证书,并记下下下一个是谁。除了证书的“sha256”的字典顺序之外,我找不到合理的逻辑(例如日期、别名等)。这对我来说似乎不太可能

示例客户端执行如下操作

System.setProperty("javax.net.ssl.keyStore","device.p12");  
System.setProperty("javax.net.ssl.keyStorePassword","password");  
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");  
System.setProperty("javax.net.ssl.trustStore","truststore.jks");  
System.setProperty("javax.net.ssl.trustStorePassword","password");  
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();  
SSLSocket sslSock = (SSLSocket) factory.createSocket("87.69.60.100",443);  
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(sslSock.getOutputStream(), "UTF8"));  
wr.write("GET /lather HTTP/1.1\r\nhost: 87.69.60.100\r\n\r\n");  
wr.flush();  

Apache配置了

SSLCACertificateFile rootCA.crt  
SSLVerifyClient require  

我找不到相关的文档来回答这个问题。我还想知道,Apache是否有可能以某种方式转发多个证书链?(比如一个行为不端的客户发送了一些奇怪的东西)

谢谢


共 (1) 个答案

  1. # 1 楼答案

    需要客户端身份验证的服务器将发送可接受证书类型的列表,可能还会发送可接受CA的列表。默认情况下,Java客户端将应用以下算法:

    1. 对于服务器接受的每种证书类型(RSA、DSA、EC),请在密钥存储中查找使用指定算法生成的任何公钥/私钥对
    2. 如果服务器发送了可接受CA的列表,请删除其证书链列表中不包含任何CA的任何密钥对
    3. 如果剩余至少一个密钥对,则选择与第一个密钥对应的私钥;否则,请返回步骤1以获取下一个密钥类型

    客户机证书选择算法没有在RFC 5246中指定,但是Java的简单默认实现似乎是合理的,如果将来如EJP所述会发生变化的话。特别是,“第一个”几乎是随机的-凭证当前存储在Map中,因此它将取决于条目集的迭代顺序。此外,KeyManager实现是可插入的,OpenJDK提供了一个“NewSun”实现,它通过传递安全属性ssl.KeyManagerFactory.algorithm=NewSunX509激活。第二个还将考虑客户机证书的keyUsage和extendedKeyUsage属性,以及到期日期

    如果您需要保证从一系列可能性中发送的证书,并且您发现默认行为不适合您,那么最好的选择是手动创建一个单条目密钥库,并使用它初始化SSLContext,或者编写自己的X509KeyManager实现,以在chooseClientAlias中执行您想要的操作,就像对this questionthis question的回答一样