博客 / 詳情

返回

基於Netty的IM聊天加密技術學習:一文理清常見的加密概念、術語等

1、引言

在社區中,分享了很多篇基於Netty編寫的IM聊天入門文章(比如《跟着源碼學IM》系列、《基於Netty,從零開發IM》系列等),在這些文章中分享了各種IM通信算法原理和功能邏輯的實現。但是這樣簡單的IM聊天系統是比較容易被竊聽的,如果想要在裏面説點悄悄話是不太安全的。怎麼辦呢?學過密碼學的朋友可能就想到了一個解決辦法,聊天的時候對消息加密,處理的時候再對消息進行解密。是的,道理就是這樣。但密碼學本身的理論就很複雜,加上相關的知識和概念又太多太雜,對於IM入門者來説,想要快速理清這些概念並實現合適的加解密方案,是比較頭疼的。本文正好藉此機會,以Netty編寫的IM聊天加密為例,為入門者理清什麼是PKI體系、什麼是SSL、什麼是OpenSSL、以及各類證書和它們間的關係等,並在文末附上簡短的Netty代碼實示例,希望能助你通俗易懂地快速理解這些知識和概念!
圖片
補充説明:本文為了讓文章內容儘可能言簡意賅、通俗易懂,儘量不深入探討各個技術知識和概念,感興趣的讀者可以自行查閲相關資料進一步學習。

學習交流:

  • 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》
  • 開源IM框架源碼:https://github.com/JackJiang2...(備用地址點此)
    (本文已同步發佈於:http://www.52im.net/thread-41...)

    2、相關文章

    《即時通訊安全篇(一):正確地理解和使用Android端加密算法》
    《即時通訊安全篇(二):探討組合加密算法在IM中的應用》
    《即時通訊安全篇(三):常用加解密算法與通訊安全講解》
    《即時通訊安全篇(四):實例分析Android中密鑰硬編碼的風險》
    《即時通訊安全篇(五):對稱加密技術在Android平台上的應用實踐》
    《即時通訊安全篇(六):非對稱加密技術的原理與應用實踐》
    《即時通訊安全篇(十):IM聊天系統安全手段之通信連接層加密技術》
    《即時通訊安全篇(十一):IM聊天系統安全手段之傳輸內容端到端加密技術》

    3、什麼是PKI?

    我們需要先了解一下公鑰和私鑰的加密標準體系PKI。3.1 基本概念
    圖片
    PKI的全稱是Public Key Infrastructure,是指支持公鑰管理體制的基礎設施,提供鑑別、加密、完整性和不可否認性服務。通俗講:PKI是集機構、系統(硬件和軟件)、人員、程序、策略和協議為一體,利用公鑰概念和技術來實現和提供安全服務的、普適性的安全基礎設施。在公鑰密碼中,發送者用公鑰(加密密鑰)加密,接收者用私鑰(解密密鑰)解密。公鑰一般是公開的,不再擔心竊聽,這解決了對稱密碼中的密鑰配送問題。但是接收者依然無法判斷收到的公鑰是否合法(有可能是中間人假冒的)。事實上,僅靠公鑰密碼本身,無法防禦中間人攻擊。於是,需要(認證機構)對公鑰進行簽名,從而確認公鑰沒有被篡改。加了數字簽名的公鑰稱為公鑰證書,一般簡稱證書。有了證書來認證,可以有效防禦中間人攻擊,隨之帶來了一系列非技術性工作。例如:誰來發證書?如何發證書?不同機構的證書怎麼互認?紙質證書作廢容易,數字證書如何作廢?解決這些問題,需要制定統一的規則,即PKI體系。PKI體系是通過頒發、管理公鑰證書的方式為終端用户提供服務的系統,最核心的元素是證書。圍繞證書構成了PKI體系的要素:1)使用PKI的用户;2)頒發證書的機構(Certificate Authority,CA);3)保存證書的倉庫。總之:PKI是一個總稱,既包括定義PKI的基礎標準,也包括PKI的應用標準。3.2 PKI體系現狀事實上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是個人消息交換與打包語法主要用來生成公鑰和私鑰(題外話:iOS程序員對PKCS#12不陌生,在實現APNs離線消推送時就需要導出.p12證明,正是這個)。PKCS#10是證書請求語法。

    4、什麼是SSL?

    4.1 基本概念
    圖片
    SSL(全稱 Secure Socket Layer)安全套接層是網景公司(Netscape)率先採用的網絡安全協議。它是在傳輸通信協議(TCP/IP)上實現的一種安全協議,採用公開密鑰技術。通俗地説:SSL被設計成使用TCP來提供一種可靠的端到端的安全服務,它不是單個協議,而是二層協議。低層是SSL記錄層,用於封裝不同的上層協議,另一層是被封裝的協議,即SSL握手協議,它可以讓服務器和客户機在傳輸應用數據之前,協商加密算法和加密密鑰,客户機提出自己能夠支持的全部加密算法,服務器選擇最適合它的算法。SSL特點是:它與應用層協議獨立無關。上層的應用層協議(例如:HTTP、FTP、Telnet等)能透明的建立於SSL協議之上。SSL協議在應用層協議通信之前就已經完成加密算法、通信密鑰的協商以及服務器認證工作。在此之後應用層協議所傳送的數據都會被加密,從而保證通信的私密性。
    圖片
    4.2 與TLS的關係SSL是網景公司(Netscape)設計,但IETF將SSL作了標準化,即RFC2246,並將其稱為TLS(Transport Layer Security),其最新版本是RFC5246、版本1.2。實際上:TLS是IETF在SSL3.0基礎上設計的,相當於SSL的後續版本。所以我們通常都是SSL/TLS放一起説。

    5、什麼是OpenSSL?

    5.1 基本概念
    圖片
     OpenSSL是一個開放源代碼的軟件庫,應用程序可以使用這個包來進行安全通信,它包括代碼、腳本、配置和過程的集合。例如:如果您正在編寫一個需要複雜安全加密的軟件,那麼只有添加一個安全加密庫才有意義,這樣您就不必自己編寫一大堆複雜的加解密函數(而且密碼學本身很複雜,要寫好它們並不容易)。其主要庫是以 C 語言所寫成,實現了基本的加密功能,實現了 SSL 與 TLS 協議。OpenSSL整個軟件包大概可以分成三個主要功能部分:1)SSL協議庫;2)應用程序;3)密碼算法庫。OpenSSL的目錄結構自然也是圍繞這三個功能部分進行規劃的。OpenSSL 可以運行在 OpenVMS、 Microsoft Windows 以及絕大多數類 Unix 操作系統上。5.2 具體來説密鑰和證書管理是PKI的一個重要組成部分,OpenSSL為之提供了豐富的功能,支持多種標準。OpenSSL實現了ASN.1的證書和密鑰相關標準,提供了對證書、公鑰、私鑰、證書請求以及CRL等數據對象的DER、PEM和BASE64的編解碼功能。OpenSSL提供了產生各種公開密鑰對和對稱密鑰的方法、函數和應用程序,同時提供了對公鑰和私鑰的DER編解碼功能。並實現了私鑰的PKCS#12和PKCS#8的編解碼功能。OpenSSL在標準中提供了對私鑰的加密保護功能,使得密鑰可以安全地進行存儲和分發。在此基礎上,OpenSSL實現了對證書的X.509標準編解碼、PKCS#12格式的編解碼以及PKCS#7的編解碼功能。並提供了一種文本數據庫,支持證書的管理功能,包括證書密鑰產生、請求產生、證書籤發、吊銷和驗證等功能。5.3 發展歷程OpenSSL 計劃在 1998 年開始,其目標是發明一套自由的加密工具,在互聯網上使用。OpenSSL 以 Eric Young 以及 Tim Hudson 兩人開發的 SSLeay 為基礎,隨着兩人前往 RSA 公司任職,SSLeay 在 1998 年 12 月停止開發。因此在 1998 年 12 月,社羣另外分支出 OpenSSL,繼續開發下去。
    圖片
    ▲ 上圖為 Tim HudsonOpenSSL 管理委員會當前由 7 人組成有 13 個開發人員具有提交權限(其中許多人也是 OpenSSL 管理委員會的一部分)。只有兩名全職員工(研究員),其餘的是志願者。該項目每年的預算不到 100 萬美元,主要依靠捐款。 TLS 1.3 的開發由 Akamai 贊助。5.4 下載方法OpenSSL可以從其官網上下載,地址是:https://www.openssl.org/source/,感興趣的讀者可以自行下載安裝研究。

    6、各類證書

    6.1 證書類型操作過證書的朋友可能會對各種證書類型眼花繚亂,典型的體現就是各種不同的證書擴展名上,一般來説會有DER、CRT、CER、PEM這幾種證書的擴展名。
    圖片
    以下是最常見的幾種:1)DER文件:表示證書的內容是用二進制進行編碼的;2)PEM文件:是一個文本文件,其內容是以“ - BEGIN -” 開頭的,Base64編碼的字符;3)CRT和CER文件:基本上是等價的,他們都是證書的擴展,也是文本文件,不同的是CRT通常用在liunx和unix系統中,而CER通常用在windows系統中。並且在windows系統中,CER文件會被MS cryptoAPI命令識別,可以直接顯示導入和/或查看證書內容的對話框;4)KEY文件:主要用來保存PKCS#8標準的公鑰和私鑰。6.2 常用OpenSSL命令下面的命令可以用來查看文本證書內容:openssl x509 -incert.pem -text -nooutopenssl x509 -incert.cer -text -nooutopenssl x509 -incert.crt -text -noout下面的命令可以用來查看二進制證書內容:openssl x509 -incert.der -inform der -text -noout下面是常見的PEM和DER相互轉換。PEM到DER的轉換:openssl x509 -incert.crt -outform der-out cert.derDER到PEM的轉換:openssl x509 -incert.crt -inform der -outform pem -out cert.pem補充説明:上述命令中用到的openssl程序,就是本文中提到的OpenSSL開源庫提供的程序。

    7、Netty中的聊天加密代碼示例

    7.1 關於Netty
    圖片
    Netty是一個Java NIO技術的開源異步事件驅動的網絡編程框架,用於快速開發可維護的高性能協議服務器和客户端,事實上用Java開發IM系統時,Netty是幾乎是首選。有關Netty的介紹我就不囉嗦了,如果不瞭解那就詳讀以下幾篇:《史上最強Java NIO入門:擔心從入門到放棄的,請讀這篇!》《Java的BIO和NIO很難懂?用代碼實踐給你看,再不懂我轉行!》《新手入門:目前為止最透徹的的Netty高性能原理和框架架構解析》《史上最通俗Netty框架入門長文:基本介紹、環境搭建、動手實戰》基它有關Netty的重要資料:Netty-4.1.x 源碼 (在線閲讀版)Netty-4.1.x API文檔 (在線查閲版)7.2 啓動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的方法,這裏取最簡單的一個進行分析:publicstaticSslContextBuilder forServer(File keyCertChainFile, File keyFile) {    returnnewSslContextBuilder(true).keyManager(keyCertChainFile, keyFile);}該方法接收兩個參數:1)keyCertChainFile是一個PEM格式的X.509證書文件;2)keyFile是一個PKCS#8的私鑰文件。熟悉OpenSSL的童鞋應該知道使用openssl命令可以生成私鑰文件和對應的自簽名證書文件。具體openssl的操作可以查看我的其他文章,這裏就不詳細講解了。除了手動創建證書文件和私鑰文件之外,如果是在開發環境中,大家可能希望有一個非常簡單的方法來創建證書和私鑰文件,netty為大家提供了SelfSignedCertificate類。看這個類的名字就是知道它是一個自簽名的證書類,並且會自動將證書文件和私鑰文件生成在系統的temp文件夾中,所以這個類在生產環境中是不推薦使用的。默認情況下該類會使用OpenJDK's X.509來生成證書的私鑰,如果不可以,則使用 Bouncy Castle作為替代。7.3 啓動SSL Client代碼示例同樣的在client中支持SSL也需要創建一個handler。客户端的SslContext創建代碼如下:// 配置 SSL.finalSslContext sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();上面的代碼我們使用了一個InsecureTrustManagerFactory.INSTANCE作為trustManager。什麼是trustManager呢?當客户端和服務器端進行SSL連接的時候,客户端需要驗證服務器端發過來證書的正確性。通常情況下,這個驗證是到CA服務器中進行驗證的,不過這樣需要一個真實的CA證書環境,所以在測試中,我們使用InsecureTrustManagerFactory,這個類會默認接受所有的證書,忽略所有的證書異常。當然:CA服務器也不是必須的,客户端校驗的目的是查看證書中的公鑰和發送方的公鑰是不是一致的,那麼對於不能聯網的環境,或者自簽名的環境中,我們只需要在客户端校驗證書中的指紋是否一致即可。netty中提供了一個FingerprintTrustManagerFactory類,可以對證書中的指紋進行校驗。該類中有個fingerprints數組,用來存儲安全的授權過的指紋信息。通過對比傳入的證書和指紋,如果一致則校驗通過。使用openssl從證書中提取指紋的步驟如下:openssl x509 -fingerprint -sha256 -inmy_certificate.crt

    8、小結一下

    上面我們對Netty聊天用到的加密技術和相關概念進行了梳理,我來簡單這些概念之間的關係。
    這些概念之間的關係,簡單來説就是:

  • 1)PKI:是一套加密體系和標準的合集,它是理論方案;
  • 2)SSL:是利用了PKI理論體系,針對Socket網絡這個場景設計的一套安全通信標準,屬於是PKI的一個具體應用場景;
  • 3)OpenSSL:是PKI體系及SSL標準的算法和代碼實現,它包括了具體的開源代碼、工具程序等;
  • 4)各種證書:是在SSL或其它基於PKI體系的安全協議標準中需要使用的到一些加密憑證文件等。
    而具體到Netty中的聊天加密,那就是應用了上述的PKI體系,基於SSL協議,在OpenSSL等開源庫的幫助下實現的安全程序。

    9、參考資料

    [1] 公鑰基礎設施(PKI)國際標準進展
    [2] 一篇文章讓你徹底弄懂SSL/TLS協議
    [3] 什麼是OpenSSL?它有什麼用途
    [4] OpenSSL是什麼軟件
    [5] netty系列之對聊天進行加密
    [6] 跟着源碼學IM
    [7] 基於Netty,從零開發IM
    [8] TCP/IP詳解(全網唯一在線閲讀版)
    [9] 快速理解TCP協議一篇就夠
    [10] Netty-4.1.x 源碼(在線閲讀版)
    [11] Netty-4.1.x API文檔(在線版)
    (本文已同步發佈於:http://www.52im.net/thread-41...)

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.