开发者

一文详解如何通过Java实现SSL交互功能

开发者 https://www.devze.com 2023-04-27 10:47 出处:网络 作者: 上官冰
目录创建证书编写 SSL Server编写 SSL Client通用编码测试创建证书 因为要产生 key 信任库,要求的密码至少的 6位数,所以密码设为 123456
目录
  • 创建证书
    • 编写 SSL Server
    • 编写 SSL Client
    • 通用编码
  • 测试

    创建证书

    因为要产生 key 信任库,要求的密码至少的 6位数,所以密码设为 123456

    • 首先 生成 根密钥和根证书
    • 然后 生成 客户端密钥 和 客户端证书,使用根证书对应客户端证书签名,将根证书和签名客户端证书添加到密钥库中
    • 最后 同上生成 服务端签名证书,并将根证书和服务端证书添加到 密钥库中。

    对应的脚本如下所示:

    #!/bin/bash
    # 加个前缀
    PFX='file'
    # Password 这里只能使用单引号
    PASS='123456'
    echo "---- 产生根相关文件 ----"
    echo "创建自签名的根密钥"
    openssl genrsa -out ${PFX}.rootkey.pem 2048
    echo "生成根证书"
    openssl req -x509 -new -key ${PFX}.rootkey.pem -out ${PFX}.root.crt -subj "/C=CN/ST=GD/L=GZ/O=pythonRootCA/OU=RootCA/CN=RootCA"
    echo "----- 产生客户端相关文件 -----"
    echo "生成客户端密钥"
    openssl genrsa -out ${PFX}.clientkey.pem 2048
    echo "生成客户端证书请求文件,使用根证书进行签发"
    openssl req -new -key ${PFX}.clientkey.pem -out ${PFX}.client.csr -subj "/C=CN/ST=GD/L=GZ/O=BMW/OU=Vehicle/CN=Vehicle1"
    echo "用根证书来签发客户端请求文件,生成客户端证书client.crt"
    openssl x509 -req -in ${PFX}.client.csr -CA ${PFX}.root.crt -CAkey ${PFX}.rootkey.pem -CAcreateserial -days 3650 -out ${PFX}.client.crt
    echo "打包客户端资料为pkcs12格开发者_开发教程式(client.pkcs12)"
    openssl pkcs12 -export -in ${PFX}.client.crt -inkey clientkey.pem -out ${PFX}.client.pkcs12 -passin "pass:$PASS" -passout "pass:$PASS"
    echo "生成信任客户端的keystore,把根证书以及需要信任的客户端的证书添加到这个keystore"
    keytool -importcert -alias ca -file ${PFX}.root.crt -keystore ${PFX}.clienttrust.jks -storepass "$PASS" <<EOF
    是
    EOF
    keytool -importcert -alias clientcert -file ${PFX}.client.crt -keystore ${PFX}.clienttrust.jks -storepass "$PASS"
    echo "--------产生服务端相关文件----"
    echo "生成服务器端的密匙"
    openssl genrsa -out ${PFX}.serverkey.pem 2048
    echo "生成服务器端证书的请求文件。请求根证书来签发"
    openssl req -new -key ${PFX}.serverkey.pem -out ${PFX}.server.csr -subj "/C=CN/ST=GD/L=GZ/O=BMW/OU=IT/CN=Broker"
    echo "用根证书来签发服务器端请求文件,生成服务器端证书server.crt"
    openssl x509 -req -in ${PFX}.server.csr -CA ${PFX}.root.crt -CAkey ${PFX}.rootkey.pem -CAcreateserial -days 3650 -out ${PFX}.server.crt
    echo "打包服务器端资料为pkcs12格式(server.pkcs12 )"
    openssl pkcs12 -export -in ${PFX}.server.crt -inkey ${PFX}.serverkey.pem -out ${PFX}.server.pkcs12 -passin "pass:$PASS" -passout "pass:$PASS"
    echo "生成信任服务器端的keystore,把根证书以及需要信任的服务端的证书添加到这个keystore"
    keytool -importcert -alias ca -file ${PFX}.root.crt -keystore ${PFX}.servertrust.jks -storepass "$PASS" <<EOF
    是
    EOF
    keytool -importcert -alias servercert -file ${PFX}.server.crt -keystore ${PFX}.servertrust.jks -storepass "$PASS"

    生成的文件目录,如下图所示:

    一文详解如何通过Java实现SSL交互功能

    #编码

    编写 SSL Server

    import Javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLServerSocket;
    import java.net.Socket;
    
    public class SSLServer {
        private SSLServerSocket sslServerSocket;
    
        public static void main(String[] args) throws Exception {
            SSLServer server = new SSLServer();
            server.initTestServer();
            server.process();
        }
    
        private SSLServerSocket initTestServer() throws Exception {
        // ssl-cert 放在 测试 resources 目录下
            String certDic = SSLServer.class.getClassLoader().getResource("ssl-cert").getPath();
            sslServerSocket = initSocket(certDpythonic + "/file.server.pkcs12",
                    certDic + "/file.clienttrust.jks",
                    "123456");
        // 如果为 false 表示单向认证,否则为双向认证
            sslServerSocket.setNeedClientAuth(false);
            System.out.println("Server test initialted!");
            return sslServerSocket;
        }
    
        private SSLServerSocket initSocket(String keyPath, String trustPath, String password) throws Exception {
            SSLContext context = SSLContext.getInstance("TLSv1.2");
            char[] keystorePass = password.toCharArray();
            context.init(SSLUtils.creatKey(keyPath, keystorePass).getKeyManagers(),
                    SSLUtils.creatTrustJks(trustPath, keystorePass).getTrustManagers(),
                    null);
            return (SSLServerSocket) context.getServerSocketFactory().createServerSocket(9999);
        }
    
    //服务端回复客户端
        private void process() throws Exception {
            String bye = "Hello, I am Server!";
            while (true) {
                Socket socket = sslServerSocket.accept();
                System.out.println("Received: " + SSLUtils.read(socket));
                SSLUtils.write(bye, socket);
            }
        }
    }

    编写 SSL Client

    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.TrustManagerFactory;
    
    public class SSLClient {
        private SSLSocket sslSocket;
    
        public static void main(String[] args) throws Exception {
            SSLClient client = new SSLClient();
            client.init();
            client.process();
        }
    
        privjavascriptate void init() throws Exception {
         // ssl-cert 放在 测试 resources 目录下
            String certDic = this.getClass().getClassLoader().getResource("ssl-cert").getPath();
            initSocket(certDic + "/file.server.pkcs12", certDic + "/file.servertrust.jks", "123456");
            System.out.println("Client initiated.");
        }
    
        private void initSocket(String keystorePath, String trustStorePath, String password) throws Exception {
            char[] keystorePass = password.toCharArray();
    
            KeyManager[] keyManagers = null;
            KeyManagerFactory keyManagerFactory = SSLUtils.creatKey(keystorePath, keystorePass);
            if (keyManagerFactory != null) {
                keyManagers = keyManagerFactory.getKeyManagers();
            }
    
            TrustManager[] trustManagers = null;
            TrustManagerFactory trustManagerFactory = SSLUtils.creatTrustJks(trustStorePath, keystorePass);
            if (trustManagerFactory != null) {
                trustManagers = trustManagerFactory.getTrustManagers();
            }
    
            SSLContext context = SSLContext.getInstance("TLSv1.2");
            context.init(keyManagers, trustManagers, null);
    
            String host = "127.0.0.1";
            sslSocket = (SSLSocket) context.getSocketFactory().createSocket(host, 9999);
        }
    
        public void process() throws Exception {
            String hello = "Client Hello";
            SSLUtils.write(hello, sslSocket);
            System.out.println(SSLUtils.read(sslSocket));
        }
    
    }

    通用编码

    import org.apache.commons.lang3.StringUtils;
    
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.TrustManagerFactojavascriptry;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    import java.security.KeyStore;
    
    public class SSLUtils {
    
        public static void write(String message, Socket sslSocket) throws Exception {
            OutputStream out = sslSocket.getOutputStream();
            byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
            out.write(messageBytes, 0, messageBytes.length);
            out.flush();
        }
    
        public static String read(Socket sslSocket) throws Exception {
            InputStream in = sslSocket.getInputStream();
            byte[] buffer = new byte[50];
            in.read(buffer);
            return new String(buffer);
        }
    
        public static KeyManagerFactory creatKey(String keystorePath, char[] keystorePass) throws Exception {
            if (StringUtils.isEmpty(keystorePath)) {
                return null;
            }
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
            kmf.init(loadKeyStore(keystorePath, keystorePass), keystorePass);
            return kmf;
        }
    
        public static TrustManagerFactory creatTrustJks(String trustClientKeystorePath, char[] keystorePass) throws Exception {
            if (StringUtils.isEmpty(trustClientKeystorePath)) {
                return null;
            }
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");
            tmf.init(loadKeyStore(trustClientKeystorePath, keystorePass));
            returnjavascript tmf;
        }
    
        private static KeyStore loadKeyStore(String keystorePath, char[] keystorePass) throws Exception {
            KeyStore serverKeyStore = KeyStore.getInstance(StringUtils.substringAfterLast(keystorePath, "."));
            serverKeyStore.load(new FileInputStream(keystorePath), keystorePass);
            return serverKeyStore;
        }
    }

    测试

    启动 SSLServer 和 SSLClient 可以得到的结果如下所示:

    一文详解如何通过Java实现SSL交互功能

    一文详解如何通过Java实现SSL交互功能

    使用 wireshark 抓包如下所示:

    一文详解如何通过Java实现SSL交互功能

    这就是对应的 SSL 连接

    到此这篇关于一文详解如何通过Java实现SSL交互功能的文章就介绍到这了,更多相关Java实现SSL交互内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号