什么是SSL/TLS

不使用SSL/TLS的网络通信,一般都是明文传输,网络传输内容在传输过程中很容易被窃听甚至篡改,非常不安全。SSL/TLS协议就是为了解决这些安全问题而设计的。SSL/TLS协议位于TCP/IP协议之上,各个应用层协议之下,使网络传输的内容通过加密算法加密,并且只有服务器和客户端可以加密解密,中间人即使抓到数据包也无法解密获取传输的内容,从而避免安全问题。例如广泛使用的HTTPS协议即是在TCP协议和HTTP协议之间加了一层SSL/TLS协议。

相关术语

在学习SSL/TLS协议之前,首先要了解一些相关概念:
- 对称加密:加密和解密都采用同一个密钥,常用的算法有DES、3DES、AES,相对于非对称加密算法更简单速度更快。
- 非对称加密:和对称加密算法不同,非对称加密算法会有两个密钥:公钥(可以公开的)和私钥(私有的),例如客户端如果使用公钥加密,那么即时其他人有公钥也无法解密,只能通过服务器私有的私钥解密。RSA算法即是典型的非对称加密算法。
- 数字证书:数字证书是一个包含公钥并且通过权威机构发行的一串数据,数字证书很多需要付费购买,也有免费的,另外也可以自己生成数字证书,本文中将会采用自签名的方式生成数字证书。

SSL/TLS流程

使用SSL/TLS协议的服务器和客户端开始通信之前,会先进行一个握手阶段:

  1. 客户端发出请求:这一步客户端会生成一个随机数传给服务器;
  2. 服务器回应:这一步服务器会返回给客户端一个服务器数字证书(证书中包含用于加密的公钥),另外服务器也会生成一个随机数给客户端;
  3. 客户端回应:这一步客户端首先会校验数字证书的合法性,然后会再生成一个随机数,这个随机数会使用第2步中的公钥采用非对称加密算法(例如RSA算法)进行加密后传给服务器,密文只能通过服务器的私钥来解密。
  4. 服务器最后回应:握手结束。

握手结束后,客户端和服务器都有上面握手阶段的三个随机数。客户端和服务器都通过这三个随机生成一个密钥,接下来所有的通信内容都使用这个密钥通过对称加密算法加密传输,服务器和客户端才开始进行安全的通信。

如果看到这里还是一脸懵逼,可以参考SSL/TLS协议运行机制的概述更深入地了解SSL/TLS流程,本文不再过多介绍。

生成私钥和证书

使用openssl来生成私钥和证书:

openssl req -x509 -newkey rsa:2048 -nodes -days 365 -keyout private.pem -out cert.crt

运行以上命令后,会在当前目录下生成一个私钥文件(private.pem)和一个证书文件(cert.crt)。

生成的私钥和证书Twisted、Netty可以直接使用,然而MINA对私钥文件的格式的要求,要将pem格式转换成der格式,实际上就是将文本文件私钥转成二进制文件私钥。openssl将private.pem转成private.der私钥文件:

openssl pkcs8 -topk8 -inform PEM -in private.pem -outform DER -nocrypt -out private.der

SSL/TLS服务器

接下来在http://xxgblog.com/2014/08/21/mina-netty-twisted-2/一文的基础上,加上SSL/TLS层。

MINA

MINA可以通过SslFilter来实现SSL/TLS,初始化SslFilter的代码比较繁琐:

public class MinaServer {public static void main(String[] args) throws Exception {String certPath = "/Users/wucao/Desktop/ssl/cert.crt";  // 证书String privateKeyPath = "/Users/wucao/Desktop/ssl/private.der";  // 私钥// 证书// https://docs.oracle.com/javase/7/docs/api/java/security/cert/X509Certificate.htmlInputStream inStream = null;Certificate certificate = null;try {inStream = new FileInputStream(certPath);CertificateFactory cf = CertificateFactory.getInstance("X.509");certificate = cf.generateCertificate(inStream);} finally {if (inStream != null) {inStream.close();}}// 私钥PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Files.readAllBytes(new File(privateKeyPath).toPath()));PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());ks.load(null, null);Certificate[] certificates = {certificate};ks.setKeyEntry("key", privateKey, "".toCharArray(), certificates);KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());kmf.init(ks, "".toCharArray());SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(kmf.getKeyManagers(), null, null);IoAcceptor acceptor = new NioSocketAcceptor();DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();chain.addLast("ssl", new SslFilter(sslContext));  // SslFilter需要放在最前面chain.addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"), "\r\n", "\r\n")));acceptor.setHandler(new TcpServerHandle());acceptor.bind(new InetSocketAddress(8080));}
}class TcpServerHandle extends IoHandlerAdapter {@Overridepublic void exceptionCaught(IoSession session, Throwable cause)throws Exception {cause.printStackTrace();}@Overridepublic void messageReceived(IoSession session, Object message)throws Exception {String line = (String) message;System.out.println("messageReceived:" + line);}@Overridepublic void sessionCreated(IoSession session) throws Exception {System.out.println("sessionCreated");}@Overridepublic void sessionClosed(IoSession session) throws Exception {System.out.println("sessionClosed");}
}

Netty

Netty通过添加一个SslHandler来实现SSL/TLS,相对MINA来说代码就比较简洁:

public class NettyServer {public static void main(String[] args) throws InterruptedException, SSLException {File certificate = new File("/Users/wucao/Desktop/ssl/cert.crt");  // 证书File privateKey = new File("/Users/wucao/Desktop/ssl/private.pem");  // 私钥final SslContext sslContext = SslContextBuilder.forServer(certificate, privateKey).build();EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch)throws Exception {ChannelPipeline pipeline = ch.pipeline();// SslHandler要放在最前面SslHandler sslHandler = sslContext.newHandler(ch.alloc());pipeline.addLast(sslHandler);pipeline.addLast(new LineBasedFrameDecoder(80));pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));pipeline.addLast(new TcpServerHandler());}});ChannelFuture f = b.bind(8080).sync();f.channel().closeFuture().sync();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}}class TcpServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {String line = (String) msg;System.out.println("channelRead:" + line);}@Overridepublic void channelActive(ChannelHandlerContext ctx) {System.out.println("channelActive");}@Overridepublic void channelInactive(ChannelHandlerContext ctx) {System.out.println("channelInactive");}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}
}

Twisted

Twisted实现SSL/TLS也是非常简单的,将reactor.listenTCP替换为reactor.listenSSL即可

# -*- coding:utf-8 –*-from twisted.protocols.basic import LineOnlyReceiver
from twisted.internet.protocol import Factory
from twisted.internet import reactor, sslsslContext = ssl.DefaultOpenSSLContextFactory('/Users/wucao/Desktop/ssl/private.pem',  # 私钥'/Users/wucao/Desktop/ssl/cert.crt',  # 公钥
)class TcpServerHandle(LineOnlyReceiver):def connectionMade(self):print 'connectionMade'def connectionLost(self, reason):print 'connectionLost'def lineReceived(self, data):print 'lineReceived:' + datafactory = Factory()
factory.protocol = TcpServerHandle
reactor.listenSSL(8080, factory, sslContext)
reactor.run()

SSL/TLS客户端

这里还是使用Java来写一个SSL/TLS客户端,用来测试以上三个服务器程序。需要注意的是,在上面SSL/TLS流程的介绍中,SSL/TLS握手阶段的第2步服务器会将证书传给客户端,第3步客户端会校验证书的合法性,所以下面的代码首先会让客户端信任openssl生成的证书,才能正确的完成SSL/TLS握手。

public class SSLClient {public static void main(String args[]) throws Exception {// 客户端信任改证书,将用于校验服务器传过来的证书的合法性String certPath = "/Users/wucao/Desktop/ssl/cert.crt";InputStream inStream = null;Certificate certificate = null;try {inStream = new FileInputStream(certPath);CertificateFactory cf = CertificateFactory.getInstance("X.509");certificate = cf.generateCertificate(inStream);} finally {if (inStream != null) {inStream.close();}}KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());ks.load(null, null);ks.setCertificateEntry("cert", certificate);TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");tmf.init(ks);SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, tmf.getTrustManagers(), null);SSLSocketFactory socketFactory = sslContext.getSocketFactory();Socket socket = null;OutputStream out = null;try {socket = socketFactory.createSocket("localhost", 8080);out = socket.getOutputStream();// 请求服务器String lines = "床前明月光\r\n疑是地上霜\r\n举头望明月\r\n低头思故乡\r\n";byte[] outputBytes = lines.getBytes("UTF-8");out.write(outputBytes);out.flush();} finally {// 关闭连接out.close();socket.close();}}
}

MINA、Netty、Twisted一起学系列

MINA、Netty、Twisted一起学(一):实现简单的TCP服务器

MINA、Netty、Twisted一起学(二):TCP消息边界问题及按行分割消息

MINA、Netty、Twisted一起学(三):TCP消息固定大小的前缀(Header)

MINA、Netty、Twisted一起学(四):定制自己的协议

MINA、Netty、Twisted一起学(五):整合protobuf

MINA、Netty、Twisted一起学(六):session

MINA、Netty、Twisted一起学(七):发布/订阅(Publish/Subscribe)

MINA、Netty、Twisted一起学(八):HTTP服务器

MINA、Netty、Twisted一起学(九):异步IO和回调函数

MINA、Netty、Twisted一起学(十):线程模型

MINA、Netty、Twisted一起学(十一):SSL/TLS

MINA、Netty、Twisted一起学(十二):HTTPS

源码

https://github.com/wucao/mina-netty-twisted

MINA、Netty、Twisted一起学(十一):SSL/TLS相关推荐

  1. Mina、Netty、Twisted一起学(五):整合protobuf

    protobuf是谷歌的Protocol Buffers的简称,用于结构化数据和字节码之间互相转换(序列化.反序列化),一般应用于网络传输,可支持多种编程语言. protobuf怎样使用这里不再介绍, ...

  2. Mina、Netty、Twisted一起学(一):实现简单的TCP服务器

    MINA.Netty.Twisted为什么放在一起学习?首先,不妨先分别看一下它们官方网站对其的介绍: MINA: Apache MINA is a network application frame ...

  3. Netty入门(七)使用SSL/TLS加密Netty程序

    为了支持 SSL/TLS,Java 提供了 javax.net.ssl API 的类 SslContext 和 SslEngine 使它相对简单的实现解密和加密.Netty 利用该 API 实现了 C ...

  4. 速记:安卓Netty部署SSL/TLS和避坑指南

    速记:安卓Netty部署SSL/TLS和避坑指南 先按照 https://blog.csdn.net/russle/article/details/99086684 方法操作 第一步 生成服务器端私钥 ...

  5. 添加https后反向代理gateway报错io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record

    添加https后反向代理gateway报错 2023-02-17 14:19:05.328 [reactor-http-epoll-4] ------ ERROR c..si.gateway.exce ...

  6. 开源项目SMSS发开指南(四)——SSL/TLS加密通信详解

    本文将详细介绍如何在Java端.C++端和NodeJs端实现基于SSL/TLS的加密通信,重点分析Java端利用SocketChannel和SSLEngine从握手到数据发送/接收的完整过程.本文也涵 ...

  7. GCDAsyncSOcket使用及其SSL/TLS双向认证的实现

    GCDAsyncSoceket使用及其SSL/TLS的实现 关于GCDAsyncSocket:首先我们得知道GCDAsnyc是由第三方开发的一个苹果系统的socket库,功能强大,而且简单易用.当然关 ...

  8. SSL/TLS攻击介绍--重协商漏洞攻击

    一.概述 最近几年曝出的高风险SSL/TLS安全漏洞大多跟SSL实现库相关,比如2011年曝出的SSL/TLS默认重协商漏洞,可导致DOS攻击, 比如2014年4月曝出的"心脏滴血" ...

  9. Spring-cloud-gateway:not an SSL/TLS record: 485454502f312e3120343030200d0a436f6e74656e76c3报错

    报错信息: 2022-06-26 07:22:46.066  INFO 6136 --- [  restartedMain] com.lxs.demo.GatewayApplication       ...

最新文章

  1. 健康大脑结构的变化如何影响认知的?
  2. 主线程 java_java-在子线程中执行主线程方法
  3. Cannot resolve field [product], input field list:[user, EXPR$0]
  4. 在Linux下使用iconv转换字符串编码
  5. 大公司里学做人,小公司里学做事。
  6. 学习Python编程培训 有哪些爬虫技术课程需要掌握
  7. 团队文化中的害群之马
  8. 简单的Python文件服务器和HTTP POST上传文件C代码
  9. Atitit 数据库抽象层jdbc pdo ado.net等比较与异常点 目录 1. 应该具有的功能 1 1.1. 元数据 API 1 1.2. 分布式事务 vs事务中使用 Savepoint 1
  10. 从文案到配音,只需要一部手机!5分钟掌握影视解说制作流程
  11. 敏捷开发Sprint周期总结
  12. LAMMPS案例分析——水滴的蒸发
  13. Keyword Spotting (KWS) | Deep Spoken Keyword Spotting: An Overview
  14. vba 关闭屏幕刷新
  15. 12月的第一天!给你一个11月回血指南!
  16. 微信小程序-动态验证码
  17. 机器学习(Machine Learning)深度学习(Deep Learning)资料汇总
  18. 腾讯云注册与实名图文教程
  19. angular js 循环数据(死数据) 添加数据 隔行换色 单个删除 排序
  20. 上汽招聘项目管理PMO(地点:上海,薪酬面议)

热门文章

  1. Vue----单文件组件
  2. 出门问问×趁早|内测探索“序列猴子”大模型,联手打造“好习惯小助手”
  3. cdh 安装 agent失败
  4. 计算机网络之IP地址分配及静态路由配置
  5. flask_wtf CSRFProtect机制
  6. AmazonS3文档——对象存储之《对象操作》
  7. 自己编写小程序背日语50音图
  8. 2023年大学开学典礼讲话稿
  9. sso 服务端配置_使用身份传播配置服务提供商启动的SSO
  10. 两年 JAVA 程序员的面试总结