关于即时通讯:手把手教你为基于Netty的IM生成自签名SSLTLS证书

39次阅读

共计 8187 个字符,预计需要花费 21 分钟才能阅读完成。

1、引言

对于 IM 聊天利用来说,为了晋升安全性,对聊天音讯加密是惯例操作。
众所周之,Netty 是高性能的 Java NIO 网络通信框架,因此用 Netty 来写 IM 是再失常不过了。网上对于为 Netty 生成、以及应用 SSL/TLS 证书的文章有很多,但因为各种起因,生成的证书要么是 Netty 中无奈读取和应用,要么是代码不全或不具体导致基本配不通 SSL/TLS 加密。
正好这段时间专门为 MobileIMSDK 生成了一套测试证书,棘手把这个过程记录了下来,分享给大家。
本文要分享的是如何应用 OpenSSL 生成在基于 Netty 的 IM 中真正可用的 SSL/TLS 证书,内容包含:证书的创立、创立过程中的留神点,以及在 Server 端、Android 端、iOS 端、Java 桌面端、H5 端应用证书的代码范例。

注:对于那些付费购买了第 3 方权威 CA 机构签发的证书,他们都有相应的应用文档,这就没什么好说的。本文里的证书指的是不须要花钱的自签名证书。
学习交换:

  • 挪动端 IM 开发入门文章:《新手入门一篇就够:从零开发挪动端 IM》
  • 开源 IM 框架源码:https://github.com/JackJiang2…(备用地址点此)
    (本文已同步公布于:http://www.52im.net/thread-41…)

2、常识筹备

► 如果你对 IM 零碎毫无概念,倡议先浏览《零根底 IM 开发入门 (一):什么是 IM 零碎?》系列文章,通俗易懂,适宜小白。
► 如果你想零碎学习 IM 开发相干的理论知识,比方网格编程、IM 架构设计等,倡议先浏览《新手入门一篇就够:从零开发挪动端 IM》。
► 如果你不理解 Netty 是什么,倡议浏览以下几篇 Netty 的根底入门好文章:

  • 1)新手入门:目前为止最透彻的的 Netty 高性能原理和框架架构解析
  • 2)写给初学者:Java 高性能 NIO 框架 Netty 的学习办法和进阶策略
  • 3)史上最艰深 Netty 框架入门长文:根本介绍、环境搭建、入手实战

► 如果你已把握 IM 理论知识,同时也对 Netty 根本把握,正筹备入手实战,则能够浏览《基于 Netty,从零开发 IM》和《跟着源码学 IM》这个系列文章,有各种入门级实战代码,图文并茂,适宜学习。
► 如果你对 IM、Netty 已基本上手,但对 IM 平安方面的技术概念有点理不清,倡议必读《基于 Netty 的 IM 聊天加密技术学习:一文理清常见的加密概念、术语等》。

3、什么是 Netty

Netty 是一个 Java NIO 技术的开源异步事件驱动的网络编程框架,用于疾速开发可保护的高性能协定服务器和客户端。往艰深了讲,能够将 Netty 了解为:一个将 Java NIO 进行了大量封装,并大大降低 Java NIO 应用难度和上手门槛的超牛逼框架。(援用自《史上最艰深 Netty 框架入门长文:根本介绍、环境搭建、入手实战》)
PS:限于篇幅,对于 Netty 方面的入门常识就不再赘述,如有必要,请认真跟着本文第二节“2、常识筹备”里无关 Netty 的文章进行浏览。

4、什么是 OpenSSL

OpenSSL 是一个凋谢源代码的软件库,应用程序能够应用这个包来进行平安通信,它包含代码、脚本、配置和过程的汇合。其次要库是以 C 语言所写成,实现了根本的加密性能,实现了 SSL 与 TLS 协定。OpenSSL 整个软件包大略能够分成三个次要性能局部:SSL 协定库、应用程序、明码算法库。PS:OpenSSL 的介绍就点到为止,如有趣味,可仔细阅读《基于 Netty 的 IM 聊天加密技术学习:一文理清常见的加密概念、术语等》。

5、下载和装置 OpenSSL

1)办法一:能够从 OpenSSL 的 Github 仓库下载源码自行编译(源码下载地址),对于个别使用者来说,自已编译着实有点麻烦,不举荐这么玩。
2)办法一:也能够从这个网站下载第 3 方编译好的 OpenSSL 安装程序(安装程序下载地址),这样上手简略快捷。具体能够参考《openssl 装置教程(windows7 零碎,超具体)》这篇文章。
3)办法一:也能够间接用上面附件里的安装程序(这是我始终用的版本,版本较老,有趣味可间接下载应用):
 Openssl-windows-0.9.8k(52im.net).rar (874.97 KB , 下载次数: 1 , 售价: 1 金币)
4)解决“openssl.cnf 找不到”的问题:如果你装置好 OpenSSL 后,应用时报“openssl.cnf 找不到”或“计算机短少 openssl.cnf”等之类谬误提醒,能够下载上面这个 openssl.cnf 文件。openssl.cnf 文件附件下载:
openssl_conf(52im.net).rar (4.63 KB , 下载次数: 1 , 售价: 1 金币)openssl.cnf 文件解压缩后:

openssl.cnf 文件配置应用:

以下是 openssl.cnf 文件的配置应用命令:(以我的装置目录为例)

C:\Openssl-windows-0.9.8k-out32dll>set OPENSSL_CONF=c:/WINDOWS/system32/openssl.cnf

准备就绪,接下来咱们就能够开始生成 SSL/TLS 证书了!

6、生成 Netty 可用的 SSL/TLS 证书

6.1 概述

通过实际,生成 Netty 可用的 SSL/TLS 证书须要 4 步:
1)创立私钥证书;
2)将私钥格局转成 pk8;
3)创立证书申请;
4)生成公钥证书。
接下来,跟着本节内容,一步步应用 OpenSSL 生成一个真正能在 Netty 中能应用的自签名证书。

6.2 第一步:创立私钥证书

在 CMD 管制台下执行如下指令:(记得手动创立 netty 目录)

openssl genrsa -des3 -out netty/netty-key.pem 1024

提醒:以上指令中,如无“-des3”参数,则 Netty 的代码中应用时将报“File does not contain valid private key”等谬误(如下图所示)。

6.3 第二步:将私钥格局转成 pk8

在 CMD 管制台下执行如下指令:

openssl pkcs8 -innetty/netty-key2.pem -topk8 -out netty/netty-key2.pk8

提醒 1:如不转 pk8 格局,则 Netty 的代码中应用时会报以下谬误:

提醒 2:如代码中不为 key 退出明码,则 Netty 的代码中应用时会报以下谬误:

提醒 3:Netty 的代码中应用时要退出上方生成 Key 证书时的明码即可:

6.4 第三步:创立证书申请

在 CMD 管制台下执行如下指令:

openssl req -new -out netty/netty-req2.csr -key netty/netty-key2.pem

提醒:经上指令中,Common Name 指明的是证书绑定的域名,你能够用域名或 ip,本次生成用了子域名。

6.5 第四步:生成公钥证书

在 CMD 管制台下执行如下指令:

openssl x509 -req -inca/ca-req2.csr -out netty/netty-cert2.crt -signkey netty/netty-key2.pem -days 3650

提醒:out 参数生成的是.crt,而在后面的是.pem,这只是扩展名区别,内容都一样。

6.6 最终成绩

 

至此,咱们曾经为 Netty 创立好了证书,接下来的章节,就是分享如何读取和应用这些证书的。

7、实战代码

7.1 概述

本节将为你演示如何在基于 Netty 的 IM 中应用上节中生成的证书。
为了让示例代码更具实战意义,本节的示例代码将援用的是开源 IM 框架 MobileIMSDK  的源码,如果有趣味深刻学习,能够从上面的开源仓库中下载到 MobileIMSDK 的残缺源码。
1)GitHub.com 托管地址:https://github.com/JackJiang2…
2)码云 gitee 托管地址:https://gitee.com/jackjiang/M…

7.2 基于 Netty 的 IM 服务端如何开启 SSL/TLS

首先将上节中生成的证书,搁置到你的 IM 服务端磁盘目录下。以下截图和示例代码以 MobileIMSDK 的开源代码为例。
咱们能够将证书放到这个地位:

应用证书的示例代码片段:(残缺代码详见 ServerLauncherImpl.java)

    /** * 创立 SslContext 对象,用于开启 SSL/TLS 加密传输。* * @return 如果胜利创立则返回 SslContext 对象,否则返回 null */privatestaticSslContext createSslContext() {                   try{         // 证书文件         InputStream certChainFile = ServerLauncherImpl.class.getResourceAsStream("certs/netty-cert2.crt");         // 私钥文件(留神:Netty 只反对.pk8 格局)InputStream keyFile = ServerLauncherImpl.class.getResourceAsStream("certs/netty-key2.pk8");         // 私钥明码         String keyPassword = "123456";         // 生成 SslContext 对象(为了不便了解,此处应用的是单向认证)SslContext sslCtx = SslContextBuilder.forServer(certChainFile, keyFile, keyPassword).clientAuth(ClientAuth.NONE).build();                          returnsslCtx;} catch(Exception e) {logger.warn("createSslContext() 时出错了,起因:"+e.getMessage(), e);    }    returnnull;}

PS:如果你想自已入手残缺运行一下,能够浏览《MobileIMSDK 的 Demo 应用帮忙:Server 端》。接下来的内容,咱们将实现客户端连贯到应用 SSL/TLS 证书的 Netty IM 服务端。

7.3Android 端如何开启 SSL/TLS

因为服务端曾经开启了 SSL/TLS 加密,咱们在开发 IM 的客户端时,该如何启用 SSL/TLS 呢(否则你未开启 SSL/TLS 的客户端必定是连不上你的服务端的)?
这里为了不便示例,咱们同样以 MobileIMSDK 的 Android 端开源代码为例。
Android 端开启 SSL/TLS 加密的示例代码片段:(残缺代码详见 IMClientManager.java)

/** 
* 创立 SslContext 对象,用于开启 SSL/TLS 加密传输。* 
*  @return 如果胜利创立则返回 SslContext 对象,否则返回 null 
*/
publicSslContext createSslContext() {        SslContext sslContext = null;        try{                sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();                Log.d(TAG, "【IMCORE-TCP】已开启 SSL/TLS 加密 ( 单向认证),且 sslContext 创立胜利。");        } catch(Exception e) {Log.w(TAG, "【IMCORE-TCP】创立 sslContext 时出错,起因是:"+ e.getMessage(), e);        }         returnsslContext;}

PS:如果你想自已入手残缺运行一下,能够浏览《MobileIMSDK 的 Demo 应用帮忙:Android 版》。

7.4iOS 端如何开启 SSL/TLS

同样的,iOS 端该如何开启 SSL/TLS 呢?
这里咱们仍然以 MobileIMSDK 的 iOS 端开源代码为例(MobileIMSDK 的 iOS 应用的是 CocoaAsyncSocket 网络库,如果你也是用的它,就能够间接参考了,因为开启了 SSL/TLS 的 CocoaAsyncSocket 代码跟未开启加密的代码用法差别较多,且这方面能够参考的材料较少)。
iOS 端开启 SSL/TLS 加密的示例代码片段:(残缺代码详见 LocalSocketProvider.m)

/** * 当 socket 曾经残缺连贯并筹备好读和写数据时,将调用此办法。*/- (void)socket:(MBGCDAsyncSocket *)socket didConnectToHost:(NSString*)host port:(uint16_t)port{if([ClientCoreSDK isENABLED_DEBUG])        NSLog(@"【IMCORE-TCP-SOCKET】成收到的了 TCP 的 connect 反馈, isConnected? %d、已开启 ssl 加密? %d", [socket isConnected], [ClientCoreSDK isSSL]);     // 如果未开启 SSL 加密传输,则失常进入连贯实现后的代码逻辑    if(![ClientCoreSDK isSSL]) {[selfwhenDidConnect:socket];    }    // 如果已开启 SSL 加密传输,则须要在回调中调用 startTLS 办法,以便实现跟服务端的 SSL 握手过程,// 如果 ssl 握手胜利,则会通过 socketDidSecure: 回调告诉开发者    else{// 配置 SSL/TLS 设置信息        NSMutableDictionary*settings = [NSMutableDictionarydictionaryWithCapacity:3];        // 容许自签名证书手动验证        [settings setObject:@YESforKey:GCDAsyncSocketManuallyEvaluateTrust];        // 经测试,本项不设置并不影响 SSL 的启用 //      [settings setObject:@"此处填服务器 IP 地址" forKey:GCDAsyncSocketSSLPeerName];        // 如果不是自签名证书,而是权威证书颁发机构注册申请的证书,这个 settings 字典可不传(将应用 GCDAsyncSocket 的默认配置)[socket startTLS:settings];    }} /** * 当 SSL 握手胜利后(也就是上方调用 startSSL: 办法后),将调用此办法。*/- (void)socketDidSecure:(MBGCDAsyncSocket *)socket{[selfwhenDidConnect:socket];} /** * Allows a socket delegate to hook into the TLS handshake and manually validate the peer it's connecting to. */- (void)socket:(MBGCDAsyncSocket *)sock didReceiveTrust:(SecTrustRef)trust completionHandler:(void(^)(BOOLshouldTrustPeer))completionHandler{NSLog(@"【IMCORE-TCP-SOCKET】didReceiveTrust...");     // 以下没有做更简单的 ssl 证书验证逻辑,如您须要实现更弱小的双向认证等逻辑,能够参考这里:// [url=https://github.com/FuangCao/cavan/blob/338ca8c09d6c78c5b38b95c6ffe994241afcc96e/xcode/TestSSL/TestSSL/ViewController.m]https://github.com/FuangCao/cava ... SL/ViewController.m[/url]    if(completionHandler) {completionHandler(YES);    }}

阐明:CocoaAsyncSocket 中开启 SSL/TLS 并不像 Android 和 Java 中那么简略,它不只是几行代码的事,而是整个数据读取逻辑的变动。
PS:如果你想自已入手残缺运行一下,能够浏览《MobileIMSDK 的 Demo 应用帮忙:iOS 版》。

7.5Java 桌面端如何开启 SSL/TLS

Java 桌面端开启 SSL/TLS 的代码跟 Android 端是一样。咱们同样以 MobileIMSDK 的 Java 端开源代码为例。
Java 桌面端开启 SSL/TLS 加密的示例代码片段:(残缺代码详见 IMClientManager.java)

/** * 创立 SslContext 对象,用于开启 SSL/TLS 加密传输。* * @return 如果胜利创立则返回 SslContext 对象,否则返回 null */publicSslContext createSslContext() {        SslContext sslContext = null;        try{                sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();                Log.d(TAG, "【IMCORE-TCP】已开启 SSL/TLS 加密 ( 单向认证),且 sslContext 创立胜利。");        } catch(Exception e) {Log.w(TAG, "【IMCORE-TCP】创立 sslContext 时出错,起因是:"+ e.getMessage(), e);        }         returnsslContext;}

PS:如果你想自已入手残缺运行一下,能够浏览《MobileIMSDK 的 Demo 应用帮忙:Java 版》。

7.6H5 端如何开启 SSL/TLS

我这里说的 H5 端,指的是能反对规范 HTML5 端 WebSocket 协定的 PC 浏览器端、手机挪动端内嵌的 Web 引擎等场景。
H5 端能开启 SSL/TLS 有两个前提:
1)第 3 方 CA 机构签发的 SSL/TLS 证书(这条是要害,不然浏览器因平安起因会阻止 WebSocket 连贯的建设);
2)基于 Netty 的 IM 服务端已开启 SSL/TLS(见本章“7.2 基于 Netty 的 IM 服务端如何开启 SSL/TLS”)。
满足以上两点后,H5 端什么代码都不需改变,只需将申请 url 由“ws”改成“wss”:

8、参考资料

[1] MobileIMSDK 开源工程源码
[2] 史上最艰深 Netty 框架入门长文:根本介绍、环境搭建、入手实战
[3] 基于 Netty,从零开发 IM
[4] 基于 Netty 的 IM 聊天加密技术学习:一文理清常见的加密概念、术语等
[5] IM 聊天系统安全伎俩之通信连贯层加密技术
[6] 通俗易懂:一篇把握即时通讯的音讯传输平安原理
[7] 探讨组合加密算法在 IM 中的利用
[8] openssl 装置教程(windows7 零碎,超具体)
[9] WebSocket 从入门到精通,半小时就够!
(本文已同步公布于:http://www.52im.net/thread-41…)

正文完
 0