简体   繁体   English

如果有多个匹配的证书,如何选择SSL客户端证书?

[英]How is the SSL client certificate chosen when there are multiple matching certificates?

It's not something that should happen by design, but for security concerns, i'm wondering how will the "right" certificate be sent to the server, assuming there are more than one certificates matching the requirement of being signed by a certain CA? 这不是设计应该发生的事情,但出于安全考虑,我想知道如何将“正确”的证书发送到服务器,假设有多个证书符合某个CA签名的要求?

I'm using a simple SSL JAVA example client, connecting to an Apache HTTPD. 我正在使用一个简单的SSL JAVA示例客户端,连接到Apache HTTPD。

I tried testing with 4 certificates, each time deleting the chosen one and noting who was chosen next. 我尝试使用4个证书进行测试,每次都删除所选的证书,并注意下一个选择了谁。 I couldn't find a reasonable logic (ie date, alias name etc.) other than maybe a lexicographic order of the "sha256" of the certificates. 除了证书的“sha256”的词典顺序之外,我找不到合理的逻辑(即日期,别名等)。 that seems unlikely to me... 这似乎不太可能......

The example client does something like 示例客户端执行类似的操作

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();  

And the Apache is configured with Apache配置了

SSLCACertificateFile rootCA.crt  
SSLVerifyClient require  

I couldn't find the relevant documentation to answer the question. 我找不到相关文件来回答这个问题。 I'm also wondering- is there any chance that the Apache will somehow forward more than one certificates chains? 我也想知道 - Apache是​​否有可能以某种方式转发多个证书链? (say with a misbehaving client sending something weird). (对于一个行为不端的客户发送一些奇怪的东西)。

Thanks! 谢谢!

A server that requires client authentication will send a list of acceptable certificate types, possibly along with a list of acceptable CAs. 需要客户端身份验证的服务器将发送可接受的证书类型列表,可能还包含可接受的CA列表。 By default, your Java client then applies the following algorithm: 默认情况下,您的Java客户端将应用以下算法:

  1. For each certificate type (RSA, DSA, EC) accepted by the server, find any public/private key pairs in the key store which have been generated with the specified algorithm 对于服务器接受的每种证书类型(RSA,DSA,EC),查找密钥库中使用指定算法生成的任何公钥/私钥对
  2. If the server sent a list of acceptable CAs, remove any key pair that doesn't contain any of the CAs in the list in its certificate chain 如果服务器发送了可接受的CA列表,请删除其证书链中列表中不包含任何CA的任何密钥对
  3. If there is at least one key pair remaining, select the private key corresponding to the first one; 如果剩余至少一个密钥对,则选择与第一个密钥对对应的私钥; otherwise go back to step 1 for the next key type. 否则返回步骤1以获取下一个键类型。

The client certificate choice algorithm isn't specified in RFC 5246 , but Java's simple default implementation seems reasonable, if subject to change in the future as noted by EJP. RFC 5246中未指定客户端证书选择算法,但Java的简单默认实现似乎是合理的,如果EJP指出将来可能会发生变化。 In particular, the 'first' one is pretty much random - credentials are currently stored in a Map , so it is going to depend on iteration order of the entry set. 特别是,“第一个”几乎是随机的 - 凭证当前存储在Map ,因此它将取决于条目集的迭代顺序。 Also, the KeyManager implementations are pluggable, and there is a 'NewSun' implementation available with OpenJDK that is activated by passing the security property ssl.KeyManagerFactory.algorithm=NewSunX509 . 此外, KeyManager实现是可插入的,并且OpenJDK提供了一个'NewSun'实现,它通过传递安全属性ssl.KeyManagerFactory.algorithm=NewSunX509 This second one will also take into account of your client certificates' keyUsage and extendedKeyUsage attributes, as well as the expiry dates. 第二个还将考虑您的客户端证书的keyUsage和extendedKeyUsage属性,以及到期日期。

If you need to guarantee the certificate sent from a list of possibilities and you find that the default behaviours aren't doing it for you, your best option is to manually create a single-entry keystore and use it to initialise an SSLContext , or write your own implemenation of X509KeyManager to do what you want in chooseClientAlias , like in the answers to this question or this question . 如果您需要保证从可能列表中发送的证书,并且您发现默认行为不是为您执行此操作,则最佳选择是手动创建单项密钥库并使用它来初始化SSLContext ,或者写入你自己的实行X509KeyManager做你想做的事, chooseClientAlias ,想在回答这个问题,还是这个问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM