1引言
平時開發工作中,我們會經常接觸加密、解密的技術。尤其在今天行動網際網路時代,越來越多的使用者會將資料儲存在雲端,或使用線上的服務處理資訊。這些資料有些涉及使用者的隱私,有些涉及使用者的財產,要是沒有一套的方案來解決使用者的資料安全問題的話,這將是一個多麼可怕的事兒。
同時,我們作為開發者,也會經常遇到使用者對資料安全的需求,當我們碰到了這些需求後如何解決,如何何種方式保證資料安全,哪種方式最有效,這些問題經常困惑著我們。即時通訊網(52im.net)本次著重整理了常見的通訊安全問題和加解密演演算法知識與即時通訊(IM)開發同行們一起分享和學習。
2安全性威脅
一般的,我們在網路中傳輸的資料,都可以認為是存在這潛在的風險的。用一句話來概括就是:「任何在網路中傳輸的明文資料都存在安全性威脅。」
下面就列舉下我們通訊中面臨的四種威脅:
3加密解密演演算法
我們經常說加密解密演演算法是資料安全領域裡的「劍」,是一種主動的防護,對資料進行必要的加密處理,以保證其在資料傳輸、儲存中的安全。
1原理
嚴謹的說,base64並不是加密演演算法,這裡提到他是因為他的實現比較簡單,通過他的實現,我們可以更好的理解加密解密的過程。
下面看下他是如何「加密」的。假設我們要對「BC」字串進行加密。現將其轉換為二進位制表達方式,並連起來:01000010 01000011,接下來對二進位制按6位分組,不夠6位補0,得到010000、100100、001100(最後兩位補0)。下面查表,找到對應的值「QKM」。那麼「QKM」就是「BC」用base64「加密」後的值了。
從上面的base64演演算法,我們可以窺視部分加密的本質:將一段有意義的資訊,通過某種方式,對映為一段看不懂的資訊。使用函數表達即為:
1
public Ciphertext encrypted(Plaintext text);
值得注意的是,base64裡有一張對映表,如果改變對映表的順序,最終得到的結果就會跟著改變。有點類似烹調,在相同原料、相同烹調方式下,我們改變加入的調料,最終做出的東西將會也不一樣。這裡的對映表,我們叫之為「金鑰」。
2小結
通過base64演演算法,可以看出,一個加密演演算法會有兩部分組成:金鑰、演演算法。兩者不能都公開,都公開的話,就可以被人逆向運算,進行解密。一般的,我們將金鑰進行保密,將演演算法進行公開。演演算法的公開,有利於演演算法的推廣,普及,更有利於尋找演演算法中的漏洞。也就是因為base64同時公開了演演算法、金鑰,所以我們說他並不是真正的加密演演算法。當然如果你調整了上面對映表,那麼也能做到加密演演算法的目的,不過base64加密的強度比較差,所以不建議在實際應用中作為加密演演算法使用。
1基本
我們在平時的工作中經常聽到MD5演演算法。比如在一些下載頁面裡會給出一個md5的作為檔案驗證串,在迅雷下載中作為檔案的唯一標識。這類演演算法嚴格上來說也不是加密演演算法,是一種叫做摘要演演算法的演演算法,不過在平時的使用中,我們經常將摘要演演算法混合使用,所以在廣義上來說也可以將他叫為加密演演算法。
2摘要長度
摘要演演算法的特點是可以將任意長度的字串,給轉換為定長的字串。可以意料的是,在這個轉換過程中,一定是一共單向的過程。打個比方,我們將一個256長度的字串轉換為128長度的字串,轉換前有N256種可能,轉換後有N128種可能,這一定不可能是1對1的對應關係。
所以我們只要保證摘要串(轉換後的串)位數只夠的長,使得「給定一個字串A,經過摘要演演算法處理後的串B,很難找到一個字串C,其摘要後的串和串B相同」 即可。所以目前主流的摘要演演算法MD/SHA的摘要串長度都在128位元以上。而正是出於這個原因,美國還對長摘要串的加密演演算法進行了出口的限制。
3通訊模型
摘要演演算法在平時的使用中,經常以如下的形式進行:
假設使用者端需要傳輸一段資訊data給伺服器端,為了data在網路中資料的完整性,或者說防止資訊data被惡意的使用者篡改,可以始終這種安全通訊模型:使用者端與伺服器端實現確定了加密金鑰key,一段任意的字串,使用者端將key與資料data拼接在一起,進行摘要得到摘要串C,將data、C傳給伺服器端,伺服器端得到data和C後,同樣使用與使用者端相同的方法,計算摘要串S,如果S等於C的話,就說明A在傳輸中,沒有被人篡改。
流程如下圖:
對於我們在通訊的面臨的四種威脅,摘要演演算法是否能防範呢:
截獲:由於網路中傳輸的資料依然的明文的,對於攻擊者來說暴露無遺,所以摘要演演算法對於這種威脅,沒什麼辦法。
中斷:摘要演演算法,是對資料的驗證,對整個網路的可用性方面的攻擊,無法防範。
篡改:使用者端發出的資料,中途被攻擊者進行了修改,由於攻擊者並不知道金鑰key,將無法生成正確的摘要串。所以,摘要演演算法可以防範篡改威脅。
偽造:攻擊者偽造成使用者端,給伺服器端發資料,但由於拿不到金鑰key,偽造不出摘要串。所以,在這種情況下,摘要演演算法是有一定的防範作用的。但是,在偽造威脅中,還有一種是重放攻擊,攻擊者事先將使用者端發給伺服器端的包截下來,然後重複傳送。例如:使用者端發給伺服器端密碼時,被攻擊者記錄了下來,當下次,伺服器端再向使用者端詢問密碼時,攻擊者只需將記錄下來的包發給伺服器端即可。所以摘要演演算法對於偽造威脅的防範是不徹底的,其只可以辨別偽造的內容,不能辨別偽造的傳送方。
常見的摘要演演算法有MD5/MD4/SHA-1/SHA-2等,其摘要串長度也不盡相同。現在MD4/MD5/SHA-1等一些摘要串長度128位元的摘要演演算法已不再安全,山東大學的王小波教授已經證明MD4/MD5/SHA-1已經可以快速生成「碰撞」。所以在真正的對安全性要求極高的場所還是使用長摘要串的摘要演演算法來的靠譜一些。
1基本
理論上說對稱加密演演算法,才是我們真正說的加密演演算法。所謂對稱加密演演算法,通俗的講,就是使用金鑰加密,再使用金鑰解密的加密演演算法的總稱。也就是平時我們說到加密演演算法,腦子裡第一個跳出來的加密方式一般都是對稱加密演演算法。上面將的base64其實也是一種「對稱加密演演算法」,只是其金鑰公開了而已。
2通訊模型
同樣的場景:使用者端要將資料data發給伺服器端。使用者端對使用金鑰key,對資料data加密,生成加密串C,通過網路將C傳輸為伺服器端,伺服器端,使用金鑰key對C解密,獲取資料data,做自己的業務邏輯。
簡單直接的一種加密方式,與摘要演演算法不同的地方是,加密過程其是雙向的,C由data加密而來,同樣可以解密獲得data,前提條件是加密解密時的key相同。而摘要演演算法無法從C解密得到data。
加密過程簡單,那麼其在對抗通訊中面臨的四種威脅的作用有怎麼樣呢:
截獲:這麼在網路中傳輸的內容為密文,即使攻擊者截獲了報文,由於沒有金鑰,也無法解析。所以,這次對稱加密演演算法在防範截獲威脅方面有這很大的優勢。
中斷:和摘要演演算法一樣,無法防範。
篡改:由於資料是密文傳輸的,攻擊者,無法解析,更無法偽造了。所以,可以防範。
偽造:對於資料的偽造,和摘要演演算法一樣,可以防範,但對於偽造的傳送方,對稱加密演演算法和摘要演演算法一樣,比較的無力。
3演演算法優缺點
對稱加密演演算法有著很多的好處,比較加密速度快,演演算法簡單,安全模型的安全性較高等,但在正式中使用時,卻不得不解決一個問題:金鑰如何傳遞。如果將金鑰在網路中傳遞,勢必有被截獲的風險。由於這個問題的存在,導致單純的使用對稱加密演演算法的通訊模型,並不是一個通用的模型,只在一些特殊的場合中使用,例如:使用者端/伺服器端為同一端點,或者線下合作的場景——雙方將金鑰寫入合同中,線下傳遞。
不過對於金鑰,還是建議經常的更換,金鑰的破解是一個耗時的過程,長時間不變的金鑰,無遺對攻擊者創造了破解的機會,當有一天攻擊者破解了金鑰,滅頂之災也就來到。
說了這麼多的對稱加密演演算法,還沒有說對稱加密演演算法有哪些,比較常用的對稱加密演演算法有DES/3DES/AES/IDEA/RC4/RC2等。其加密強度,可以從其支援的金鑰長度看出,金鑰越長,加密強度越好;同時,加密過程越慢。
1基本
對稱加密演演算法指加密解密用同一金鑰,那麼非對稱加密就是加密解密用不同的金鑰。加密演演算法一次生成兩個金鑰,一個叫做公鑰,一個較為金鑰。公鑰加密的資料,用金鑰解密;金鑰加密的資料,用公鑰來解密(有些非對稱加密演演算法,只能用金鑰加密,公鑰解密,或只能用金鑰加密,公鑰解密)。
非對稱加密演演算法的確神奇,其理論的基礎來自於數論。例如RSA演演算法建立在數論中的「大數分解和素數檢測」的理論基礎上。而ElGamal和ECC演演算法基於的則是數論中的「離散對數問題」。數學中的最後一個未找到應用場景的分支學科——數論,終於在加密學領域,找到了應用場景,這不得不說是個奇蹟。
非對稱加密演演算法的加入,使得加密演演算法得以真正的完整,他有這舉足輕重的作用。他很好的解決了對稱加密演演算法的缺陷。
2通訊模型
使用者端要將資料data傳送給伺服器端,使用者端向伺服器端發起對話請求,伺服器端生成一對金鑰——公鑰Gkey和私鑰Skey。將Gkey傳送給使用者端,使用者端使用Gkey對資料data進行加密,獲得密文C,將C發給伺服器端,伺服器端使用自己的Skey解密,獲得資料data,完成後續業務邏輯。
從上面的通訊模型中可以看到,在網路中傳輸的只有密文C、和公鑰Gkey。而私鑰Skey不會在網路中傳輸,攻擊者只能獲取到公鑰,無法對解密密文C,也就保證了資料的安全性。詳細的分析下通訊中面臨的四種威脅:
截獲:同樣網路中傳輸的是密文,即時被截獲,攻擊者沒有私鑰,也無法解析密文。所以可以很好的防範截獲威脅。
中斷:對於針對可用性的攻擊,由於一般都是基於底層協定的攻擊,所以一般很難防範。
篡改:由於資料是密文傳輸的,攻擊者沒有私鑰,無法解析,更無法偽造了。
偽造:對於資料的偽造,和摘要演演算法一樣,可以防範,但對於偽造的傳送方,對稱加密演演算法和摘要演演算法一樣,比較的無力。
和對稱加密演演算法一樣,只能對通訊中的截獲、篡改有防範作用,對其他兩個中斷、偽造威脅都無法防範。而由於非對稱加密演演算法,很好的解決了對稱加密演演算法中金鑰交換的問題,所以其有著很不錯的應用場景,可以說是一種通用的加密模型。
3演演算法優缺點
那麼非對稱加密演演算法就沒有缺點嗎?也不是,首先,我們看上面的通訊模型,他比對稱加密演演算法的通訊模型來的複雜,存在著兩次請求/響應。此外,非對稱加密演演算法的計算可能會很慢,比對稱加密演演算法來慢得多。所以,非對稱加密演演算法在解決了對稱加密演演算法的缺陷後,存在著一些效能問題,比較通用的解決辦法是將兩種加密演演算法進行結合——先使用非對稱加密演演算法傳遞臨時的對稱加密演演算法的金鑰,金鑰傳遞完成後,再使用更快的對稱加密演演算法來進行真正的資料通訊。
典型的非對稱加密演演算法有RSA/ElGamal/ECC演演算法,除了這兩個演演算法外,還有一個DH演演算法,其比較的另類,其設計的初衷就是解決對稱加密演演算法中金鑰安全交換的問題。其通訊模型如下:
所有使用者端生成一堆公鑰CGkey和私鑰CSkey,將AGkey發給伺服器端。伺服器端通過AGkey生成伺服器端的公鑰SGkey和私鑰SSkey,並將SGkey發還給使用者端。使用者端通過CSkey與SGkey生成對稱加密演演算法的金鑰key,伺服器端通過CGkey和SSkey生成相同的金鑰key。後續使用者端和伺服器端都是用各自的金鑰key來通訊。
不得不說,這又是一個多麼神奇的演演算法。但是他的確存在。並且早於其他的非對稱加密演演算法。
1基本
以上三種演演算法都有防篡改的功能,但摘要演演算法、和對稱加密演演算法若要防篡改,則需要交換金鑰,這又是一件麻煩事兒。所以一般在單純的防篡改的需求上,都是使用非對稱加密演演算法。但若是對整個明文進行加密的話,加密過程勢必消耗大量時間,所以就誕生了數位簽章。
數位簽章,本質上就是非對稱加密演演算法,但出於解密執行效率的考慮,並是不對明文進行加密,而是對明文的摘要加密,生成「數位串」,並將「數位串」附在明文之後。
數位簽章實際上是非對稱加密演演算法的一個妥協方案,為了提高加解密的效率,捨棄了非對稱加密演演算法對截獲威脅的優勢。
2通訊模型
先來看非對稱加密演演算法的第一種通訊模型,由使用者端生成一堆金鑰——公鑰Gkey和私鑰Skey,並使用Skey對明文data進行加密,獲得密文C。將C與Gkey傳送給伺服器端,伺服器端使用Gkey對C進行解密。
這種通訊模型,只需要一次請求/響應過程,但卻無法防範截獲威脅,由於最後的密文C的解密用的是公鑰Gkey,而Gkey在通過網路傳遞,所以攻擊者可以很方便的對資料進行截獲、解密,獲得明文data。但這種通訊模型,對於數位簽章的場景正合適,數位簽章的場景並不準備防範「截獲」威脅。
那麼下面來看下完整的數位簽章的通訊模型:伺服器端生成一堆金鑰,公鑰Gkey和私鑰Skey,在將明文data進行摘要,獲得摘要串Z1,使用私鑰對Z1加密,獲得密文C,將C,data,Gkey發給伺服器端,伺服器端使用Gkey解密後獲得Z1,重新根據data計算出摘要Z2,通過比較Z1是否等於Z2來判斷資料是否被篡改。
以上的模型主要由兩個步驟組成,摘要與非對稱加密演演算法的應用。平常我們經常用到的簽名演演算法,也是這兩種演演算法的組合,比如:SHA1wthRSA,使用SHA1來做摘要,RSA做未對稱加密;MD5withRSA,使用MD5做摘要演演算法,RSA做未對稱加密;SHA1withDSA,DSA是ElGamal演演算法的一種改進。
1基本
上面說了這麼多演演算法,又是摘要演演算法,又是對稱加密演演算法,又是非對稱加密演演算法的。但是對於通訊中的四種威脅——截獲、中斷、篡改、偽造最多也就只能解決其中的兩個,對於中斷、和偽造威脅,只能乾瞪眼。難道,就沒有其他辦法了嗎。
對於中斷,一般是網路拓撲或協定級別要解決的問題,已經超出了我們的範疇,暫時不表,我們只能做到的是當網路不可用時,傳輸的資料出現丟包或異常時可以進行及時的建設,這裡就需要用到資料完整性的驗證了。
至於,要對付攻擊者「偽造」的威脅,這不僅僅是單一演演算法層面可以解決的問題了。
2通訊模型
正如上面幾節所說,偽造分為兩種,一種是資料偽造,只要做好防篡改的工作,資料偽造都可以很好的防範。另外一種是偽裝成某一網站,與使用者進行互動,盜取使用者的一些信。比較常見的如釣魚網站、黑代理伺服器等。
哪非對稱加密演演算法的通訊模型來舉個例子。使用者端A在獲得給自己公鑰時,並沒有懷疑與公鑰發出方的身份,使用者端A以為發給他的依然B,實際上,B發出的公鑰已經被攻擊者C攔截並丟棄了,C重新生成公鑰偽裝為B發給了使用者端,後續的流程實際上都是攻擊者C在於使用者端A通訊,而使用者端A則以為與自己通訊的是伺服器B。
這個偽造的過程在平時我們的生活中也經常會碰見,比如:在實名制以前,張三買到火車票後,半路被人打劫,車票被搶。這就有點類似於遭遇了攻擊者的攻擊,攻擊者搶走了張三的火車票(公鑰Gkey),並偽造了一張可以以將亂真的車票,(重新生成公鑰Gkey’)使用這張車票上火車。整個過程看似天衣無縫,攻擊者獲得了一張免費的車票,張三損失了一張火車票。
當然,現在這種火車票qiang劫的事件已經不太會發生了,因為已經實行了實名制。實名制的引入,給我們解決上面的「偽造」威脅提供了一個方案。火車票實名制,使用了身份證作為驗證使用者身份的一個證明。那麼我們在網路通訊中是否也可以引入這麼個「網站身份證」呢。回答是肯定的,目前也正是這麼做的,我們叫他「數位憑證」。
3CA
正如我們身份證是由可信任的公安局辦發。數位憑證也是由權威機構簽發,我們叫做CA,CA會保證證書的確是發給了應該得到該證書的的人。CA也屬於一個機構,他也有被人偽造的風險。所以CA一般是分級的,頂層的叫做RootCA,由他保證下面的CA的身份。
所以我們的機器裡,儲存著有限的幾個RootCA的機構的公鑰。打個比方,張三有個數位憑證,是由A這個CA機構頒發的,A的身份由RootCA來保證。當瀏覽器與張三的網站進行通訊時,獲取到了張三的數位憑證,實際上這個數位憑證是個巢狀的證書,裡面包含著兩個子證書:RootCA頒發給A的證書,和A頒發給張三網站的證書。在瀏覽器中儲存著有限個著RootCA的公鑰。使用RootCa的公鑰對A證書進行驗證,驗證通過,使用A證書裡的公鑰對張三網站的證書進行驗證,只有再次驗證通過後,才能說張三網站的證書得到了確認。
整個驗證過程是一個信任鏈。
數位憑證裡主要包含著兩樣東西:數位憑證所有者的身份資訊,數位憑證所有者的公鑰。為了保證證書在網路中通訊不被篡改,證書裡會帶上這些資訊的數位簽章。那麼對數位憑證的驗證就是對數位簽章的驗證,這就是上圖中每次證書的驗證都要使用到公鑰的原因了。
另外還有一些關於c++ Linux後臺伺服器開發的一些知識點分享:Linux,Nginx,MySQL,Redis,P2P,K8S,Docker,TCP/IP,協程,DPDK,webrtc,音視訊等等視訊。
需要的朋友可以VX關注零聲學院領取