简介

在之前的文章中,咱们讲到了怎么应用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 -nooutopenssl x509 -in cert.cer -text -nooutopenssl x509 -in cert.crt -text -noout

上面的命令能够用来查看二进制证书内容:

openssl x509 -in cert.der -inform der -text -noout

上面是常见的PEM和DER互相转换:

PEM到DERopenssl x509 -in cert.crt -outform der-out cert.derDER到PEMopenssl 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

本文已收录于 http://www.flydean.com/12-netty-securechat/

最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!

欢送关注我的公众号:「程序那些事」,懂技术,更懂你!