对于IM聊天应用来说,为了提升安全性,对聊天消息加密是常规操作。
注:对于那些付费购买了第3方权威CA机构签发的证书,他们都有相应的使用文档,这就没什么好说的。本文里的证书指的是不需要花钱的自签名证书。
学习交流:
2、知识准备
如果你对IM、Netty已基本上手,但对IM安全方面的技术概念有点理不清,建议必读《基于Netty的IM聊天加密技术学习:一文理清常见的加密概念、术语等》。
3、什么是Netty
Netty是一个JavaNIO技术的开源异步事件驱动的网络编程框架,用于快速开发可维护的高性能协议服务器和客户端。往通俗了讲,可以将Netty理解为:一个将JavaNIO进行了大量封装,并大大降低JavaNIO使用难度和上手门槛的超牛逼框架。(引用自《史上最通俗Netty框架入门长文:基本介绍、环境搭建、动手实战》)
4、什么是OpenSSL
OpenSSL是一个开放源代码的软件库,应用程序可以使用这个包来进行安全通信,它包括代码、脚本、配置和过程的集合。其主要库是以C语言所写成,实现了基本的加密功能,实现了SSL与TLS协议。OpenSSL整个软件包大概可以分成三个主要功能部分:SSL协议库、应用程序、密码算法库。
PS:OpenSSL的介绍就点到为止,如有兴趣,可仔细阅读《基于Netty的IM聊天加密技术学习:一文理清常见的加密概念、术语等》。
5、下载和安装OpenSSL
1)方法一:可以从OpenSSL的Github仓库下载源码自行编译(源码下载地址),对于一般使用者来说,自已编译着实有点麻烦,不推荐这么玩。
3)方法一:也可以直接用下面附件里的安装程序(这是我一直用的版本,版本较老,有兴趣可直接下载使用):
Openssl-windows-0.9.8k(52im.net).rar(874.97KB,下载次数:1,售价:1金币)
4)解决“openssl.cnf找不到”的问题:如果你安装好OpenSSL后,使用时报“openssl.cnf找不到”或“计算机缺少openssl.cnf”等之类错误提示,可以下载下面这个openssl.cnf文件。
openssl.cnf文件附件下载:
openssl_conf(52im.net).rar(4.63KB,下载次数:1,售价:1金币)
openssl.cnf文件解压缩后:
openssl.cnf文件配置使用:
以下是openssl.cnf文件的配置使用命令:(以我的安装目录为例)
C:\Openssl-windows-0.9.8k-out32dll>setOPENSSL_CONF=c:/WINDOWS/system32/openssl.cnf
准备就绪,接下来我们就可以开始生成SSL/TLS证书了!
6、生成Netty可用的SSL/TLS证书
6.1概述
经过实践,生成Netty可用的SSL/TLS证书需要4步:
接下来,跟着本节内容,一步步使用OpenSSL生成一个真正能在Netty中能使用的自签名证书。
6.2第一步:创建私钥证书
在CMD控制台下执行如下指令:(记得手动创建netty目录)
opensslgenrsa-des3-outnetty/netty-key.pem1024
提示:以上指令中,如无“-des3”参数,则Netty的代码中使用时将报“Filedoesnotcontainvalidprivatekey”等错误(如下图所示)。
6.3第二步:将私钥格式转成pk8
在CMD控制台下执行如下指令:
opensslpkcs8-innetty/netty-key2.pem-topk8-outnetty/netty-key2.pk8
提示1:如不转pk8格式,则Netty的代码中使用时会报以下错误:
提示2:如代码中不为key加入密码,则Netty的代码中使用时会报以下错误:
提示3:Netty的代码中使用时要加入上方生成Key证书时的密码即可:
6.4第三步:创建证书请求
opensslreq-new-outnetty/netty-req2.csr-keynetty/netty-key2.pem
提示:经上指令中,CommonName指明的是证书绑定的域名,你可以用域名或ip,本次生成用了子域名。
6.5第四步:生成公钥证书
opensslx509-req-inca/ca-req2.csr-outnetty/netty-cert2.crt-signkeynetty/netty-key2.pem-days3650
提示:out参数生成的是.crt,而在前面的是.pem,这只是扩展名区别,内容都一样。
6.6最终成果
7、实战代码
7.1概述
本节将为你演示如何在基于Netty的IM中使用上节中生成的证书。
为了让示例代码更具实战意义,本节的示例代码将引用的是开源IM框架MobileIMSDK的源码,如果有兴趣深入学习,可以从下面的开源仓库中下载到MobileIMSDK的完整源码。
7.2基于Netty的IM服务端如何开启SSL/TLS
首先将上节中生成的证书,放置到你的IM服务端磁盘目录下。以下截图和示例代码以MobileIMSDK的开源代码为例。
我们可以将证书放到这个位置:
使用证书的示例代码片段:(完整代码详见ServerLauncherImpl.java)
*创建SslContext对象,用于开启SSL/TLS加密传输。*@return如果成功创建则返回SslContext对象,否则返回nullprivatestaticSslContextcreateSslContext(){try{//证书文件InputStreamcertChainFile=ServerLauncherImpl.class.getResourceAsStream("certs/netty-cert2.crt");//私钥文件(注意:Netty只支持.pk8格式)InputStreamkeyFile=ServerLauncherImpl.class.getResourceAsStream("certs/netty-key2.pk8");//私钥密码StringkeyPassword="123456";//生成SslContext对象(为了方便理解,此处使用的是单向认证)SslContextsslCtx=SslContextBuilder.forServer(certChainFile,keyFile,keyPassword).clientAuth(ClientAuth.NONE).build();returnsslCtx;}catch(Exceptione){logger.warn("createSslContext()时出错了,原因:"+e.getMessage(),e);returnnull;
PS:如果你想自已动手完整运行一下,可以阅读《MobileIMSDK的Demo使用帮助:Server端》。
接下来的内容,我们将实现客户端连接到使用SSL/TLS证书的NettyIM服务端。
7.3Android端如何开启SSL/TLS
因为服务端已经开启了SSL/TLS加密,我们在开发IM的客户端时,该如何启用SSL/TLS呢(否则你未开启SSL/TLS的客户端肯定是连不上你的服务端的)?
这里为了方便示例,我们同样以MobileIMSDK的Android端开源代码为例。
Android端开启SSL/TLS加密的示例代码片段:(完整代码详见IMClientManager.java)
*创建SslContext对象,用于开启SSL/TLS加密传输。*@return如果成功创建则返回SslContext对象,否则返回nullpublicSslContextcreateSslContext(){SslContextsslContext=null;try{sslContext=SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();Log.d(TAG,"【IMCORE-TCP】已开启SSL/TLS加密(单向认证),且sslContext创建成功。");}catch(Exceptione){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)
说明:CocoaAsyncSocket中开启SSL/TLS并不像Android和Java中那么简单,它不只是几行代码的事,而是整个数据读取逻辑的变化。
PS:如果你想自已动手完整运行一下,可以阅读《MobileIMSDK的Demo使用帮助:iOS版》。
7.5Java桌面端如何开启SSL/TLS
Java桌面端开启SSL/TLS的代码跟Android端是一样。我们同样以MobileIMSDK的Java端开源代码为例。
Java桌面端开启SSL/TLS加密的示例代码片段:(完整代码详见IMClientManager.java)
PS:如果你想自已动手完整运行一下,可以阅读《MobileIMSDK的Demo使用帮助:Java版》。
7.6H5端如何开启SSL/TLS
我这里说的H5端,指的是能支持标准HTML5端WebSocket协议的PC浏览器端、手机移动端内嵌的Web引擎等场景。
H5端能开启SSL/TLS有两个前提:
满足以上两点后,H5端什么代码都不需改动,只需将请求url由“ws”改成“wss”:
8、参考资料
[1]MobileIMSDK开源工程源码
[2]史上最通俗Netty框架入门长文:基本介绍、环境搭建、动手实战
[3]基于Netty,从零开发IM
[4]基于Netty的IM聊天加密技术学习:一文理清常见的加密概念、术语等