乐趣区

关于netty:netty系列之对聊天进行加密

工具与资源核心
帮忙开发者更加高效的工作,提供围绕开发者全生命周期的工具与资源
https://developer.aliyun.com/…

简介

在之前的文章中,咱们讲到了怎么应用 netty 建设聊天室,然而这样的简略的聊天室太容易被窃听了,如果想要在外面说点悄悄话是很不平安的,怎么办呢?学过密码学的敌人可能就想到了一个解决办法,聊天的时候对音讯加密,解决的时候再对音讯解密即可。
当然在 netty 中上述的工作都不须要咱们手动来实现,netty 曾经提供了反对 SSL 的 channel 供咱们抉择,一起来看看吧。

PKI 规范

在讲 netty 的具体反对之前,咱们须要先理解一下公钥和私钥的加密规范体系 PKI。PKI 的全称是 Public Key Infrastructure,也就是公钥体系。用于标准公钥私募进行加密解密的规定,从而便于不同零碎的对接。
事实上 PKI 规范曾经有两代协定了。
第一代的 PKI 规范次要是由美国 RSA 公司的公钥加密规范 PKCS,国际电信联盟的 ITU-T X.509,IETF 的 X.509,WAP 和 WPKI 等规范组成。然而因为第一代 PKI 规范是基于形象语法符号 ASN.1 进行编码的,实现起来比较复杂和艰难,所以产生了第二代 PKI 规范。
第二代 PKI 规范是由微软、VeriSign 和 webMethods 三家公司在 2001 年公布的基于 XML 的密钥治理标准也叫做 XKMS。
事实上当初 CA 核心应用的最广泛的标准还是 X.509 系列和 PKCS 系列。
X.509 系列次要由 X.209、X.500 和 X.509 组成,其中 X.509 是由国际电信联盟(ITU-T)制订的数字证书规范。在 X.500 根底上进行了性能加强,
X.509 是在 1988 年公布的。X.509 证书由用户公共密钥和用户标识符组成。此外还包含版本号、证书序列号、CA 标识符、签名算法标识、签发者名称、证书有效期等信息。
而 PKCS 是美国 RSA 公司的公钥加密规范,包含了证书申请、证书更新、证书作废表公布、扩大证书内容以及数字签名、数字信封的格局等方面的一系列相干协定。它定义了一系列从 PKCS#1 到 PKCS#15 的规范。
其中最罕用的是 PKCS#7、PKCS#12 和 PKCS#10。PKCS#7 是音讯申请语法,罕用于数字签名与加密,PKCS#12 是集体音讯替换与打包语法次要用来生成公钥和私钥。PKCS#10 是证书申请语法。

各类证书的后缀和转换

操作过证书的敌人可能会对证书的后缀目迷五色,一般来说会有 DER、CRT、CER、PEM 这几种证书的后缀。
DER 示意证书的内容是用二进制进行编码的。
PEM 文件是一个文本文件,其内容是以“– BEGIN -”结尾的,Base64 编码的字符。
CRT 和 CER 基本上是等价的,他们都是证书的扩大,也是文本文件,不同的是 CRT 通常用在 liunx 和 unix 零碎中,而 CER 通常用在 windows 零碎中。并且在 windows 零碎中,CER 文件会被 MS cryptoAPI 命令辨认,能够间接显示导入和 / 或查看证书内容的对话框。
KEY 文件,次要用来保留 PKCS#8 规范的公钥和私钥。
上面的命令能够用来查看文本证书内容:

openssl x509 -in cert.pem -text -noout
openssl x509 -in cert.cer -text -noout
openssl x509 -in cert.crt -text -noout
上面的命令能够用来查看二进制证书内容:
openssl x509 -in cert.der -inform der -text -noout
上面是常见的 PEM 和 DER 互相转换:

PEM 到 DER
openssl x509 -in cert.crt -outform der-out cert.der
DER 到 PEM
openssl x509 -in cert.crt -inform der -outform pem -out cert.pem

netty 中启动 SSL server

事实上这个题目是不对的,netty 中启动的 server 还是原来那个 server,只是对发送的音讯进行了加密解密解决。也就是说增加了一个专门进行 SSL 操作的 Handler。
netty 中代表 ssl 处理器的类叫做 SslHandler,它是 SslContext 工程类的一个外部类,所以咱们只须要创立好 SslContext 即可通过调用 newHandler 办法来返回 SslHandler。
让服务器端反对 SSL 的代码:
ChannelPipeline p = channel.pipeline();
SslContext sslCtx = SslContextBuilder.forServer(…).build();
p.addLast(“ssl”, sslCtx.newHandler(channel.alloc()));
让客户端反对 SSL 的代码:
ChannelPipeline p = channel.pipeline();
SslContext sslCtx = SslContextBuilder.forClient().build();
p.addLast(“ssl”, sslCtx.newHandler(channel.alloc(), host, port));
netty 中 SSL 的实现有两种形式,默认状况下应用的是 OpenSSL,如果 OpenSSL 不能够,那么将会应用 JDK 的实现。
要创立 SslContext, 能够调用 SslContextBuilder.forServer 或者 SslContextBuilder.forClient 办法。
这里以 server 为例,看下创立流程。SslContextBuilder 有多种 forServer 的办法,这里取最简略的一个进行剖析:

public static SslContextBuilder forServer(File keyCertChainFile, File keyFile) {
return new SslContextBuilder(true).keyManager(keyCertChainFile, keyFile);
}
该办法接管两个参数,keyCertChainFile 是一个 PEM 格局的 X.509 证书文件,keyFile 是一个 PKCS#8 的私钥文件。
相熟 OpenSSL 的童鞋应该晓得应用 openssl 命令能够生成私钥文件和对应的自签名证书文件。
具体 openssl 的操作能够查看我的其余文章,这里就不具体解说了。
除了手动创立证书文件和私钥文件之外,如果是在开发环境中,大家可能心愿有一个非常简单的办法来创立证书和私钥文件,netty 为大家提供了 SelfSignedCertificate 类。
看这个类的名字就是晓得它是一个自签名的证书类,并且会主动将证书文件和私钥文件生成在零碎的 temp 文件夹中,所以这个类在生产环境中是不举荐应用的。默认状况下该类会应用 OpenJDK’s X.509 来生成证书的私钥,如果不能够,则应用 Bouncy Castle 作为代替。

netty 中启动 SSL client

同样的在 client 中反对 SSL 也须要创立一个 handler。客户端的 SslContext 创立代码如下:

// 配置 SSL.
final SslContext sslCtx = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE).build();
下面的代码咱们应用了一个 InsecureTrustManagerFactory.INSTANCE 作为 trustManager。什么是 trustManager 呢?
当客户端和服务器端进行 SSL 连贯的时候,客户端须要验证服务器端发过来证书的正确性,通常状况下,这个验证是到 CA 服务器中进行验证的,不过这样须要一个实在的 CA 证书环境,所以在测试中,咱们应用 InsecureTrustManagerFactory,这个类会默认承受所有的证书,疏忽所有的证书异样。
当然,CA 服务器也不是必须的,客户端校验的目标是查看证书中的公钥和发送方的公钥是不是统一的,那么对于不能联网的环境,或者自签名的环境中,咱们只须要在客户端校验证书中的指纹是否统一即可。
netty 中提供了一个 FingerprintTrustManagerFactory 类,能够对证书中的指纹进行校验。
该类中有个 fingerprints 数组,用来存储平安的受权过的指纹信息。通过比照传入的证书和指纹,如果统一则校验通过。
应用 openssl 从证书中提取指纹的步骤如下:
openssl x509 -fingerprint -sha256 -in my_certificate.crt

总结

通过设置 client 和 server 端的 SSL handler,就能够实现客户端和服务器端的加密音讯传输。
本文的例子能够参考:learn-netty4(https://github.com/ddean2009/…)

退出移动版