在之前的文章中 我们讲到了怎么使用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.pemnetty中启动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/
最通俗的解读 最深刻的干货 最简洁的教程 众多你不知道的小技巧等你来发现
欢迎关注我的公众号:「程序那些事」,懂技术 更懂你
清楚你的优先级 代码的写法有很多种:有的运行起来很快,有的只会占用少量内存,...
大家好,最近有小伙伴在后台问我,大一新生学校在教C语言,是不是已经过时了?第...
致力于将数据转化为行动和价值的 Splunk公司(NASDAQ:SPLK)今天宣布与新推出的Am...
对于做外贸的企业级用户,如果客户仅是香港、台湾、日本客户,建议租用 香港服务...
问题描述 用户购买HECS后,无法Ping通弹性公网IP,或者云服务器Ping不通外网。 ...
域名 哪个需实名?域名实名制目的是为了迫使企业或个人对网站发布的内容负责,到...
随着科技的进步,中国互联网的普及,信息的传递越来越多的靠互联网来完成,包括...
1. 接口描述 接口请求域名: cvm.tencentcloudapi.com 。 本接口 (CreateDisaste...
蒋江伟 / 文 对于云计算的用户来说,理解什么是云原生尤为重要。不是简单地使用...
如今,推荐系统已经成为各大电商平台的重要流量入口,谁才能够做到比用户更懂用...