JAVA-SSL客户端-未使用密钥管理器

时间:2018-08-02 08:37:04

标签: java ssl certificate alias keystore

我实现了自定义密钥管理器,以便在需要ssl握手时选择使用哪个别名。 问题是尽管已正确实例化了自定义密钥管理器的所有方法,但都没有调用。

使用仅包含一个别名的密钥库,可以很好地进行通信并且代码可以正常工作,但是此处的目的是可以在运行时更改别名。

这是我实现的完整代码。感谢您的帮助。

package ssl;

import java.net.Socket;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLEngine;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509KeyManager;

public class AliasSelectorKeyManager extends X509ExtendedKeyManager {

    private X509KeyManager sourceKeyManager = null;
    private String alias;

    public AliasSelectorKeyManager(X509KeyManager keyManager, String alias) {
        this.sourceKeyManager = keyManager;
        this.alias = alias;
    }

    @Override
    public String chooseEngineClientAlias(String[] paramArrayOfString, Principal[] paramArrayOfPrincipal, SSLEngine paramSSLEngine) {

        return chooseClientAlias(paramArrayOfString, paramArrayOfPrincipal, null);
    }

    @Override
    public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
        boolean aliasFound = false;

        //Get all aliases from the key manager. If any matches with the managed alias,
        //then return it.
        //If the alias has not been found, return null (and let the API to handle it, 
        //causing the handshake to fail).

        for (int i = 0; i < keyType.length && !aliasFound; i++) {
            String[] validAliases = sourceKeyManager.getClientAliases(keyType[i], issuers);
            if (validAliases != null) {
                for (int j = 0; j < validAliases.length && !aliasFound; j++) {

                    if (validAliases[j].equals(alias)) {

                        aliasFound = true;
                    }
                }
            }
        }

        if (aliasFound) {
            return alias;
        } else {

            return null;
        }
    }
}

所有这些操作只是覆盖了调用特定sourceKeyManager实现的每个方法。自定义包含两种方法:

  • chooseEngineClientAlias ;
  • 选择ClientAlias

这是我的SSL客户端主体:

package ssl;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;

public class SSLClientV2 {

    public static void main(String[] args) {

        String keyStoreType = "PKCS12";
        String keyManagementAlgorithm = "SunX509";
        String keyStorePassword = "password";
        String keyStoreFileName = "C:/keystore.p12";

        String protocolVersion = "TLSv1.2";

        System.out.println("Key store File name.......: " + keyStoreFileName);
        System.out.println("Key store type............: " + keyStoreType);
        System.out.println("Key store Password........: " + keyStorePassword);
        System.out.println("SSL Protocol..............: " + protocolVersion);
        System.out.println("Key Management Algorithm..: " + keyManagementAlgorithm);

        System.out.println(System.lineSeparator());

        KeyStore keyStore = null;
        KeyManagerFactory keyManagerFactory = null;
        SSLContext sslContext = null;

        try (FileInputStream keyStoreFile = new FileInputStream(keyStoreFileName)) {

            System.out.println("Loading keystore...");
            keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(keyStoreFile, keyStorePassword.toCharArray());

            System.out.println("Keystore loaded successfully.");
        } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {

            System.out.println("ERROR: Could not load keystore.");
            e.printStackTrace();
        }

        System.out.print(System.lineSeparator());

        if (keyStore != null) {

            try {
                System.out.println("Initializing Key Manager Factory...");

                keyManagerFactory = KeyManagerFactory.getInstance(keyManagementAlgorithm);
                keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());

                System.out.println("Key Manager Factory initialized successfully.");
            } catch (NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException e) {

                System.out.println("ERROR: Could not initialize Key Manager Factory.");
                e.printStackTrace();
            }
        }

        System.out.print(System.lineSeparator());

        if (keyManagerFactory != null) {

            try {
                System.out.println("Initializing SSL Context...");

                KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
                TrustManager[] trustManagers = new TrustManager[] {

                        new X509TrustManager() {

                            @Override
                            public X509Certificate[] getAcceptedIssuers() {

                                return null;
                            }

                            @Override
                            public void checkServerTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {

                            }

                            @Override
                            public void checkClientTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {

                            }
                        }
                };

                for (int i = 0; i < keyManagers.length; i++) {
                    if (keyManagers[i] instanceof X509KeyManager) {

                        keyManagers[i] = new AliasSelectorKeyManager((X509KeyManager) keyManagers[i], "my.custom.alias");
                        System.out.println("Custom Key Manager loaded (#" + (i + 1) + ", class: " + keyManagers[i].getClass().getName() + ")");
                    }
                }

                sslContext = SSLContext.getInstance(protocolVersion);
                SecureRandom secureRandom = new SecureRandom();

                secureRandom.nextInt();
                sslContext.init(keyManagers, trustManagers, secureRandom);

                System.out.println("SSL Context initialized successfully.");
            } catch (KeyManagementException | NoSuchAlgorithmException e) {

                System.out.println("ERROR: Could not initialize SSL Context.");
                e.printStackTrace();
            }
        }

        System.out.print(System.lineSeparator());
        if (sslContext != null) {

            try (SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket("192.168.10.10", 1443)) {

                System.out.println("Communication initialized, starting handshake...");
                socket.startHandshake();

                System.out.println("Handshake completed successfully.");
                BufferedWriter w = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String m = null;

                System.out.print(System.lineSeparator());

                String content = "Hello World";
                System.out.println("Sending: " + content);

                w.write(content);
                w.flush();

                System.out.println("Message received: ");
                while ((m = r.readLine()) != null) {

                    System.out.println(m);
                }

                w.close();
                r.close();

            } catch (IOException e) {

                e.printStackTrace();
            }
        }
    }
}

2 个答案:

答案 0 :(得分:0)

也请重写此方法: X509KeyManager :: getClientAliases(String keyType,Principal []发行者)

答案 1 :(得分:0)

服务器端是否开启了 needClientAuth 标志?

https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html#setNeedClientAuth(boolean)

只有在标志打开时,服务器才会在握手期间询问客户端的身份验证。