温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Netty、MINA、Twisted中SSL/TLS的示例分析

发布时间:2021-12-28 15:48:14 阅读:196 作者:小新 栏目:开发技术
亿速云SSL证书,防劫持篡改、防监听窃取、提升搜索排名 点击了解>>

这篇文章主要介绍了Netty、MINA、Twisted中SSL/TLS的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

1. 相关术语

在学习SSL/TLS协议之前,首先要了解一些相关概念:

对称加密:加密和解密都采用同一个密钥,常用的算法有DES、3DES、AES,相对于非对称加密算法更简单速度更快。

非对称加密:和对称加密算法不同,非对称加密算法会有两个密钥:公钥(可以公开的)和私钥(私有的),例如客户端如果使用公钥加密,那么即时其他人有公钥也无法解密,只能通过服务器私有的私钥解密。RSA算法即是典型的非对称加密算法。

数字证书:数字证书是一个包含公钥并且通过权威机构发行的一串数据,数字证书很多需要付费购买,也有免费的,另外也可以自己生成数字证书,本文中将会采用自签名的方式生成数字证书。

2. SSL/TLS流程

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

1)客户端发出请求:这一步客户端会生成一个随机数传给服务器。

2)服务器回应:这一步服务器会返回给客户端一个服务器数字证书(证书中包含用于加密的公钥),另外服务器也会生成一个随机数给客户端。

3)客户端回应:这一步客户端首先会校验数字证书的合法性,然后会再生成一个随机数,这个随机数会使用第2步中的公钥采用非对称加密算法(例如RSA算法)进行加密后传给服务器,密文只能通过服务器的私钥来解密。

4)服务器最后回应:握手结束。

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

3. 生成私钥和证书

使用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

4. SSL/TLS服务器

接下来在Netty、MINA、Twisted一起学系列02:TCP消息边界问题及按行分割消息 一文的基础上,加上SSL/TLS层。

1)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.html        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();            }        }        // 私钥        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 {    @Override    public void exceptionCaught(IoSession session, Throwable cause)            throws Exception {        cause.printStackTrace();    }    @Override    public void messageReceived(IoSession session, Object message)            throws Exception {        String line = (String) message;        System.out.println("messageReceived:" + line);    }    @Override    public void sessionCreated(IoSession session) throws Exception {        System.out.println("sessionCreated");    }    @Override    public void sessionClosed(IoSession session) throws Exception {        System.out.println("sessionClosed");    }}

2)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>() {                        @Override                        public 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 {    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) {        String line = (String) msg;        System.out.println("channelRead:" + line);    }    @Override    public void channelActive(ChannelHandlerContext ctx) {        System.out.println("channelActive");    }    @Override    public void channelInactive(ChannelHandlerContext ctx) {        System.out.println("channelInactive");    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {        cause.printStackTrace();        ctx.close();    }}

3)Twisted

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

# -*- coding:utf-8 –*-from twisted.protocols.basic import LineOnlyReceiverfrom twisted.internet.protocol import Factoryfrom 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 = TcpServerHandlereactor.listenSSL(8080, factory, sslContext)reactor.run()

5. 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();        }    }}

感谢你能够认真阅读完这篇文章,希望小编分享的“Netty、MINA、Twisted中SSL/TLS的示例分析”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!

亿速云提供多种品牌、不同类型SSL证书签发服务,包含:域名型、企业型、企业型专业版、增强型以及增强型专业版,单域名SSL证书300元/年起。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:http://blog.itpub.net/31558358/viewspace-2565392/

AI

开发者交流群×