標籤:

網路安全初探

網路安全初探

寫在最前面

本文最初發佈於我的blog上,因為知乎文章字數限制,刪除了一些內容,本文主要從應用視角探討網路加密、數據真實性驗證,終端身份認證技術。由於本人水平有限,有不正確的地方,歡迎批評指正,最後原創不易,轉載請註明出處。

網路安全技術簡介

為什麼需要網路安全技術?

互聯網最初的設想,是讓一部分人共享一個局部網路,而使用者均是可信賴的人,因此網路在設計之初,並沒有考慮到安全方面的問題。隨著網際網路技術的發展,現在幾乎將整個世界互聯在了一起,任何一端發送數據包,均要經過很多不可信賴的網路,而在通過這些網路的過程中,數據包可能被截獲、篡改,甚至是偽造。為了應對這種問題,我們需要一種技術,做到數據加密後不可破解(Confidentiality),辨別數據是否被篡改(Message Integrity),發送者、接受者身份不可被偽造(End-point Authentication)。這種技術,就是本文要探討的網路安全技術。

什麼是網路加密?

假設網路上,有兩個以上的人,通過一個通信軟體進行信息交換,那麼他們輸入的即將用於傳輸的數據,被稱之為明文(cleartext or plaintext),通過某種加密演算法e(x)運算後,

得到密文(ciphertext),密文在網路中傳輸,到達對端後通過解密函數d(x)獲得明文,於是就完成了整個加密解密的過程。也就是說,假設數據為m,加密函數為e(x),解密函數為d(x),密文為c,則有

  • 發送方輸入要發送的數據m
  • 發送方將數據m通過加密函數,e(x)對m進行加密,則有c = e(m)
  • 發送方將加密數據發送到網路
  • 接收方收到密文c
  • 接收方通過解密函數d(x)解密密文c,則有m = d( c )

上述流程,闡述了網路加密解密的基本流程,為了使整個流程更易於理解,現在假設m為"hello world"字元串,e(x)則是將m的ASCII碼加1後輸出密文c,然後將密文c傳輸給對端,

對端通過解密函數d(x)將c內的ASCII碼全部減一後,就能得到明文m,於是有:

  • 輸入m = "hello world"
  • 使用e(x)加密m,得到c = "ifmmp!xpsme",並將c通過網路傳輸給對端
  • 對端接收到加密數據c以後,通過解密函數d(x),將c中每一個字元的ASCII值減1,得到原文m,即m = d( c )

上述的例子,簡述了簡要的加密解密流程,當然舉例用的加密演算法也過於簡單,不過這裡的目的是給出一個概要說明,給讀者梳理加密和解密流程的基本概念。後面我們將以應用層使用的視角,討論一下加密演算法。

什麼是數據真實性驗證?

如果網路上,兩個正在通訊的實體A和B,正在進行數據通信,當A發送數據給B時,數據可能被中間人截獲,並篡改後再發送給B。舉一個Top-Down這本書上的例子,假如A發送信息"I love you"給B,此時信息被C截獲,修改為I dont love you後,再發給B,那麼B此時無法辨別該信息是否真的由A發送。因此這裡需要一種驗證機制來驗證數據是否被篡改。要達到這個目標,我們一般使用一種專門用於hash值計算的hash函數,不同的數據通過hash函數計算,能夠(極大概率)獲得不同的hash值,因此當傳輸中的數據被改變時,那麼新計算的hash值則(極大概率)不同於原來的值,因此可以辨別數據是否被篡改。於是數據傳輸流程就變成了如下步驟

  • A輸入數據m
  • A通過函數h(x),計算得到m = h(m)
  • A將輸入數據和hash值,放入原數據的尾部,得到(m, h(m))並將數據發送給B
  • B收到數據(m, h(m))後,通過h(x)計算數據m,得到h(m),並將h(m)和h(m)進行對比,如果相等,則說明數據未被篡改,否則數據被篡改

上述例子,展示了進行數據真實性驗證的流程,然而它的弱點也是非常明顯的,假設有一個監聽者C,冒充A發送一個數據m,並且m在中途沒有被修改,那麼當B收到數據時,按上述步驟去驗證,是無法驗證出哪裡不對勁的,因此,我們在進行hash運算的時候,需要雙方共同約定一個secret值,在進行hash值計算時,需要將數據m和secret s一起放入到hash函數內,計算hash值,這個值被稱之為MAC(message authentication code)[1],因為這個secret是A和B雙方共同約定的一個值,因此監聽者C很難冒充A,發送一個數據包給B,於是流程則變為如下所示的步驟:

  • A輸入數據m
  • A通過函數h(x)和secret s,計算hash值h(m + s)
  • A將hash值,插入數據m的尾部,得到(m, h(m + s))
  • A將該數據發送給B
  • B收到數據後,通過將數據m和共同約定的s,計算hash值h(m + s)
  • 對比h(m + s)和h(m + s),如果相等,則表示數據未被篡改,否則表示數據被篡改

上述例子,不僅給出了檢驗數據是否被篡改的方案,也給出了終端身份認證的一種方案,hash計算,是一種密碼學技術,但不是一種加密技術。

什麼是終端身份認證?

終端身份認證,本質就是通信雙方,要確保通信對象是其本人,而非冒充的。終端認證的方式有很多種,如上節所示的那樣,通信雙方共同約定一個secret,那麼接受的一方很容易驗證數據是否偽造的。在使用對稱加密的通信中,雙方一樣要約定一個key值,只要key不被泄漏,數據很難被破解以及偽造,也達到了認證的效果,為了提升通信的安全性,一般先將要發送的數據,通過hash函數計算出hash值後,再加密發給對方,這樣就同時達到了數據不可被破解、數據認證和身份認證三個目的。在使用非對稱加密的情形中,我們首先要驗證對方的public key,也就是去第三方機構驗證public key是否其本人,以達到身份認證的目的。

加密(Encryption)和哈希(Hashing)的區別

加密在維基百科裡的定義如下所示[2]:

In cryptography, encryption is the process of encoding a message or information in such a way that only authorized parties can access it and those who are not authorized cannot. Encryption does not itself prevent interference, but denies the intelligible content to a would-be interceptor. In an encryption scheme, the intended information or message, referred to as plaintext, is encrypted using an encryption algorithm – a cipher – generating ciphertext that can be read only if decrypted. For technical reasons, an encryption scheme usually uses a pseudo-random encryption key generated by an algorithm. It is in principle possible to decrypt the message without possessing the key, but, for a well-designed encryption scheme, considerable computational resources and skills are required. An authorized recipient can easily decrypt the message with the key provided by the originator to recipients but not to unauthorized users.

加密的本質,就是將信息轉換為一段不易閱讀的字元,加密後數據的長度是任意的,它要求只有被認證的一方才能夠將密文解密,並獲得原文,其他人無法獲取原文信息。加密演算法有兩種,一種是對稱加密,即收發雙方都擁有一個共同的key(即加密和解密都用同一個key)擁有key的一方則是被認證的一方。另一種則是非對稱加密,這種方式將會有一個key對,一個公鑰和一個私鑰,公鑰可以在網路上傳輸,並且通過公鑰加密,只有私鑰才能解密,加密後的密文可以還原。加密技術,是防止他人竊取要通過網路傳輸的機密信息的一種有效手段。

圖1 加密和解密流程

哈希函數,引用securityinnovationeurope.com內的一段定義[3]:

A hash is a string or number generated from a string of text. The resulting string or number is a fixed length, and will vary widely with small variations in input. The best hashing algorithms are designed so that its impossible to turn a hash back into its original string.

密碼學中的哈希函數,是通過一串文本字元,將其生成固定長度的字元串或者整數值,當輸入的內容發生輕微的變化時,他的結果也往往大相徑庭,而且與加密不同的是,經過hash函數計算的字元串,幾乎不可能還原成原來的字元。哈希函數,一般應用在數據真實性的驗證上,而不是保證數據不會被破解。

圖2 任何字元進行hash計算,都會變成固定長度的一組字元串或數值

儘管hasing和encryption有諸多相似之處,他們終究不是一個東西,首先第一點區別是,加密後的密文的長度是不定的,而hash值則一定是相同長度的。第二點是,加密後的密文是可以還原的,而經過hash函數計算後的hash值,是不能被還原的。最後一點,也是最重要的一點,則是用途上不同,加密技術,是為了保證第三方無法獲得密文的原文,而hash函數,則是為了保證數據的真實性可以得到驗證。

網路加密技術

上一節,我們對網路安全的加密、認證機制,作了簡要的概述,接下來我們將會深入這幾個方面進行論述,本節主要集中在探討加密演算法。本節我們會先探討傳統的加密方式,然後再探討現代加密演算法,包括對稱加密和非對稱加密。

傳統的網路加密方式

這一小節,展示的加密演算法,其實在當今看來,其實並不安全,但也算的上是加密技術的起源思想,闡述這些內容,有助於我們理解什麼是加密。

字母偏移

假設我們的明文,只是包含a-z這26個字母,那麼本段將展示的加密演算法,則是基於本字母,向後偏移N位(假設N=5),那麼,對應關係則有:

|

---|---

原來的字母 | a b c d e f g h i j k l m n o p q r s t u v w x y z

加密後的字母 | f g h i j k l m n o p q r s t u v w x y z a b c d e

表1

此時,加密和解密都遵循這一張表的對應關係,對於加密函數e(x)和解密函數d(x)而言,對所有處於a-z範圍內的明文,每個字母都會在上表中找到對應的字母。現在假設網路上A和B兩個人進行通信,他們交換的信息只包含a-z的字母,於是有:

  • A輸入明文m = "i love you"
  • 在A發送信息給B前,先通過查找表1,計算e(m) = m,則m = "n qtaj dtz"
  • A將加密後的m通過網路發送給B
  • B接收到m後,通過解密函數d(x),計算得到d(m) = i love you = m

上面的論述,展示了最原始和最簡單的加密演算法,僅僅只是通過偏移字母來進行加密,加密函數e(x)和解密函數d(x)一樣,都是通過查找表1中的對應關係,來進行加密和解密的,唯一的區別則是,加密時,e(x)通過原來的字母,作為key查找加密後的字母。而解密函數d(x)則是以,加密後的字母為key,查找原來的字母。不論N是多少,這種方式都是相當不安全的,因為除了原來的字母排列,我們只需要再試25次,就能夠找到N的值到底是多少,找出N到底是多少,甚至可以通過人工來排列,也不會花費太多的時間。

生成亂序字母表

為了進一步加強加密演算法的安全性,這裡將討論一種比上面一種稍微更複雜一點的演算法,所謂更複雜,其實就是要增加更多的可能性(上述演算法包括原字母排列,也只有26種可能性),其核心思想仍然是生成一張字母映射表,加密函數和解密函數,仍然和上一小節討論的那樣,查詢該表進行加密和解密。但是不同於上面的做法,每一個字母都是偏移固定的位數,這種演算法是:

  • 先從26個字母中,隨機一個字母對應a
  • 然後再從剩餘的25個字母中,隨機一個對應b
  • 然後再從剩餘的24個字母中,隨機一個對應c
  • 依次類推直至每一個字母,都有唯一的一個經過隨機篩選的字母與之對應,並且是一一對應

於是我們可以得出類似下表的映射關係

|

---|---

原字母表| a b c d e f g h i j k l m n o p q r s t u v w x y z

C1 | s e l j u q g h m t r p f d x v i b o k z w a n y c

C2 | s c x q f p l m t y b g z h a u w d v i n o j k e r

C3 | s r w d i v n t f h x g p c k b o m z u a q l j e y

C4 | v z k t h q u d e a m g j y r s c p x n w i l b o f

C5 | k y t w c o u f m l e r j a q b s d v x i h z n p g

... | ...

表2

如上表所示,原字母表,可以生成一個隨機的亂序的字母表與之對應,每個字母,都有唯一的一個字母與之對應,而不會重複對應。因此他有26!=403291461126605635584000000種可能性,現在看來,這種方式比前一種方式要安全的多,起碼從人工角度來看,在有限時間內破解加密消息是極為困難的。現在假設隨機生成的映射表是C1,網路上要進行通訊的兩個實體A和B共享這個C1表,於是有:

  • A輸入明文m = i love you
  • A通過加密函數e(x)計算密文,通過查詢原字母表和C1的映射關係,則有e(m) = m pxwu yxz = m
  • A將密文發送給B
  • B收到m後,使用解密函數d(x),通過查詢原字母表與C1的映射關係,可以將m還原為m,於是整個加密解密流程完成

從上述流程來看,和我們上面介紹的加密和解密演算法完全一致,只是映射表生成的方式改變了,然而就是這微小的改變,卻顯著增加了破解的難度。而之所以破解難度顯著上升,是由於組合可能性的以萬億億億億倍的級別的增加為基礎的,也就是說可能性越多,即便加密解密演算法相同,也會增加破解難度。

多張亂序字母表,按一定順序加密

除了上節論述的加密方式,還有一種更加改進的加密方式,就是如表2所示,生成多張不相等的亂序字母表C1~C5,然後生成一個key,key的值為C1~C5的隨機組合數組,如{ C2, C1, C5, C4, C3, },則在加密的時候,每個字母按照順序,先後按照順序,找到對應的亂序表,查找對應的輸出字元,如此循環往複。本質就是,要採用哪個表來替換,該邏輯也很簡單,假設字母在原文中所處的位置為index,etbl_index為key數組的下標,於是有:

當index % len(key)不為0時:etbl_index = index % len(key)當index % len(key)為0時etbl_index = len(key)

比如明文i love you中,i為第1個字母,那麼key列表下標則為1 % 5 = 1,那麼它的字母替換表則是key[1],也就是C2;l為第2個字母,則它所採用的字母表下標為2 % 5 = 2,那麼它的字母替換表則是key[2]也就是C1;依此類推,o、v、e、y、o和u,分別是第3、4、5、6、7和8個字母,因此他們對應的key列表下標分別是3、4、5、1、2、3,在key列表找,則是C5、C4、C3、C1、C2和C3。

解密的時候,也按照該順序表,找到對應的字元進行解密,還原原文。現在假設網路上兩個通信實體A和B進行加密通信,他們共享如表2所示的亂序字母表(包含原字母表和C1~C5),使用key = { C2, C1, C5, C4, C3, },則有:

  • A輸入明文m = "i love you"
  • A將明文m通過e(x)加密函數進行加密,並且輸入key,於是有e(m, key) = m = "t pqii exi"
  • A將密文m通過網路發送給B
  • B收到密文後,通過輸入密文m和key給解密函數,於是有d(m, key) = m = i love you

這種加密方式已經引入了key的概念了,儘管這種方式已經極大提升了安全性,但是在當今的計算機世界中,破解上述的方式仍然不是一件非常困難的事情,不過這裡強化了加密的基本概念,後面我們會繼續探討被廣泛使用的加密演算法,包括對稱加密和非對稱加密。

現代加密方式

基於block加密

上節,我們介紹了通過生成亂序字母表的方式進行加密和解密處理,但是這種方式有一個問題,就是無法通過統一的亂序表,對世界上各種語言進行加密和解密,這樣的話就需要為每一種語言生成一個亂序表,這並不是一件很高效的事情。由於我們所有輸入計算機的文字和數據信息,都是以二進位的形式表示,如果我們的加密演算法是針對bit位,而不是文字本身,那麼就可以無視信息是何種語言。這種方式就是我們要討論的,基於block的加密。

我們要進行加密和解密的信息,以若干位為一個block,最簡單的加密方式,仍然是為每一個block生成一個亂序表。block的bit位越多,其組合也越多,破解難度也越大,但是這種方式佔用的內存也越多。現在我們假設一個block為3個bit位,此時,我們為二進位數值000從000~111隨機一個值,作為其替換的數值;然後為001從剩下的7個數值中隨機一個,作為其替換值;接著為002從剩下的6個中隨機一個,依次類推,我們可以得到類似表3的映射關係。

輸入 | 輸出

---|---

000 | 110

001 | 111

010 | 101

011 | 100

100 | 011

101 | 010

110 | 000

111 | 001

表3

通過上表,我們可以知道每一個block都有一個唯一的從二進位數值000~111範圍內的值與之對應,因此所有的組合一共是(2^3)! = 8! = 40320種組合。雖然以3bit為單位的block,破解它是輕而易舉的事情,如果block以64bit為單位,那麼破解難度會比以3bit為block的難度要高,一共有(2^64)!種組合,但是同時生成亂序表所消耗的時間,和加密解密時,佔用內存也是相當驚人的,它大約佔用2^64 * 8 = 128EB,我想未來10年內,這麼龐大的內存可能都無法普及。當今在世界範圍內廣泛使用的加密解密演算法(如AES演算法),並非以此種方式做簡單替換,而是將block直接與key作xor運算[4]。

對稱加密

上一節,我們介紹了基於block加密的一些思路,並且引進了前面章節討論通過替換的方式進行加密的方法。但這也遇到了一些問題,如果block太長,內存佔用就過大,如果block太短,那麼又容易破解,為了應對日趨嚴峻的網路完全局勢,通過秘鑰(secret key)加密的方式應運而生。目前通過秘鑰加密的演算法主要有兩種,一種是對稱加密,還有一種則是非對稱加密。本節主要介紹對稱加密,並在下一節介紹非對稱加密。

對稱加密概述

對稱加密的本質,就是通信雙方使用相同的加密和解密演算法,相同的秘鑰,進行加密和解密。假設通信雙方A和B的加密函數為e(x),解密函數為d(x),秘鑰為k,明文為m,密文為c,則有:

  • 發送方A輸入明文m
  • 發送方A通過加密函數e(x)和秘鑰k,加密m,於是有e(m, k) = c
  • 發送方將密文c發送給接收方B
  • 接收方B通過解密函數d(x)和秘鑰k,解密c,於是有d(c, k) = m

圖3

現在我們知道了,明文要通過秘鑰進行加密,那麼如何在不藉助亂序表替換的方式,進行加密和解密運算呢?實際上,現今在世界範圍內常用的對稱加密演算法,廣泛使用key和數據block進行xor[5]運算進行加密和解密的。我們來看一個最簡單的例子,假設明文數據的16進位表示為0x1234;key為0x5678;數據block和key均為16位,最簡單粗暴的加密方式就是明文直接和key進行xor運算[6],則有:

十六進位值 | 二進位值

--- | ---

0x1234 | 0001001000110100

0x5678 | 0101011001111000

xor結果| 0100010001001100

表4

數據通過和key進行xor運算,得到加密數據的十六進位表示為0x444C,現在我們將加密後的數據,和key值做xor運算,則有:

十六進位值 | 二進位值

--- | ---

0x444c | 0100010001001100

0x5678 | 0101011001111000

xor結果| 0001001000110100

表5

如上所示,密文通過和key進行xor運算後得到的十六進位為0x1234,得到原文,通過上述的例子,這裡想引出一個結論,則是明文通過和key進行xor運算,得到的密文能夠通過與key進行xor運算拿回明文。

通過上述的方式,我們確實可以得到一個簡單的加密和解密演算法,但是這種演算法並不安全,我們有很多手段獲得密文和明文的關係,如某些常用詞如ing,ed,ty等後綴入手,通過統計的方式查找明文與密文的關係,最終可以達到部分甚至全部破解key的效果,為了應對這種情況,當今通常會先對數據拆分block,然後加密會進行多輪,每輪從原始的key中派生一個roundkey出來,和每一個數據block進行xor運算,最後將密文發送給通信的另一方,另一方接收到以後,也會根據原始的key派生出roundkey,進行xor運算,並執行和加密一樣多輪的次數,最後獲得原文。在這方面,做的最好的則是AES演算法,它不僅僅只是為每一輪加密和解密生成一個roundkey,還進行了其他操作,這裡不對具體的對稱加密演算法,做詳介紹,讀者可以參照Advanced Encryption Standard (AES) Algorithm to Encrypt and Decrypt Data 了解更多關於AES演算法的信息。

對稱加密的弱點

對稱加密演算法,有速度上的優勢,但是它的安全是依賴於通信雙方已經擁有同一個秘鑰的基礎上,而當兩個從未通信過的兩端,如何去同步這個雙方共同使用的key呢?從目前的手段來看,通信雙方只能通過如線下交換的方式,獲得通信的秘鑰,但是在互聯網上,雙方在不可能碰面的情況下,通信雙方就無法安全地同步秘鑰給對方。為了解決這個問題,我們需要用到非對稱加密,即公鑰加密,私鑰解密,公鑰可以在網路中被所有人知道,而私鑰需要接收方保存好。公鑰加密的密文只能通過私鑰進行解密。下一節我們將探討非對稱加密演算法。

非對稱加密

非對稱加密概述

上一節,我們討論了對稱加密,並且也闡述了對稱加密的弱點,就是key無法在網路上安全地同步,為了解決這個問題,於是非對稱加密演算法被發明出來。非對稱加密,每個用戶會在通信前,生成一個秘鑰對,公鑰和私鑰,其中公鑰負責加密,而私鑰負責解密。公鑰可以在公網上傳輸,可以被任何人截獲,私鑰需要所有者自己保存,並且不能外泄。現在假設通信雙方A和B需要進行信息交換,公鑰為K+,私鑰為K-,加密函數為e(x),解密函數為d(x),明文數據為m,密文數據為c,於是有:

  • 發送端A向接收方B請求B的公鑰K+
  • 發送端A獲得接受方B的公鑰K+
  • 發送端A輸入明文m
  • 發送端A通過加密函數e(x)和K+加密明文m,於是有e(m, K+) = c
  • 發送端A將密文c發送給接收方B
  • 接收方獲得密文c,通過解密函數d(x)和私鑰K-,對c進行解密,於是有d(c, K-) = m

圖4

非對稱加密原理:以RSA演算法為例[7]

當前世界範圍內,使用最多的非對稱加密演算法則是RSA演算法,本節我們將會詳細討論RSA演算法的一些基本原理。

(1) RSA演算法流程

  • 生成兩個大質數p和q,且p和q不相等,p和q不可外泄
  • 令n = pq,z = (p-1)(q-1)
  • 選擇一個數值e,令e < n,且gcd(e, z) = 1 (gcd意為greatest common divisor最大公約數),則(n, e)為公鑰的組成部分
  • 選擇一個數值d,令ed mod z = 1,則(n, d)為私鑰的組成部分
  • 現在發送端A,輸入一段信息,並以十進位值m表示它,並且m < n(任何字元在計算機中,都以二進位數值表示,而二進位信息可以被表示為任何信息)
  • 發送端A對m進行加密,則有m^e mod n = c
  • 發送端A將密文c發送給接收方B,接收方B收到密文c後,通過私鑰進行解密,則有c^d mod n = m,將數據還原

上面流程,闡述了RSA演算法的的基本流程,現在們通過一個實例來直觀感受一下,藉助《Computer Networking A Top-Down Approach》第8章中的例子,假設p = 5,q = 7,則有:

  • 令p = 5,q = 7
  • 則有n = pq = 5 * 7 = 35,z = (p - 1)(q - 1) = (5 -1)(7 - 1) = 4 * 6 = 24
  • 令e = 5,因為gcd(e, z) = gcd(5, 24) = 1,且e < n,因此e滿足條件
  • 令d = 29,因為e * d mod z = 145 mod 24 = 1,因此d也滿足條件
  • 輸入字元!,!的ASCII碼為33(注意33 < n),使用公鑰(n, e)加密則有33^5 mod 35 = 3
  • 然後對私鑰對密文進行解密,則有3^29 mod 35 = 33

經過一輪的加密和解密,我們居然通過上述方式,完整將一個字元加密,並且解密還原,但是RSA演算法為何能夠運作?現在我們來深入探討一下。

(2) RSA演算法推導

要證明上面展示的例子,具有一般性,那麼就必須證明m^ed mod n = m mod n。

首先我們還要承認幾個公理,他們分別是:

[(a mod n) + (b mod n)] mod n = (a + b) mod n [(a mod n) – (b mod n)] mod n = (a – b) mod n [(a mod n) ? (b mod n)] mod n = (a ? b) mod n (a mod n)^d mod n = a^d mod n

以下是證明流程(更豐富的證明,請參閱[9]):

  • 我們對數值m進行加密,則有m^e mod n,此時再對密文解密,則有(m^e mod n)^d mod n,該式可以表示為m^ed mod n
  • 根據費馬小定理[8],如果p是質數,並且a不能被p整除,則有a^(p-1) mod p = 1 mod p
  • 由於ed mod z = 1,則ed可以表示為k * z + 1(k為正整數)
  • 於是m^ed mod p = (m ^ (k * z + 1)) mod p = ([m ^ k(p-1)(q-1)] * m) mod p = ([(m ^ k(p-1)(q-1)) mod p] * (m mod p)) mod p
  • 令x = m ^ (p - 1),則有(x^k(q-1)) mod p = ((x mod p)^k(q-1)) mod p = ((m^(p-1) mod p)^k(q-1)) mod p,因為p為質數,m一定不被p整除(2 =< m < pq),根據費馬小定理於是有(m^(p-1) mod p)^k(q-1)為1,於是有[(m ^ k(p-1)(q-1)) mod p] = 1,因此m^ed mod p = (m mod p) mod p = m mod p
  • 同理可證m^ed mod q = m mod q
  • 根據中國剩餘理論,可以得到m^ed mod pq = m mod pq

上面簡要論證了RSA演算法的一般性,後面我們來看看非對稱加密的幾個實際應用領域。

使用領域

(1) 安全加密

前面的章節,已經介紹了關於非對稱加密的操作流程,和公式推導,非對稱加密最重要的應用領域,就是數據的加密和解密。現在假設A和B進行通信,首先他們要將自己的公鑰傳給對方,然後通過對方的公鑰加密數據,並將密文信息傳給對方,對方通過自己的私鑰解密。雖然非對稱加密是非常安全的,但是它也非常耗費性能,加密和解密需要耗費相當多的時間,因此,這種情況下,人們更傾向於將非對稱加密和對稱加密結合的方式,進行信息的加密和解密。如A和B先交換各自的公鑰,然後其中一方,通過對方的公鑰加密對稱加密使用的秘鑰,並傳輸給對方,對方收到後,就直接使用對稱加密的秘鑰,進行信息的加密和解密,這種方式,既解決了對稱加密,秘鑰交換不安全的問題,也解決了非對稱加密過於耗費性能的問題。

(2) public key認證

我們在使用網站進行購物的時候,或者登陸平台的時候,往往要輸入賬戶名和密碼,而如果不對這些信息進行加密,那麼賬戶名和密碼將會被截獲,給用戶帶來不可挽回的損失。為了解決這個問題,用戶首先要從訪問的網站上下載一個公鑰,然後通過public key加密自己的賬號和密碼,傳給網站,然後網站校驗後允許用戶登錄,享有賬號相關的服務。由於網站公鑰,只有站點自己擁有的私鑰才能解密,因此,賬戶和密碼的消息即便被中間人截獲,也難以破解。

但是,即便如此,用戶的賬戶和密碼也不是絕對安全的,因為,中間人可以偽造一個和用戶所要訪問的網站,高度相似的假站點,然後提供自己的公鑰給用戶,用戶使用假站點的公鑰對自己的賬號和密碼進行加密,中間人截獲信息後,因為對方用的是自己的公鑰,因此可以用自己擁有的私鑰對其進行解密,從而獲得用戶的賬號和密碼。這種也是一種中間人攻擊的方式。

為了避免這種情況的發生,一些為機構背書的權威機構,提供了公鑰認證服務,一個站點需要將自己的機構id和公鑰,提供給認證機構,認證機構會記錄其id和公鑰,並生成一個證書給該站點。用戶訪問站點的時候,首先下載該站點的證書(證書里包含機構id,公鑰和認證機構),然後將機構id,公鑰取出,到證書中註明的認證機構伺服器(key server[10]),如果認證通過,則認為該公鑰是真實可信的,否則認為其實偽造的假證書,用戶端將停止後續流程。

(3) 數字簽名[11]

接下來要討論的是數字簽名,我們在生活中,在合同中署上自己的名字的時候,就表示自己已經認真閱讀合同,並同意合同中的條款。署名意味著,不可抵賴,合同塗改無效也意味著合同內容不可篡改,一式兩份甚至多份,有利於起糾紛時,對簿公堂時進行有效證明。當今互聯網極大方便了我們的活動行為,甚至提供了網上合同的服務,那網上合同又是如何做到合同內容不可篡改,簽訂的合同不可抵賴的呢?這裡還是要用到我們的非對稱加密,首先我們需要去權威機構生成自己的公私鑰對,然後在權威機構的key servers上註冊自己的身份證號和公鑰信息,公鑰存在機構上,私鑰自己保存。當我們在網上閱讀完合同的時候,並同意簽署的時候,首先系統會為該合同的內容生成一個hash值,然後使用用戶的私鑰對hash值進行加密,因為只要私鑰不外泄,那麼就可以認定所有操作只有該用戶才能做,因為私鑰僅此一份,他人沒有。加密後的數據,將發送到提供網路合同的機構保存,該密文只能被該用戶的公鑰解出來,只要能被正確解出來,則意味著該密文是該用戶同意簽署的某份合同。因為數字簽名的目的,是為了防止抵賴,以及簽名內容不可被篡改,因此即便被第三方截獲破解,也是無關緊要的,況且用戶的public key也不會被傳來傳去,也減少了被截獲破解的風險。

由於合同內容通過hash函數進行hash值計算,因此如果合同內容修改了,hash值也不相同,hash值和密文內的hash值不同,則被視為不同的合同內容,因此很容易判斷合同是否被篡改,從而做到了合同不可被篡改這一點,另一方面,上文也提到了,因為私鑰只有用戶有,別人的私鑰加密合同,用該用戶的公鑰無法解出有效信息,因此這一點可以做到防抵賴,上面內容是非對稱加密和hash函數,在數字簽名領域的應用。

圖5

Hash函數

前面章節已經介紹過hash函數,如圖2所示,hash函數的作用就是讓不同的輸入,產生固定長度的字元串或者數值,前文我們也對比了加密和hash的區別,但是這裡還要強調一點,則是hash值的不可逆性質,對此,securityinnovationeurope.com的解釋是:

A hash is a string or number generated from a string of text. The resulting string or number is a fixed length, and will vary widely with small variations in input. The best hashing algorithms are designed so that its impossible to turn a hash back into its original string.

引證來源:securityinnovationeurope.com

而Wikipedia上有這樣的闡述:

A cryptographic hash function allows one to easily verify that some input data maps to a given hash value, but if the input data is unknown, it is deliberately difficult to reconstruct it (or any equivalent alternatives) by knowing the stored hash value.

引證來源:en.wikipedia.org/wiki/H

hash值的不可逆性,也是hash函數和加密解密的重要區別之一。

正如我們已經探討過的那樣,hash函數的任務就是將不同的輸入,生成固定長度的不同的字元串序列或數值,然而,實際上有許多hash演算法,仍然可以使得不同的輸入,輸出相同的hash值,這種被稱之為碰撞。而在密碼學中,故意找出生成相同hash值的輸入的,我們稱之為Collision attack[12],Collision attack有兩種,他們分別是:

  • Collision attack:找到兩個不同的輸入m1和m2,使得hash(m1) = hash(m2)
  • Chosen-prefix collision attack:給定兩個不同的前綴p1和p2,找到兩個輸入m1和m2,使得hash(p1 || m1) = hash(p2 || m2) (||為連接符)

如果我們使用能夠被輕易Collision attack的hash演算法,那麼以上面的網上合同為例,用戶進行了數字簽名後,如果有一方剛好找到修改合同中的某些內容,並且使得hash值相等的話,那麼合同即可被篡改,失去了簽名的安全性。目前,曾經被廣泛使用的MD5和SHA-1都被視為不安全的,目前SHA-256被更多地用在安全領域。

雖然MD5已經被視為不安全,但它在校驗數據的完整性方面還是有效的。比如我們的CDN伺服器,對提供給用戶下載的每個文件,都預先計算一個hash值,並將這些hash值記錄在一個文件中,如version.txt:

文件名 | MD5 hash值

--- | ---

file1 | 9e107d9d372bb6826bd81d3542a419d6

file2 | e4d909c290d0fb1ca068ffaddf22cbd0

file3 | d41d8cd98f00b204e9800998ecf8427e

表6

用戶登錄後,先從CDN獲取version.txt文件,如果本地文件的MD5值和version.txt中的不同,則表示文件被更新或者已經損壞,需要重新下載,當本地文件的MD5 hash值和version文件中的一一對應時,則表示整個更新過程完成,圖6展示了這一點。

圖6

Secure Sockets Layer協議[13]

Secure Sockets Layer協議(簡稱為SSL),是集合對稱加密、非對稱加密和hash函數技術,並同時滿足數據機密性、數據真實性認證和終端身份認證多種需求的協議。我們的https就是基於SSL協議實現的,SSL協議是應用層協議,本節將對SSL進行介紹,它的組織如圖7所示。

圖7

SSL的協議結構

當我們應用層的數據,序列化以後,交給SSL進行傳輸時,如果我們直接在數據末尾加上MAC,並加密傳輸,那麼對端只有在接收完完整的應用層數據後,才能進行MAC驗證,這顯然不是我們想要的,因此,SSL會將該序列化好的應用層數據分割為若干個chunk,而每個chunk會加上首部和尾部MAC構成一個被稱之為record的結構,然後一個record接一個record地交給TCP進行數據傳輸(chunk就是record中的data),而record的格式如下所示:

圖8

  • type:表示當前消息是SSL所處的那個階段(handshake、data transfer或close)
  • Version:自解釋欄位
  • Length:表示後面的加密數據,原始數據的長度為多少
  • Data:數據域
  • MAC:經過hash函數計算的hash value

SSL連接建立流程

現在我們來看一下SSL的連接建立流程,假設客戶端C要通過SSL與伺服器S進行通信,則有:

  • 客戶端C和伺服器S建立TCP連接,並完成三次握手
  • 客戶端C將所有自己支持的對稱加密、非對稱加密和hash函數演算法,以及客戶端生成的一個臨時隨機值NonceC,發送給伺服器S
  • 伺服器S從客戶端C發送的演算法列表中,選擇一個對稱加密演算法(如AES),非對稱加密演算法(如RSA)和一個hash演算法(如SHA-256),自己的證書,以及一個臨時隨機值NonceS給客戶端C
  • 客戶端C收到選擇的演算法,證書和NonceS以後,先校驗證書,將證書中的id和public key到指定的CA的key server上進行校驗,如果校驗通過,則執行下一步
  • 客戶端C生成一個Pre-Master Secret(PMS)數據串,並通過證書里的public key進行加密,並傳給伺服器
  • 客戶端C和伺服器S,會使用相同的函數,根據PMS和NonceS、NonceC,生成成四個secret key,分別是客戶端C的對稱加密秘鑰Kc,hash函數的secret值Mc,服務端S的對稱加密秘鑰Ks,hash函數的secret值Ms(最簡單的做法,就是將PMS平均分成4份,其中兩份拼上NonceC後給客戶端C,兩份給拼上NonceS後給伺服器S,也就是說將PMS分成P1,P2,P3和P4,於是有Kc = concat(P1, NonceC),Mc = concat(P2, NonceC),Ks = concat(P3, NonceS),Ms = concat(P4, NonceS),然而出於安全考慮,SSL演算法比這個複雜)
  • 客戶端C將所有連接階段發送和接收的handshake message全部拼起來,計算一個hash值MAC,並發給伺服器
  • 伺服器S將所有連接階段發送和接收的handshake message全部拼起來,計算一下hash值MAC,並發給客戶端

圖9

上面是SSL建立連接的流程,而最後兩個步驟令人困惑,為何客戶端C和伺服器S,要將所有發送和接收的handshake message拼起來,並計算hash值呢?因為在完成TCP三次握手以後,客戶端會向伺服器發送自己支持的加密和hash演算法列表,並且這些消息都是明文傳輸的,而加密演算法中有強有弱,如果中間人截獲該包,刪除所有複雜的加密演算法,讓列表中留下自己有把握破解的加密演算法,那麼此時發送給伺服器S後,伺服器只能選擇這個演算法。為了避免這種問題,客戶端和伺服器會將自己所有發送和接收的數據包拼接起來計算一個hash值MAC,然後交換這個MAC值,如果MAC值匹配不上,則意味著有人在中間做了手腳,因此SSL連接將被中斷。

SSL數據傳輸

在handshake完成以後,就可以通過SSL層進行通訊了,上文我們也提到了,應用層下傳的數據,會被分割成若干個chunk,然後加上首部和尾部組成record,然後再一個record接一個record地傳輸。如圖8所示,SSL協議會對record中的data和MAC的組合部分進行加密,而我們的hash值MAC,是record的type,TCP的sequence number,record的data和hash secret組合起來共同計算的記過,即MAC = hash(data, hash_secret, record_type, tcp_sequence_num),現在假設客戶端C和伺服器S建立完成了handshake流程,客戶端的對稱加密秘鑰為Kc,hash secret為Mc,則有:

  • 客戶端輸入數據message並傳給SSL層
  • SSL將message分割成若干個chunk,每個chunk為一個data數據
  • SSL逐個chunk進行處理,計算hash值MAC,則有MAC = hash(chunk, Mc, record_type, tcp_sequence_num)
  • SSL將chunk視為一塊data,並計算data的長度length
  • SSL對data和MAC,通過Kc進行加密則有,Ec = E(data, MAC)
  • SSL構建record,將加密後的Ec拼合首部type、version和length,構建圖8的結構
  • SSL將record交給TCP進行傳輸
  • 伺服器S收到record後,先通過Kc將Ec解密,獲得data + MAC拼合的序列
  • 伺服器S根據record的length,將真實的data找出,重新計算MAC,然後校驗MAC值
  • 伺服器S在收齊所有的record後,將應用層數據拼合好交給應用進程,傳輸流程完畢

上面的流程,我們這裡引出幾個疑問,第一個就是計算hash值MAC的時候,為何要加入tcp_sequence_num?如果沒有加入這個tcp_sequence_num的話,客戶端C傳輸的數據包,如果被中間人截獲,並修改包的順序後傳給伺服器S,那麼伺服器S在校驗數據包的MAC階段,將無法檢測出任何異常,最終將所有record的data拼合好以後,上傳給應用進程,應用進程將無法獲得客戶端C發送的真實數據,我們把這種中間人攻擊,稱之為reorder attack,如果我們把tcp_sequence_num也加入到hash運算,那麼當我們的TCP包的seq num被修改時,對端收到數據包以後,計算校驗值的時候,將和record中的MAC值不一致,那麼可以視這個包被攻擊了。

還有一個問題,則是SSL每次在Handshake階段,都要交換一次Nonce,這個Nonce的用途是避免包被中間人截獲,然後重新發給伺服器(這種被稱之為replay attack)。然而TCP每次建立連接,客戶端和伺服器都會重新生成sequence number,那麼按道理上一段闡述的將tcp_sequence_num加入hash值運算就可以防止包括reorder attack,甚至replay attack也可以避免,因為每次新的TCP連接建立時,seq num基本上都不相同,就算中間人截獲,那麼在新的會話中,因為中間人之前截獲的包的sequence number和當前會話不一致,也可能會被TCP視為無效的包。然而事實並非如此,如果中間人截獲了,包括TCP三次握手包在內的,所有客戶端C和伺服器S通信的包,那麼這種replay attack是可以進行的,因為TCP是在握手階段交換sequence number,而現在握手包都被截獲了。為了避免這種問題,才引入了Nonce這種臨時隨機值,每次SSL完成三次握手後,服務端和客戶端會交換Nonce,最後根據Nonce生成客戶端和伺服器各自的秘鑰,hash secret,也就是說每次SSLhandshake完,他們的秘鑰和hash secret都是不一樣的,中間人就算截獲了所有的包,並在若干日後重發,因為新的會話生成的秘鑰和hash secret已經和截獲包里的不一致了,因此即便發給伺服器,伺服器也能輕易判斷出這個是個假請求。

Reference

[1] [Computer Networking A Top-Down Approach 6th:Section 8.3.2 Message Authentication Code]

[2] [Wikipedia Encryption]

[3] [What is the difference between Encryption and Hashing]

[4] [Advanced Encryption Standard (AES) Algorithm to Encrypt and Decrypt Data:Section ENCRYPTION PROCESS AddRoundKey ]

[5] [Exclusive or]]

[6] [XOR cipher]

[7] [Computer Networking A Top-Down Approach 6th:Section 8.2.2 Public Key Encryption]

[8] [Fermats little theorem]

[9] [The RSA Public-Key Cryptosystem]

[10] [Key Server]

[11] [Computer Networking A Top-Down Approach 6th:Section 8.3.3 Digital Signatures]

[12] [Collision attack]

[13] [Computer Networking A Top-Down Approach 6th:8.6 Securing TCP Connections: SSL]


推薦閱讀:

洋蔥式信息安全觀察-起點:IT規劃
青年,你的「前世今生」,已不是秘密
U盤丟失導致英國女王出行信息泄露!
去互聯網公司了,寫點小感悟
攻擊者另闢新路:在MS Office文檔中嵌入Flash 0 day漏洞

TAG:信息安全 |