首页 > 解决方案 > 如果套接字握手中的客户端证书中有两个有效证书,则在 SSL 连接中使用哪个证书

问题描述

我的密钥库中已经有一个有效的证书,并且与服务器的握手过程正在运行。当在同一个密钥库中添加另一个具有不同 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();

标签: socketssslclient-certificatessslsocketfactory

解决方案


类似当有很多时,使用来自 keystore 和 truststore 的哪个密钥和证书?为服务器。

对于 SunX509 KeyManagerFactory:

  • 在初始化时,它创建一个 HashMap,其中包含来自密钥库的所有私钥条目,由别名键控;

  • 握手调用chooseClientAlias,对于服务器指定/请求的每个 <=1.2 certificate_type 或 1.3 sigalg(在代码中称为 keyType)按HashIterator顺序检查每个 HashMap 条目(由从别名的哈希码)查看叶子证书是否具有该密钥类型,并且链中的任何证书都由服务器指定的 CA 之一颁发,除非服务器将 CA 列表留空,在这种情况下,这部分检查将被跳过.

如果您选择了错误的证书和密钥,请检查服务器是否在其 CertificateRequest 消息中指定了正确的 CA 列表。您可以通过运行 sysprop 在 Java 客户端执行此操作javax.net.debug=ssl:handshake,或者在 1.3 中使用网络级工具(如 wireshark 或 tcpdump)除外。


推荐阅读