美文网首页
Keytool工具生成SSL证书以及在Java中实现SSL

Keytool工具生成SSL证书以及在Java中实现SSL

作者: 胡浩8880 | 来源:发表于2020-04-09 08:58 被阅读0次

    1.Keytool工具生成SSL证书

        keytool即JDK中自带的证书生成工具,常见的还有openssl工具。

         1.生成一个自签名的CA证书,为了给Client和Server的证书签名。

          命令:keytool -genkeypair (-keyalg RSA) -alias TEST_ROOT -keystore test_root.jks

          解释:生成一对密钥,存储在test_root.jks中,条目别名为TEST_ROOT。输入该命令后会提示输入个人信息。当命令完成后,会在test_root.jks中生成一个自签名的证书。当然,私钥也保存在该文件中。这里密钥库的密码和密钥密码都设置成123456

    如果不加keyalg 的,默认是DSA算法生成

    2.为server生成一对密钥(也就是一个自签名的证书)

     命令:keytool -genkeypair -alias TEST_SERVER -keystore test_server.jks

    解释:生成一对密钥,存储在test_server.jks中,条目别名TEST_SERVER。

    3.生成一个签名请求文件(即请求CA给server自签名的证书签名)

    命令:keytool -certreq -file test_server.csr -alias TEST_SERVER -keystore test_server.jks

    解释:为存储在test_server.jks中的别名TEST_SERVER生成一个证书请求文件test_server.csr。

    4.ca为server的证书签名

    命令:keytool -gencert -infile test_server.csr -outfile test_server.cer -alias TEST_ROOT -keystore TEST_ROOT.jks

    解释:利用TEST_ROOT.jks中条目别名为TEST_ROOT的私钥为test_server.csr证书请求对应的证书签名,并将签名后的证书保存在test_server.cer中。

    5.导出ca证书

    命令:keytool -exportcert -alias TEST_ROOT -file test_root.cer -keystore test_root.jks

    解释:将test_root.jks中条目别名为TEST_ROOT的证书导出到test_root.cer中。

    6.将ca证书导入到test_server.jks中。

    命令:keytool -importcert -alias TEST_ROOT -file test_root.cer -keystore TEST_SERVER.jks

    解释:将test_root.cer证书文件导入TEST_SERVER.jks中,条目别名为TEST_ROOT。这里需要注意,在TEST_SERVER.jks中之前应不存在条目别名为TEST_ROOT,这样才会以信任证书的方式导入。

    7.更新server证书

    命令:keytool -importcert -alias TEST_SERVER -file test_server.cer -keystore TEST_SERVER.jks

    解释:将test_server.cer导入到TEST_SERVER.jks中。因为在生成server密钥对的时候,在test_server.jks中已经存在自签的证书,条目别名为TEST_SERVER。而该命令保存的别名还是TEST_SERVER。意思上就是更新证书。将之前自签名的证书替换为ca签名过的证书。

    8.查看test_server.jks中server的证书和ca证书。

    命令:keytool -list -v -keystore test_server.jks

    从条目test_server中可以看出,该证书被ca签名后,ca的证书也保存在该条目中,形成证书链。

    对于Client的证书生成参考2-7步。在该过程中生成的文件如下:

    2.在Java中实现SSL通信

      Java中主要通过JSSE(Java Secure Socket Extension)来完成安全套接字的编写。其中主要涉及了一些类,例如Keystore、KeyManagerFactory、TrustManagerFactory、SSLContext等。它们的关系如下图(图的来源于文章结尾的链接中)

    编程的步骤如下:

    1.利用keystore类完成客户端和服务器的证书库和信任库的加载

    2.利用加载的证书库和信任库,完成KeyManagerFactory和TrustManagerFactory的初始化。

    3.生成SSLContext对象,并用keyManagerFactory和TrustManagerFactory生成的keyManager和TrustManager完成初始化。

    4.利用SSLContext对象,生成对应的SSLSocket和SSLServerSocket。

    需要的文件

    1.test_root.jks(存储了ca证书,因为client和server的证书都是被ca签名的,所以ca证书被信任,则client和server的证书都会被信任)。

    2.test_client.jks(存储了client的证书)。

    3.test_server.jks(存储了server的证书)。

    客户端代码

    public class Client {

        public static void main(String[] args) throws Exception {

            String clientKeyStoreFile = "d:\\keystore\\test_client.jks";

            String clientKeyStorePwd = "123456";

            String clientKeyPwd = "123456";

            String clientTrustKeyStoreFile = "d:\\keystore\\test_root.jks";

            String clientTrustKeyStorePwd = "123456";

            //生成client的keystore对象

            KeyStore clientKeyStore = KeyStore.getInstance("JKS");

            clientKeyStore.load(new FileInputStream(clientKeyStoreFile), clientKeyStorePwd.toCharArray());

            //生成信任证书的keystore对象

            KeyStore clientTrustKeyStore = KeyStore.getInstance("JKS");

            clientTrustKeyStore.load(new FileInputStream(clientTrustKeyStoreFile), clientTrustKeyStorePwd.toCharArray());

            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

            kmf.init(clientKeyStore, clientKeyPwd.toCharArray());

            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

            tmf.init(clientTrustKeyStore);

            SSLContext sslContext = SSLContext.getInstance("TLSv1");

            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

            SSLSocketFactory socketFactory = sslContext.getSocketFactory();

            Socket socket = socketFactory.createSocket("localhost", Server.SERVER_PORT);

            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            send("hello", out);

            send("exit", out);

            receive(in);

            socket.close();

        }

        public static void send(String s, PrintWriter out) throws IOException {

            System.out.println("Sending: " + s);   

            out.println(s);

        }

        public static void receive(BufferedReader in) throws IOException {

            String s;

            while ((s = in.readLine()) != null) {

                System.out.println("Reveived: " + s);

            }

        }

    }

    服务器代码

    public class Server implements Runnable,HandshakeCompletedListener {

        public static final int SERVER_PORT = 11123;

        private final Socket s;

        private String peerCerName;

        public Server(Socket s) {

          this.s = s;

        }

        public static void main(String[] args) throws Exception {

            String serverKeyStoreFile = "d:\\keystore\\test_server.jks";

            String serverKeyStorePwd = "123456";

            String ServerKeyPwd = "123456";

            String serverTrustKeyStoreFile = "d:\\keystore\\test_root.jks";

            String serverTrustKeyStorePwd = "123456";

            /*

            * 加载server.keystore

            *

            */

            KeyStore serverKeyStore = KeyStore.getInstance("JKS");

            serverKeyStore.load(new FileInputStream(serverKeyStoreFile), serverKeyStorePwd.toCharArray());

            /*

            * 加载servertrust.keystore

            *

            */

            KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS");

            serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray());

            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

            kmf.init(serverKeyStore, ServerKeyPwd.toCharArray());

            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

            tmf.init(serverTrustKeyStore);

            SSLContext sslContext = SSLContext.getInstance("TLSv1");

            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

            SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();

            SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(SERVER_PORT);

            //设置双向验证

            sslServerSocket.setNeedClientAuth(true);

            while (true) {

                SSLSocket s = (SSLSocket)sslServerSocket.accept();

                Server cs = new Server(s);

                s.addHandshakeCompletedListener(cs);

                new Thread(cs).start();

            }

        }

        @Override

        public void run() {

            try {

                BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));

                PrintWriter writer = new PrintWriter(s.getOutputStream(), true);

                writer.println("Welcome~, enter exit to leave.");

                String message;

                while ((message = reader.readLine()) != null && !message.trim().equalsIgnoreCase("exit")) {

                    writer.println("Echo: " + message);

                }

                writer.println("Bye~, " + peerCerName);

            } catch (Exception e) {

                e.printStackTrace();

            } finally {

                try {

                    s.close();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }

        @Override

        public void handshakeCompleted(HandshakeCompletedEvent event) {

            try {

                X509Certificate cert = (X509Certificate) event.getPeerCertificates()[0];

                peerCerName = cert.getSubjectX500Principal().getName();

            } catch (SSLPeerUnverifiedException ex) {

                ex.printStackTrace();

            }

        }

    }

    运行结果:

    说明SSL握手成功建立。

    参考的文章:https://www.ibm.com/developerworks/cn/java/j-lo-socketkeytool/

    相关文章

      网友评论

          本文标题:Keytool工具生成SSL证书以及在Java中实现SSL

          本文链接:https://www.haomeiwen.com/subject/jwhqmhtx.html