SSLSocket

Posted RookieSh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSLSocket相关的知识,希望对你有一定的参考价值。

SSLSocket定义

SSLSocket扩展Socket并提供使用SSL或TLS协议的安全套接字。它也是基于正常的流套接字,但是在网络传输协议(如TCP)上添加了安全保护层。

SSLSocket相关类

功能描述
SSLContext 该类的实例表示安全套接字协议的实现,是SSLSocketFactory、SSLServerSocketFactory和SSLEngine的工厂
SSLSocket 扩展自Socket
SSLServerSocket 扩展自ServerSocket
SSLSocketFactory 抽象类,扩展自SocketFactory,是SSLSocket的工厂
SSLServerSocketFactory 抽象类,扩展自ServerSocketFactory,是SSLServerSocket的工厂
KeysStore 密钥和证书的存储设施
KeyManager 接口,Java Secure Socket Extension密钥管理器
TrustManger 接口,信任管理器
X509TrustedManager TrustManger的子接口,管理X509证书,验证远程安全套接字

SSLServerSocket实现

SSLServerSocket需要证书进行安全全验证

使用keytool工具生成一个名称为seckey证书

 
   
   
 
  1. $ keytool -genkey -keystore seckey -keyalg rsa -alias SSL

服务端编码

 
   
   
 
  1. package cn.sh.sslsocket.server;

  2. import javax.net.ssl.*;

  3. import java.io.*;

  4. import java.net.Socket;

  5. import java.security.*;

  6. import java.security.cert.CertificateException;

  7. import java.security.cert.X509Certificate;

  8. /**

  9. * @author sh

  10. */

  11. public class SSLSocketServer {

  12.    public static void main(String[] args) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {

  13.        //准备KeyStore相关信息

  14.        String keyName = "SSL";

  15.        String keyStoreName = "/Users/sh/workspace/netty-demo/src/cn/sh/sslsocket/seckey";

  16.        char[] keyStorePwd = "123456".toCharArray();

  17.        char[] keyPwd = "1234567890".toCharArray();

  18.        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

  19.        //装载生成的seckey

  20.        try(InputStream in = new FileInputStream(new File(keyStoreName))) {

  21.            keyStore.load(in, keyStorePwd);

  22.        }

  23.        //初始化KeyManagerFactory

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

  25.        kmf.init(keyStore, keyPwd);

  26.        //初始化SSLContext

  27.        SSLContext context = SSLContext.getInstance(keyName);

  28.        context.init(kmf.getKeyManagers(), new TrustManager[]{getX509TrustManger()}, new SecureRandom());

  29.        //监听和接受客户端连接

  30.        SSLServerSocketFactory factory = context.getServerSocketFactory();

  31.        SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(10002);

  32.        System.out.println("服务器端已启动!!!");

  33.        //等待客户端连接

  34.        Socket client = serverSocket.accept();

  35.        //准备输出流,用于向客户端发送信息

  36.        OutputStream output = client.getOutputStream();

  37.        //获取输入流,用于读取客户端发送的信息

  38.        InputStream in = client.getInputStream();

  39.        byte[] buf = new byte[1024];

  40.        int len;

  41.        if ((len = in.read(buf)) != -1) {

  42.            output.write(buf, 0, len);

  43.        }

  44.        //冲刷数据

  45.        output.flush();

  46.        //关闭输入输出流

  47.        output.close();

  48.        in.close();

  49.        serverSocket.close();

  50.    }

  51.    public static X509TrustManager getX509TrustManger() {

  52.        return new X509TrustManager() {

  53.            @Override

  54.            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

  55.            }

  56.            @Override

  57.            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

  58.            }

  59.            @Override

  60.            public X509Certificate[] getAcceptedIssuers() {

  61.                return new X509Certificate[0];

  62.            }

  63.        };

  64.    }

  65. }

客户端实现

普通Socket连接服务器

实现

 
   
   
 
  1. package cn.sh.sslsocket.client;

  2. import java.io.IOException;

  3. import java.io.InputStream;

  4. import java.io.OutputStream;

  5. import java.net.Socket;

  6. /**

  7. * @author sh

  8. */

  9. public class SocketClient {

  10.    public static void main(String[] args) throws IOException {

  11.        Socket socket = new Socket("localhost", 10002);

  12.        OutputStream output = socket.getOutputStream();

  13.        InputStream input = socket.getInputStream();

  14.        output.write("I am SocketClient".getBytes());

  15.        output.flush();

  16.        byte[] buf = new byte[1024];

  17.        int len;

  18.        StringBuilder builder = new StringBuilder();

  19.        while ((len = input.read(buf)) != -1) {

  20.            builder.append(new String(buf, 0, len));

  21.        }

  22.        System.out.println("client received:" + builder.toString());

  23.    }

  24. }

运行结果

服务器结果如下图

服务端会抛出异常javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

客户端结果如下图

SSLSocket

客户端接收到乱码

使用SSLSocket,不使用证书

编码实现

 
   
   
 
  1. package cn.sh.sslsocket.client;

  2. import javax.net.ssl.SSLSocket;

  3. import javax.net.ssl.SSLSocketFactory;

  4. import java.io.IOException;

  5. import java.io.InputStream;

  6. import java.io.OutputStream;

  7. /**

  8. * @author sh

  9. */

  10. public class NoUseKeySSLSocketClient {

  11.    public static void main(String[] args) throws IOException {

  12.        SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();

  13.        SSLSocket sslSocket = (SSLSocket) factory.createSocket("localhost", 10002);

  14.        OutputStream output = sslSocket.getOutputStream();

  15.        InputStream input = sslSocket.getInputStream();

  16.        output.write("I am NoUseKeySSLSocketClient".getBytes());

  17.        output.flush();

  18.        byte[] buf = new byte[1024];

  19.        int len;

  20.        StringBuilder builder = new StringBuilder();

  21.        while ((len = input.read(buf)) != -1) {

  22.            builder.append(new String(buf, 0, len));

  23.        }

  24.        System.out.println("client received:" + builder.toString());

  25.    }

  26. }

运行结果

服务器结果如下图

SSLSocket

服务端会抛出异常javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown

客户端结果如下图

SSLSocket

客户端会抛出异常sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

使用SSLSocket,并且使用证书

编码实现

 
   
   
 
  1. package cn.sh.sslsocket.client;

  2. import cn.sh.sslsocket.server.SSLSocketServer;

  3. import javax.net.ssl.SSLContext;

  4. import javax.net.ssl.SSLSocket;

  5. import javax.net.ssl.SSLSocketFactory;

  6. import javax.net.ssl.TrustManager;

  7. import java.io.IOException;

  8. import java.io.InputStream;

  9. import java.io.OutputStream;

  10. import java.net.Socket;

  11. import java.security.KeyManagementException;

  12. import java.security.NoSuchAlgorithmException;

  13. import java.security.SecureRandom;

  14. /**

  15. * @author sh

  16. */

  17. public class SSLSocketClient {

  18.    public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException, IOException {

  19.        SSLContext context = SSLContext.getInstance("SSL");

  20.        context.init(null, new TrustManager[]{SSLSocketServer.getX509TrustManger()}, new SecureRandom());

  21.        SSLSocketFactory factory = context.getSocketFactory();

  22.        SSLSocket sslSocket = (SSLSocket) factory.createSocket("localhost", 10002);

  23.        OutputStream output = sslSocket.getOutputStream();

  24.        InputStream input = sslSocket.getInputStream();

  25.        output.write("I am SSLSocketClient".getBytes());

  26.        output.flush();

  27.        byte[] buf = new byte[1024];

  28.        int len;

  29.        StringBuilder builder = new StringBuilder();

  30.        while ((len = input.read(buf)) != -1) {

  31.            builder.append(new String(buf, 0, len));

  32.        }

  33.        output.close();

  34.        System.out.println("client received:" + builder.toString());

  35.    }

  36. }

运行结果

服务器结果如下图

客户端结果如下图

代码地址

本文章的代码在cn.sh.sslsocket包中!


以上是关于SSLSocket的主要内容,如果未能解决你的问题,请参考以下文章

使用C#实现SSLSocket加密通讯

OKHTTP - SSLSocket duplex close failed

OKHTTP - SSLSocket duplex close failed

SSLSocket

Https 代理 sslsocket

尝试发送到 SSLServerSocket 时出现 SSLSocket 异常握手错误