问题描述
我的密钥库中已经有一个有效的证书,并且与服务器的握手过程正在运行。当在同一个密钥库中添加另一个具有不同 CN 的证书并与服务器连接时,从服务器获取错误“访问被拒绝,端点无效”。我认为在与服务器连接时,当有两个有效的客户端证书使用证书(现有的一个和新导入的一个)时,第二个证书用于 ssl 连接。我想知道的是,如果密钥库中有一个以上的有效证书,则使用哪个。它与证书别名有关吗? 以下是套接字连接的代码片段。
try {
SSLSocketFactory factory = null;
try {
SSLContext ctx;
KeyManagerFactory kmf;
KeyStore ks;
char[] passphrase = "*****".tochararray();
ctx = SSLContext.getInstance("TLSv1.2");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("testkeys"),passphrase);
kmf.init(ks,passphrase);
ctx.init(kmf.getKeyManagers(),null,null);
factory = ctx.getSocketFactory();
} catch (Exception e) {
throw new IOException(e.getMessage());
}
SSLSocket socket = (SSLSocket)factory.createSocket(host,port);
String[] cipherSuites = socket.getSupportedCipherSuites();
socket.setEnabledCipherSuites( cipherSuites );
socket.setNeedClientAuth(false);
socket.startHandshake();
解决方法
服务器类似 Which key and certificate from keystore and truststore is used when there are many?。
对于 SunX509 KeyManagerFactory:
-
在初始化时,它创建一个 HashMap,其中包含来自密钥库的所有私钥条目,以别名为键;
-
handshake 调用
chooseClientAlias
,对于服务器指定/请求的每个 HashIterator 顺序中的每个 HashMap 条目(这由从别名的哈希码派生的值的可变数量的低位决定)以查看叶证书是否具有该密钥类型,并且链中的任何证书均由服务器指定的 CA 之一颁发,除非服务器将 CA 列表留空,在这种情况下,这部分检查将被跳过。
如果您选择了错误的证书和密钥,请检查服务器是否在其 CertificateRequest 消息中指定了正确的 CA 列表。您可以通过运行 sysprop javax.net.debug=ssl:handshake
在 Java 客户端执行此操作,或者在 1.3 中使用诸如wireshark 或 tcpdump 之类的网络级工具。