簡介

在之前的文章中,我們講到了怎麼使用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

本文已收錄於 http://www.flydean.com/12-netty-securechat/

最通俗的解讀,最深刻的幹貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!

netty系列之:對聊天進行加密的更多相關文章

  1. Netty之多用戶的聊天室(三)

    Netty之多用戶的聊天室(三) 一.簡單說明 筆者有意將Netty做成一個系列的文章,因為筆者並不是一個善於寫文章的人,而且筆者學習很多技術一貫的習慣就是敲代碼,很多東西敲著敲著就就熟了,然後再進行 ...

  2. 4. 彤哥說netty系列之Java NIO實現群聊(自己跟自己聊上癮了)

    你好,我是彤哥,本篇是netty系列的第四篇. 歡迎來我的公從號彤哥讀源碼系統地學習源碼&架構的知識. 簡介 上一章我們一起學習了Java中的BIO/NIO/AIO的故事,本章將帶著大家一起使 ...

  3. 用SignalR 2.0開發客服系統[系列2:實現聊天室]

    前言 交流群:195866844 上周發錶了 用SignalR 2.0開發客服系統[系列1:實現群發通訊] 這篇文章,得到了很多幫助和鼓勵,小弟在此真心的感謝大家的支持.. 這周繼續系列2,實現聊天室 ...

  4. 即時通信系統中如何實現:聊天消息加密,讓通信更安全? 【低調贈送:QQ高仿版GG 4.5 最新源碼】

    加密重要的通信消息,是一個常見的需求.在一些政府部門的即時通信軟件中(如稅務系統),對聊天消息進行加密是非常重要的一個功能,因為談話中可能會涉及到機密的數據.我在最新的GG 4.5中,增加了對聊天消息 ...

  5. 即時通信系統中實現聊天消息加密,讓通信更安全【低調贈送:C#開源即時通訊系統(支持廣域網)——GGTalk4.5 最新源碼】

    在即時通訊系統(IM)中,加密重要的通信消息,是一個常見的需求.尤其在一些政府部門的即時通信軟件中(如稅務系統),對即時聊天消息進行加密是非常重要的一個功能,因為談話中可能會涉及到機密的數據.我在最新 ...

  6. Netty 系列目錄

    Netty 系列目錄 二 Netty 源碼分析(4.1.20) 1.1 Netty 源碼(一)Netty 組件簡介 2.1 Netty 源碼(一)服務端啟動 2.2 Netty 源碼(二)客戶端啟動 ...

  7. Netty系列(四)TCP拆包和粘包

    Netty系列(四)TCP拆包和粘包 一.拆包和粘包問題 (1) 一個小的Socket Buffer問題 在基於流的傳輸裏比如 TCP/IP,接收到的數據會先被存儲到一個 socket 接收緩沖裏.不 ...

  8. Netty 系列(三)Netty 入門

    Netty 系列(三)Netty 入門 Netty 是一個提供异步事件驅動的網絡應用框架,用以快速開發高性能.高可靠性的網絡服務器和客戶端程序.更多請參考:Netty Github 和 Netty中文 ...

  9. 【讀後感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎樣 ?

    [讀後感]Netty 系列之 Netty 高性能之道 - 相比 Mina 怎樣 ? 太陽火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...

  10. 1. 彤哥說netty系列之開篇(有個問卷調查)

    你好,我是彤哥,本篇是netty系列的第一篇. 歡迎來我的公從號彤哥讀源碼系統地學習源碼&架構的知識. 簡介 本文主要講述netty系列的整體規劃,並調查一下大家喜歡的學習方式. 知識點 ne ...

隨機推薦

  1. 【小白的CFD之旅】09 初識FLUENT

    按黃師姐的推薦,小白回頭查找起 FLUENT的資料來.通過網絡及圖書館查找相關資料,小白對於FLUENT有了基本的認識. FLUENT是一個CFD軟件包,目前隸屬於ANSYS公司 目前FLUENT的最 ...

  2. python 學習筆記十五 django基礎

    Python的WEB框架有Django.Tornado.Flask 等多種,Django相較與其他WEB框架其優勢為:大而全,框架本身集成了ORM.模型綁定.模板引擎.緩存.Session等諸多功能. ...

  3. java提高篇(二四)-----HashSet

          在前篇博文中(java提高篇(二三)-----HashMap)詳細講解了HashMap的實現過程,對於HashSet而言,它是基於HashMap來實現的,底層采用HashMap來保存元素. ...

  4. gitlab配置郵件通知功能操作記錄

    之前已經介紹了gitlab的部署http://www.cnblogs.com/kevingrace/p/5651402.html但是沒有配置郵箱通知功能,今天這裏介紹下gitlab安裝後的郵箱配置操作 ...

  5. 【Linux命令與工具】ps命令

    Linux中的ps命令是Process Status的縮寫.ps命令用來列出系統中當前運行的那些進程.ps命令列出的是當前那些進程的快照,就是執行ps命令的那個時刻的那些進程,如果想要動態的顯示進程信 ...

  6. [XJOI NOI2015模擬題13] A 神奇的矩陣 【分塊】

    題目鏈接:XJOI NOI2015-13 A 題目分析 首先,題目定義的這種矩陣有一個神奇的性質,第 4 行與第 2 行相同,於是第 5 行也就與第 3 行相同,後面的也是一樣. 因此矩陣可以看做只有 ...

  7. (轉)java提高篇(二)-----理解java的三大特性之繼承

    在<Think in java>中有這樣一句話:複用代碼是Java眾多引人注目的功能之一.但要想成為極具革命性的語言,僅僅能够複制代碼並對加以改變是不够的,它還必須能够做更多的事情.在這句 ...

  8. 給dataframe添加一列索引

    測試數據自己瞎編的 需求:給現在df數據添加一列sid,要求這一列是和stock一一對應的整數 代碼如下: import pandas as pd test_data = {'stock': ['AA ...

  9. 【oracle】dmp導數據庫

    假定數據庫A為源數據庫,數據庫B為目標數據庫 step1在數據庫A中,導出生成.dmp文件,操作流程如下(以下操作均在系統用戶ora11g下執行) 1.該操作只需要在第一次使用時執行,A_dump_d ...

  10. 深入理解原型鏈(Prototype chain) __proto__

    原型鏈(Prototype chain) 原型對象也是普通的對象,並且也有可能有自己的原型,如果一個原型對象的原型不為null的話,我們就稱之為原型鏈(prototype chain). A prot ...