验证码: 看不清楚,换一张 查询 注册会员,免验证
  • {{ basic.site_slogan }}
  • 打开微信扫一扫,
    您还可以在这里找到我们哟

    关注我们

怎么通过Java实现SSL交互功能

阅读:297 来源:乙速云 作者:代码code

怎么通过Java实现SSL交互功能

      创建证书

      因为要产生 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=RootCA/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" <服务器端的密匙"
      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" <

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

      怎么通过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(certDic + "/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();
          }
      
          private 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.TrustManagerFactory;
      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));
              return 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 连接

    分享到:
    *特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: hlamps#outlook.com (#换成@)。
    相关文章
    {{ v.title }}
    {{ v.description||(cleanHtml(v.content)).substr(0,100)+'···' }}
    你可能感兴趣
    推荐阅读 更多>