網絡安全 與 加密算法


計算機中的網絡安全

在本篇中介紹了以下幾個方面:

  1. 機密性

    • 密碼學

    • 對稱加密算法(DES, 3DES, AES)

    • 公開秘鑰算法

      • RSA大素數的獲取
  2. 完整性

    • 散列函數(MD5, SHA-1, 並沒有提及算法實現)

    • 報文鑒別(MAC)

    • 數字簽名

  3. 端點鑒別

  4. 應用

    • SSL(TCP網絡安全)
  5. 運行時安全

    • 防火牆的基本知識

主要體現在以下幾個方面:

  1. 機密性, 即發送的信息只有雙方彼此能夠解讀,其他人以任何方式皆無法解讀。

  2. 報文完整性, 即接收方需要能夠驗證,當前接收到的數據是完整的,沒有被經過篡改的。機密性與完整性是相互獨立的兩個屬性。

  3. 端點鑒別, 需要知道我收到的消息, 確確實實是來自於對方, 而不是惡意方偽裝的。

  4. 運行性安全, 需要能夠識別並阻攔惡意攻擊。如 Dos攻擊等, 其目的並非為了竊取信息,而是使得系統癱瘓, 無法運行。

機密性

首先來看機密性問題, 小明和小紅之間發送的有效信息 不希望被第三方解讀。 而實現這點的方式自然是, 加密, 加密,就需要相關的密碼。

密碼學

加密所要實現的根本目的是,將數據加密,除非擁有相關的秘鑰,算法,才能夠 也 必須能夠 將數據恢復到 原始數據。

這里的原始數據被稱作明文, 小明使用了加密算法加密其明文, 生成的文本為密文, 加密算法是公知的,而秘鑰是私有的.

對稱秘鑰體系

  • 凱撒密碼 是一種簡單的加密算法。

    對於字母而言, 約定 用 當前字母的后 第K個字母加以替換, 即可生成對應的密文。

    如: a b c k=2-> c d e

    只需要雙方約定好共同的K, 即可進行加密解密。

  • 更進一步 則是將 k=2 換成只有雙方知道的算法, 如 k = index + 1, 即 k=3

    但缺點同樣明顯, 文本自身並不是沒有特點的, 如小明和小紅在溝通的時候常常會在開頭加入對方的姓名, xiao hong,

    那么經過加密之后,變成了 zkcq jqpi, 則根據習慣來推算, 很容易就得出來 K = 2.

  • 即使是它的改進算法:

    單碼代替密碼, 也難以規避掉這個問題。

    單碼代替密碼不再使用固定的K, 而是有 密碼本 將 明文一一映射替換為 密文, 如 a->h b->k c->a, 雙方都持有相應的密碼本,即可完成加解密工作。

    但是依然是之前的 xiao hong 作為慣用語, 隨着接收到的密文不斷變大,變多,則能夠逐步推算, 還原出對應的密碼本。 完成解密工作。

  • 多碼代替密碼

    這是對單碼代替密碼的一種改進, 對於明文中 文本 位置的不同 采用不同的 密碼本進行匹配。

    而秘鑰呢? 則是 多個密碼本, 以及 位置 和 密碼本之間的匹配關系。

對稱加密在現代社會有兩種寬泛的類型: 流密碼, 塊密碼。

我們會觀察到這樣兩個問題:

  1. 在上面提到的幾種簡單的文本加密算法中, 僅僅能夠對文本進行加密, 而我們在網絡中傳輸 可不一定是文本,更大的可能性是流。 包括協議的首部, 數據報本身。我們所需要加密的對象不僅僅是文本, 而在網絡中 自然更為合適的是對 數據流進行加密。 這並不意味着是 流密碼。

  2. 可匹配的可能性依然太少, 適用性不夠強。

而塊密碼, 正是前面幾種簡單密碼的延伸。

我們將數據流進行拆分 3 6 64 128 等等 bit 為一個塊, 然后對每一個塊都進行加密。

注意到 對 3 bit塊進行加密。 可能會映射到的結果有: 000 001 010 011 100 101 110 111 即 2^3 8中可能性。

而我們的輸入同樣有8種可能性, 因此會映射為 8! = 40320 種可能的結果。 即對每一種輸入都找到其映射結果, 且與其他輸入的結果不重復。

40320 種可能的結果, 對現代計算機來說破解起來實在是一件很輕易的事情。而為了防止被破解, 因此往往會采用更大的塊 做為映射, 比如說 64位, 這樣我們的可能結果就有 (2^64)! 想要破解無疑是一件很困難的事情。

不僅僅是破解起來很是困難,實現起來也是同樣的困難,需要雙方維護一個 2^64 的輸入輸出映射表, 如果需要改變映射表, 也需要雙方都進行調整才可以。

而真實采用的方式,則是 使用函數來模擬 隨機排列表, 一個簡單的例子是:將 64bit拆分成 8 * 8 bit, 每次用一個 8bit的映射表,去置換第一個塊, 將置換后的結果 與 剩余部分混合, 再循環置換 剩下的 bit塊,經過n次循環以后, 就提供了一個64bit的塊, 這種算法的秘鑰是 8張排列表。

DES算法

參考鏈接:數據加密算法--詳解DES加密算法原理與實現

DES是一個分組加密算法,典型的DES以64位為分組對數據加密,加密和解密用的是同一個算法。

密鑰長64位,密鑰事實上是56位參與DES運算(第8、16、24、32、40、48、56、64位是校驗位,使得每個密鑰都有奇數個1),分組后的明文組和56位的密鑰按位替代或交換的方法形成密文組。

需要注意的地方是, 如果初始秘鑰轉換成 byte之后, 如果其前7位是相同的, 那么這兩個秘鑰所計算出來的數據就是相同的。 因為 8 16 等等 是不參與DES運算的。

參考鏈接:JAVA DES 秘鑰問題

將初始秘鑰 通過16輪的計算,轉換, 生成16個子秘鑰(子秘鑰長度為48位)。

而后將明文數據:

首先按照固定的置換規則, 將原數據中的64bit 進行置換。 得到新的數據。

其中置換后的數據被分為兩部分, L0、R0, L0是輸出的左32位,R0是右32位

按照一定的規則 迭代置換 運用之前計算得到的 秘鑰 加密, 16輪之后, 即得到所需的L16, R16。將兩部分合並成一個分組,進行逆置換,逆置換正好是初始置換的逆運算,由此即得到密文輸出。

其初始置換數據:

58,50,42,34,26,18,10,2,

60,52,44,36,28,20,12,4,

62,54,46,38,30,22,14,6,

64,56,48,40,32,24,16,8,

57,49,41,33,25,17,9,1,

59,51,43,35,27,19,11,3,

61,53,45,37,29,21,13,5,

63,55,47,39,31,23,15,7,

逆置換:

在初始置換規則表中, 觀察會發現, 原本第一位的被挪到了第40位, 而在逆置換中, 需要將第四十位置換到第一位即可。

40,8,48,16,56,24,64,32,

39,7,47,15,55,23,63,31,

38,6,46,14,54,22,62,30,

37,5,45,13,53,21,61,29,

36,4,44,12,52,20,60,28,

35,3,43,11,51,19,59,27,

34,2,42,10,50,18,58 26,

33,1,41, 9,49,17,57,25,

正如上面所提到的:核心就是 置換,混合。 解密則是其逆過程。

3DES

3DES(即Triple DES)是DES向AES過渡的加密算法,它使用2條56位的密鑰對數據進行三次加密。是DES的一個更安全的變形。

設Ek()和Dk()代表DES算法的加密和解密過程,K代表DES算法使用的密鑰,M代表明文,C代表密文

3DES加密過程為:C=Ek3(Dk2(Ek1(M)))

3DES解密過程為:M=Dk1(EK2(Dk3(C)))

即用 k1對數據加密 k2對加密過的數據解密 k3 對解密之后的數據再度加密.

K1、K2、K3決定了算法的安全性,若三個密鑰互不相同,本質上就相當於用一個長為168位的密鑰進行加密。多年來,它在對付強力攻擊時是比較安全的。若數據對安全性要求不那么高,K1可以等於K3。在這種情況下,密鑰的有效長度為112位。

不難發現 如果 k1=k2 的話, 與 DES算法是等價的, 這樣有效的實現了與現有DES系統的向后兼容問題。因為當K1=K2時,三重DES的效果就和原來的DES一樣,有助於逐漸推廣三重DES。

AES

  1. 運算速度快,在有反饋模式、無反饋模式的軟硬件中,Rijndael都表現出非常好的性能。
  2. 對內存的需求非常低,適合於受限環境。
  3. Rijndael 是一個分組迭代密碼, 分組長度和密鑰長度設計靈活。
  4. AES標准支持可變分組長度,分組長度可設定為32 比特的任意倍數,最小值為128 比特,最大值為256 比特。
  5. AES的密鑰長度比DES大, 它也可設定為32 比特的任意倍數,最小值為12 比特,最大值為256 比特,所以用窮舉法是不可能破解的。
  6. AES算法的設計策略是WTS。WTS 是針對差分分析和線性分析提出的,可對抗差分密碼分析和線性密碼分析。

而AES的優點, 正是 DES的缺點所在。

AES的具體實現,就不再這里提到了, 感興趣的可以看參考鏈接。 在本篇中, 更關注 其核心思想是什么, 適用范圍在何處,局限性又有哪些。

而 DES 3DES AES 其核心都是 分組, 置換, 加密混淆, 迭代。 這樣一套處理體系。

用密碼生成函數 替換了 原本固定的密碼表。

AES參考: 密碼算法詳解——AES

密碼塊鏈接

需要注意到的是, 即使我們已經擁有了很強大的對稱加密算法,但這就能夠保證不被破解了嗎?

假設我們認為暴力破解是不可行的, 那么在已知部分明文的情況下, 破解出密碼並不是不可能的事情, 因為在加密算法中, 我們對於同一數據的加密結果總是相同的。而在 http傳輸中, HTTP/1.1 這必然是一個很常見的明文輸入,我們匹配了所有的輸入, 發現出現次數最多的 就可以代表其實 HTTP/1.1

考慮這樣一種情況, 在兩個人的通訊過程中,其中一個人的慣用詞匯是 你猜, 幾乎在100句聊天中, 就會出現80句以上的你猜。

那么我們只要抓取到 出現次數最多的密文, 必然就可以認定, 這個密文所對應的明文是 你猜。這樣就能夠大大減小我們破解密碼的難度。

那么自然的, 就要求存在這樣的方式, 使得對於相同的輸入, 其加密后的密文 是不相同的。 即使小明說了一百句你猜。 對於其表現形式來說,其密文都是不同的。

因此,根本無法從雜亂無章的密文中, 判斷出來究竟哪一句對應的明文是 小明的口頭禪, 你猜。

這怎么實現呢?無非是在每次傳輸都附帶一串數據,僅用於本數據的加密。 這依賴的是 異或 運算。

CBC

CBC模式的全稱是Cipher Block Chaining模式(密文分組鏈接模式),之所以叫這個名字,是因為密文分組像鏈條一樣相互連接在一起。

明文: Mi, 密文 Ci, 加密算法: Ks, 隨機的k 比特數: Ri, 異或運算的結果: Ti 異或運算: a⊕b

首先需要知道的是: 對於異或運算:

  1. a ⊕ a = 0
  2. a ⊕ b = b ⊕ a
  3. a ⊕b ⊕ c = a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c
  4. d = a ⊕ b ⊕ c 可以推出 a = d ⊕ b ⊕ c
  5. a ⊕ b ⊕ a = b

對於密文: Ci = Ks(Mi ⊕ Ri), 即將Mi 與 Ri執行異或運算, 通過Ks加密算法對其進行加密, 最終得到密文 Ci。

對於解密: 根據第四條運算法則: d = a ⊕ b ⊕ c 可以推出 a = d ⊕ b ⊕ c

解密后的數據: Ti = Mi ⊕ Ri 則有 Mi = Ti ⊕ Ri, 即對密文進行解密 與 Ri做異或運算, 即可得到初始明文 Mi。

這就要求 我們對 每一個塊(在對稱加密算法中, 正是將數據分成一個又一個的塊), 都發送相應的Ri 用於處理數據。 Ri可以明文發送, 即使Ri被劫持到, 在沒有秘鑰的情況下, 依然是沒有用的。

但這種方式同樣會帶來一個缺點,即對於每一個塊, 我們都需要發送等長的Ri給對方(異或預算必然要求兩者長度一樣,才能進行異或運算。) 這樣我們的數據長度就變為原來的兩倍, 這實在是一筆不小的開銷。

因此通常采用的方式是CBC, 其基本思想是, 僅隨第一個報文發送一個隨機值, 在之后的通訊中 通過計算獲取 相應的編碼。

因此,僅需要N+1個塊, 就能夠實現 對相同的明文,產生不同的密文。

公開秘鑰加密

但在對稱秘鑰體系中, 會有這樣一個問題, 如果一切依托於現實, 我們可以彼此約定一個只有雙方知道的秘鑰, 完成加密解密的相關工作。

但在網絡通訊中, 這並不現實, TCP鏈接時時刻刻都在被銷毀與創建中不斷循環, 我們不可能在路由器兩端使用固定的密碼, 如果這樣做的話 就意味着線路兩端的路由器都要完成解密 然后加密的操作。 用自己的密碼加密之后 發送給下一個節點。

我們也不可能將密碼直接明文 在 通訊中直接傳輸, 那樣的話, 和不加密又有什么區別呢?

這好像是個難題。

直到公開密碼的出現:

是以這樣的方式使用:

對於小B來說, 存在兩個秘鑰, 一個是 公知的 Kb+ 以及 只有自己存有的秘鑰 Kb-, 當小A想要給小B發送消息時, 首先會取得 Kb+ 用一個公知的 加密算法 進行加密,得到密文 Kb+(m), 而當小B接收到 Kb+(m) 時, 用一個公知的 解密算法 配以私鑰 Kb- 進行解密, 最終使得 Kb-(Kb+(m)) = m。 這樣需要解密密文, 就必須要兩個秘鑰才能夠解密。

雖然這樣會引入一個新的問題, 即 任何人都可以 截獲 發送給小B的消息, 然后用自己准備好的明文, 通過 Kb+對明文加密, 發送給小B。

這就要求我們能夠驗證數據的來源方究竟是誰, 需要做端點鑒別, 即確確實實是小A自身發送給小B的消息, 而不是別人冒用名義 發送 分手吧 這樣的悲慘消息。

RSA算法

對於RSA算法, 個人比較感興趣, 在這里描述的可能就會多一點。

對於任何數據流, 我們都不能忘記其本質 依然是 bit流, 而任何bit流 自然也能夠用 唯一的 整數 去表示。

加密這個bit流 自然實際上就是加密這個 唯一數值。

在RSA算法中, 並沒有將數據看成是 字符的集合, 而是數值, 這樣我們就可以使用種種數學公式加以匹配。

RSA包含兩個部分:

加密解密算法

兩個秘鑰, 公鑰和私鑰。

秘鑰的生成

  1. 選擇兩個大素數, 這個值越大越好, 甚至已經超出了常規意義上的 大數值。 該值越大, 破解RSA算法越困難。 推薦公司使用時, p q 兩個數的乘積 需要 為 1024bit數量級。

  2. 計算 n=pq 和 z=(p - 1)(q - 1)

  3. 選擇小於n的一個數值 e, 且 e 和 z 互素。

  4. 求解一個數d, 使得 ed - 1 可以被 z整除。換成數值表達則是:

    ed mod z = 1

  5. 則公鑰是 (n, e), 私鑰是 (n, d);

加解密過程

  1. 要求被加密的整數 m, m < n
  2. 求解 c = (m ^ e) mod n, c即是加密后的密文
  3. 求解 m = (c ^ d) mod n.

看上去實在是很簡單的過程。

但是 我們需要注意到的是這樣幾個問題, p q 本身就是數百bit的值。
被加密的整數一般也都不會非常小。

需要計算 m ^ e c ^ d, 這種種操作本身就是非常消耗計算力的過程。

更何況還需要求得大素數q p 本身。

工作原理

將上述 加解密過程 合並起來看:

求解m時 即是求解: ((m^e) mod n)^d mod n

在模運算中有這樣一個性質:

a ^ b mod n = ((a mod n)^b) mod n 

則上述公式可以變為:

m^ed mod n

因此現在就需要證明:

m ^ ed mod n = m

在數論中, 有:

如果 p q 是素數,且有 n = pq 和 z = (p -1) * (q - 1) 則 X^y mod n = X ^ (y mod z) mod n

因此上述被替換成:

m ^ (ed mod z) mod n => m ^ 1 mod n => (m 小於 n) m

同時如果注意到另一個特點:

如果加解密流程微調:

c = (m ^ d) mod n

m = (m ^ e) mod n

原因則是: m ^ ed mod n 等價於 m ^ de mod n

這個特性意味着什么呢?

意味着: 如果小B用自己的 私鑰 加密數據,那么 小A 可以用 小B的公鑰進行解密, 得到原始數據。 暫時這個功能好像還看不出來什么作用, 我們稍后再提。

RSA的大素數選擇

這同樣是一個難點. 如果不感興趣可以跳過.

參考:

RSA周邊——大素數是怎樣生成的?

數論部分第一節:素數與素性測試

RSA算法的核心正在於 找到兩個大素數 p q 並且這個數值越大越好, 破解的難度就越高。

我們要將兩個數相乘 很簡單, 但是因式分解, 確定它是素數 又是一件很難的事情了。

慣用 也是最簡單的方法, 正是采用試除法進行處理, 即從 2 開始逐個測試, 但目前而言, 我們需要的數值有數百位, 僅僅64位的long型 9223372036854775807 已經是這樣大的一個數值, 更何況數百位?

素性測試
  1. 費馬小定理:

    如果p是一個質數,而整數a不是p的倍數,則有a^(p-1)≡1(mod p)

    即: a的(p-1)次方除以p的余數恆等於1。

    費馬小定理是判定一個數是否為素數的必要條件,並非充分條件,因為存在着一些偽素數滿足費馬小定理卻不是素數.

    也就是說, 如果一個數是素數, 那么必然滿足費馬小定理. 換句話說, 如果存在一個數, 不滿足費馬小定理, 此時可以斷定這個數必然不是素數.

  2. Fermat 素性檢驗

    則考慮a=2, 我們可以將選定的數用 a=2做檢驗, 如果判斷不滿足 費馬小定理. 此時必然不是素數, 比起試除法要快很多。

    但遺憾的是,僅能通過不滿足來檢驗不是素數, 如果滿足我們也沒辦法確定他是素數.

    因此繼續考慮a=3的情況,一個合數可能在a=2時通過了測試,但a=3時的計算結果卻排除了素數的可能。於是,人們擴展了偽素數的定義,稱滿足 a^(n-1) mod n = 1 的合數n叫做以a為底的偽素數(pseudoprime to base a)。

    前10億個自然數中同時以2和3為底的偽素數只有1272個,這個數目不到剛才的1/4。

    這告訴我們如果同時驗證a=2和a=3兩種情況,算法出錯的概率降到了0.000025。

    容易想到,選擇用來測試的a越多,算法越准確。通常我們的做法是,隨機選擇若干個小於待測數的正整數作為底數a進行若干次測試,只要有一次沒有通過測試就可以判定這個數為合數。這就是Fermat素性測試。

    人們自然會想,如果考慮了所有小於n的底數a,出錯的概率是否就可以降到0呢?遺憾的是,居然就有這樣的合數,它可以通過所有a(前提是n與a互素)的測試。Carmichael第一個發現這樣極端的偽素數,他把它們稱作Carmichael數。前10億個自然數中Carmichael數也有600個之多。這樣高的出錯率, 說明費馬素性檢驗 依然不能夠幫我們准確找到一個大素數. 依然需要加強算法.

  3. Miller-Rabin素性測試

    基於下面的定理:

    如果p是素數,x是小於p的正整數,且x^2 mod p = 1,那么要么x=1,要么x=p-1。這是顯然的,因為x^2 mod p = 1相當於p能整除x^2-1,也即p能整除(x+1)(x-1)。由於p是素數,那么只可能是x-1能被p整除(此時x=1)或x+1能被p整除(此時 x=p-1)。

    以 a2,n341為例,演示一下該測試是如何進行的。(2^340%341==1,但是341並不是一個質數)

    根據模運算的規則: a^b mod n = (a mod n)^b mod n

    2 ^ 340 mod 341 = (2^170 mod 341)^2 mod 341 == 1

    此時必然有: 2^170 mod 341 == 1 或 2^170 mod 341 = 340 而 2^170 mod 341 結果是等於 1的

    繼續: 要求滿足: 2^85 mod 341==1 或者 2^85 mod 341 == 340 但此時 兩者都不滿足, 所以341不是素數。

    所以測試的要點則是: 盡可能提取因子2, 把n-1表示成 d * 2 ^ r, 如果n是一個素數,那么或者a ^ d mod n=1,或者存在某個i使得a ^ (d * 2 ^ i) mod n = n - 1.

    但需要注意的是: Miller-Rabin 素性測試同樣是不確定算法,我們把可以通過以a為底的Miller-Rabin測試的合數稱作以a為底的強偽素數(strong pseudoprime)。第一個以2為底的強偽素數為2047。第一個以2和3為底的強偽素數則大到1373653。

    對 於大數的素性判斷,目前Miller-Rabin算法應用最廣泛。一般底數仍然是隨機選取,但當待測數不太大時,選擇測試底數就有一些技巧了。比如,如果 被測數小於4 759 123 141,那么只需要測試三個底數2, 7和61就足夠了。當然,你測試的越多,正確的范圍肯定也越大。如果你每次都用前7個素數(2, 3, 5, 7, 11, 13和17)進行測試,所有不超過341 550 071 728 320的數都是正確的。如果選用2, 3, 7, 61和24251作為底數,那么10^16內唯一的強偽素數為46 856 248 255 981。這樣的一些結論使得Miller-Rabin算法在OI中非常實用。通常認為,Miller-Rabin素性測試的正確率可以令人接受,隨機選取 k個底數進行測試算法的失誤率大概為4^(-k)。

而 Miller-Rabin素性測試 也就是我們的終極法寶。

那么大素數是怎么生成的?

其實生成一個大素數非常簡單,最直觀的方法就是隨機搜索,例如要生成一個100位的大素數,我們先隨機生成一個數字序列,然后用Miller-Rabin素性測試對其進行測試即可,如果不是素數的話再隨機生成一個,如此循環下去~

當然我們可以采用隨機搜索法(每次生成一個完全不一樣的隨機數),也可以采用隨機遞增搜索法(生成一個隨機數之后,每次對其加2)

生成一個n位十進制大素數的步驟如下:

  1. 產生一個n位的隨機數p,且最高位不能為0
  2. 若最低位為偶數,則將它加1,保證該數為奇數以節省時間
  3. 測試該數能否被10000以下的素數(共1228個)整除,這樣可以快速排除許多合數,節省時間
  4. 在2到p-1這間隨機生成一個數a,以a為底對p進行Miller-Rabin素性測試,若不通過說明p為合數。若通過則再選取一個a對p進行測試。選取a時應該選取盡可能小的素數,以提高運算速度。大概進行5次Miller-Rabin素性測試后,精確性就比較高了
  5. 若p每次測試都通過,則認為p是素數。否則p←p+2,再次對p進行測試

會話秘鑰

我們已經看到了,對於對稱密碼而言,密碼本身的發送是一個問題,再者對待千千萬萬不同的用戶, 我們需要不同的密碼去應對每一個請求。

而RSA算法,加密起來確實無人可解, 但是運算太耗費時間, 需要的計算量是 對稱秘鑰算法的 成百上千倍。

那么,我們有沒有一個比較好的處理辦法能夠解決這些問題呢?

當然是將兩者結合起來使用了哇。

我們在一個會話剛剛開始時, 通過 RSA算法 加密 秘鑰, 將秘鑰發送給對方, 在之后的會話過程中, 使用對稱秘鑰進行會話即可。

完整性

需要驗證的是 數據未被修改過。

這就表示 對於我們的 明文, 需要有對應的數據 能夠 驗證, 確確實實沒有被變更.

密碼散列函數

也即哈希函數, hash相信每個開發人員都不陌生, 但在這里 我們對於hash的要求會更高一點:

要求對於任意兩個不同的報文, H(x) == H(y) 的概率 幾乎為0

這一點也就保證了 對於任意報文而言,通過相同的hash函數,我們幾乎不可能找到相同的報文。

MD5正是這樣這樣一個hash 函數.

SHA SHA-1 也是起到同樣的作用。

需要注意到的一點是: MD5, SHA-1 並不能夠被稱作是加密算法。

就我個人理解來說: 凡是被加密的數據,那么必然能夠還原回初始版本, 也即 解密, 而hash函數無疑是不具備這個特點的。

我們想要破解 hash函數 進行還原的唯一辦法是,窮舉法, 對撞。 因為對於密碼散列函數而言,對於不同的文本其hash值幾乎是完全不同的。那么反過來說, 對於散列值必然有其唯一對應的 原始文本。

報文鑒別

對於單純的hash來說, 如果存在第三方,截獲了 A發送的消息, 同時自己偽造了新的消息,並加入了新的散列值。偽裝成A將消息發送給B。

對方收到了消息,傻傻的以為A絕情的要分手。

那么我們就需要一種辦法, 驗證消息確確實實是 A發送的, 而不是來源於別人。

密令就是一個不錯的方式, 當地下黨接頭時, 可能也采用的是原始的對暗號的方式來確定對方的身份。

假定雙方已經持有一個 共享秘鑰s, 當A發送數據時, 通過 明文 H(m + s) 生成哈希值, 當B收到數據時, 自身已經持有s, 因此可以同樣通過 H(m + s) 驗證 數據是否是對方發送的, 也能夠驗證數據的完整性。

而 H(m + s) 就被成為是 報文鑒別碼 (MAC).

但這就要求雙方都已經持有共享秘鑰, 在部分場景, 如 在路由器 鏈路選擇算法中, 可以由網絡管理員配置秘鑰, 以確定數據的來源.

而在服務器和個人交互中呢? 我們如何確定共享秘鑰?

哎? 前面不是提到過會話秘鑰嗎, 這個應該就可以吧. 那么在雙方的初次交互過程中, 又如何確定會話的對象是 你理想中的 服務器呢? 在初次交流中, 已經偽裝成了 知心哥哥, 將秘鑰發給你, 無礙交流, 最終才發現這是又一次殘忍的欺騙.

數字簽名

看來MAC已經沒有辦法幫助我們阻擋壞人了. 那么該怎么辦呢?

帶數字簽名的數據報文 是面向大眾的, 就意味着任何一個人都可能要驗證數據簽名的准確性(這也意味着, 只要通過認證, 那么我就可以確定你是我心目中的那個人.), 因此其秘鑰是周知的, 但既然是周知的, 就意味着可能會有第三方用同樣的方式, 用秘鑰生成簽名, 做以偽裝, 且無法鑒別.

這就依賴一個很有趣的特性了.

還記得在RSA 公開秘鑰算法原理中的一個特性嗎?

c = (m ^ e) mod n

m = (m ^ d) mod n;

c = (m ^ d) mod n

m = (m ^ e) mod n;

這兩種方式是等價的嗎? 都能夠求出來最終的明文.

在需要進行數字簽名時, 即用A的私鑰簽署明文 m, 這樣唯有在明文沒有被篡改的情況下, 持有公鑰即可驗證 報文的 源, 以及報文完整性.

但僅僅是這樣還不夠好, 我們知道RSA計算對資源的消耗時相當大的, 當數據越多 消耗自然也就越大.

因此, 此時加密我們並非加密明文, 而是 加密明文對應的 散列值. 這樣 加密所需要的計算量會大大減小.

公鑰認證

就數字簽名的形成還有問題嗎?

有.

問題在於公鑰, 我們如何得到對方的 可信的 公鑰?

如果不能夠確定公鑰的准確性, 那么依然會存在第三方偽造信息的可能性.

這就需要一個第三方權威機構來做這件事情, 將公鑰與某一機構綁定 通常是由 CA(Certificate Authority)完成. 而一旦CA認證了某個實體的身份, 就會生成一個相應的證書, 證書中包含了 公鑰 以及 實體的唯一標識.

端點鑒別

也即如何證明你是你, 我是我的一個過程.

最簡單的方式, 莫過於告訴你, 我是誰, 然后你就傻傻的相信就好.

如果我們是熟悉的陌生人, 那么我去驗證數據源所屬的IP地址 是否是你的地址也不失為一種確定 你是你的 方式. 這種問題在於, IP地址是可以偽造的.

更近一步的方式, 我們不是有秘鑰嗎? 先傳輸秘鑰, 然后再...

等等, 秘鑰怎么傳輸? 如果是會話秘鑰, 通過RSA傳輸的先決條件是, 對方持有你的 公鑰. 如果明文傳輸, emmm 太可怕了還是不要想.

那么我們通過CA獲取 公鑰不就可以了么? 雙方都經過認證. 這樣就一定可以確定 雙方身份了吧.

NONONO!道高一尺, 魔高一丈.

有一種攻擊手法叫 回放. 今天你轉了 200塊給我, 雖然數據已經加密, 身份已經確定, 此時 第三方 偷偷記錄你們的交流信息, 雖然都看不懂, 無法解讀, 但這不重要, 在第二天, 按照順序將數據原原本本的再發送一遍. 在服務器端看來, 一切都很正常, 對數據的加密, 解讀 都完美無誤, 然而, 你會驚訝的發現, 有人偷了你的兩百塊.

不重數是解決上述問題的一個好辦法. 不重數是在一個協議生存周期只 使用一次的數值. 當雙方開始通信, 通過 RSA加密會話秘鑰, 使用會話秘鑰開始通信的時候, 首先 服務器發送 明文 不重數 給客戶端, 客戶端使用會話秘鑰 加密 再發送回來. 服務端進行驗證. 確定對方是活躍狀態.

SSL

網絡安全的技術手段, 從 機密性 完整性 到 端點鑒別都已經有所涉獵.

而現在幾乎已經成為瀏覽器強制標准的 HTTPS 也正是這種種手段的綜合運用. 也即SSL技術.

SSL(Secure Sockets Layer 安全套接層),及其繼任者傳輸層安全(Transport Layer Security, TLS)是為網絡通信提供安全及數據完整性的一種安全協議.

那么久以上三部分來看, 如果不使用SSL會出現什么問題呢?

在沒有機密性的前提下, 賬號密碼 這一類的東西只能夠通過明文傳輸, 如果有人獲取到了你向服務器提交的請求, 那么你的賬號安全問題就會受到威脅.

不要說base64, md5等算法. 避免不了核心問題. 在網絡傳輸中, 只需要了解你的明文是多少, 而不需要知道明文的真正含義, 就已經可以完成種種不可告人的目的了.

缺失了完整性, 報文會被別人修改, 重新發送給對方, 比如你在淘寶上本來買了一顆蘋果, 最終卻收到了一台洗衣機. 畢竟獲取你的 RSA的公鑰是可被獲取的.

缺失了端點鑒別, 很有可能別人會利用重放攻擊, 向服務器再次模擬你的請求流程, 重復購買你已經買過的東西.

SSL是處在傳輸層的服務, 因此它能夠使得任何基於TCP的服務安全性得到保障.

宏觀描述

握手

  1. 建立TCP鏈接
  2. 在TCP鏈接建立以后, 客戶端向服務器發送hello報文, 服務器用其證書進行響應, 證書中有其公鑰. 驗證服務器的真實性.
  3. 發送給服務器主秘鑰, 即用 服務器的公鑰進行加密, 將秘鑰發送給服務器, 在以后的通話中即使用會話秘鑰.

密鑰導出

但密鑰並非只用一個, 對於MAC秘鑰, 會話密鑰, 從服務器到客戶端, 以及從客戶端到服務器,采用的是不同的秘鑰.

傳輸

但僅僅這樣就能夠使得傳輸不出現問題了嗎? 並不是, 如果存在中間人, 僅僅是在傳輸的過程中對次序進行顛倒, 調整. 這樣在服務器端檢驗是發現不了任何問題的.

我們知道TCP報文是有序號的, 這也不能夠防止亂序嗎?

但需要知道的地方是, 加密的僅僅是從應用層傳輸下來的數據報, 而TCP自身的序號仍然是未經過加密的, 因此只需要修改TCP序號即可完成.

而處理的辦法則是, 並非在數據中實際的包含一個字段, 而是在計算MAC的時候, 將序號納入數據 進行計算.

SSL記錄

  1. 類型, 用於指定該字段是握手報文, 還是包含應用數據的報文, 關閉SSL鏈接也使用此報文
  2. 版本, 自解釋
  3. 長度
  4. 數據
  5. MAC (其中4, 5 會整體進行加密)

完整描述

在SSL中並沒有強制性的要求雙方究竟使用哪一種加密算法, 無論是對稱秘鑰算法還是公開秘鑰算法, 又或者是某一種特定的MAC.

真正的握手階段如下:

  1. 客戶端發送它自身支持的密碼算法列表, 連同客戶的一個不重數.

  2. 服務器選擇算法, 即 MAC, 公開密鑰算法, 對稱算法. 將選擇, 自身證書, 自身的不重數返回給客戶.

    由於雙向認證需求,服務端需要對客戶端進行認證,會同時發送一個 client certificate request, 表示請求客戶端的證書;

  3. 客戶端驗證證書, 提取公鑰, 生成一個前主秘鑰(PMS), 之后用 公鑰加密PMS, 將PMS發送給服務器.

  4. 使用相同的秘鑰導出函數, 客戶端與服務器獨立地從 PMS中計算出 相應的 主秘鑰(MS),
    之后該MS被切片生成所需要的四個密碼(兩個會話秘鑰, 兩個MAC秘鑰)

    由於服務端發起了 client certificate request, 客戶端將戶端的證書 clientCA一並發出;

  5. 客戶端發送所有握手報文的MAC

  6. 服務器發送所有握手報文的MAC

而之所以在56步要做這樣的處理 是因為, 在發送密碼算法列表的時候, 此時雙方還沒有生成 交換密碼, 是以明文發送的, 如果第三方從其中 刪除掉了 較強的 加密算法, 就能夠達成自身不可告人的目的. 大大減低破解難度.

  1. 結束SSL連接時, 在TCP原版中, 是直接發送 TCP FIN即可結束當前會話. 而在SSL中, 加入了類型字段, 指示當前類型為 結束會話, 雖然 類型本身為明文發送, 但是在 計算MAC時, 會使用類型計算MAC.

擴展閱讀: HTTPS、SSL、TLS三者之間的聯系和區別

擴展:

參考: 圖解SSH原理

通過以上介紹, 很容易聯想到一個問題, 即我們常常會使用的git, 使用git時即需要通過 生成自己的公鑰, 私鑰, 同時將公鑰保存在git服務器中, 以完成我們的提交工作. 這里即使 會話秘鑰, 非對稱公開秘鑰的聯合使用. 總算不用對着 git的操作流程, 一臉懵逼.

網絡安全的保障

有這樣多可以被攻擊的手段, 並且在之前僅僅只是提到了截取數據, 修改報文等操作, 還有更多的攻擊, 並不想要竊取你的數據, 各種各樣的病毒, 通過計算機的種種漏洞侵入到你的設備, 控制電腦. 又或是攻擊服務器, 致使服務器癱瘓.

因此, 需要能夠對進入計算機的任何外來數據都做以校驗, 攔截, 才能夠有效阻止邪惡勢力的入侵.

防火牆

所謂“防火牆”是指一種將 內部網和公眾訪問網(如Internet) 分開的方法,它實際上是一種建立在現代通信網絡技術和信息安全技術基礎上的應用性安全技術,隔離技術。越來越多地應用於專用網絡與公用網絡的互聯環境之中,尤其以接入Internet網絡為最甚。

防火牆代主要是借助 硬件和軟件 的作用於內部和外部網絡的環境間產生一種保護的屏障,從而實現對計算機不安全網絡因素的阻斷。

防火牆是在兩個網絡通訊時執行的一種訪問控制尺度,能最大限度阻止網絡中的黑客訪問你的網絡。是指設置在不同網絡(如可信任的企業內部網和不可信的公共網)或網絡安全域之間的一系列部件的組合。它是不同網絡或網絡安全域之間信息的唯一出入口,能根據企業的安全政策控制(允許、拒絕、監測)出入網絡的信息流,且本身具有較強的抗攻擊能力。它是提供信息安全服務,實現網絡和信息安全的基礎設施。

防火牆具有三個目標:

  1. 從外部到內部, 以及從內向外的所有流量都需要通過防火牆

  2. 僅允許被授權的流量通過防火牆

  3. 防火牆自身需要免於滲透. 最堅固的堡壘往往是從內部被攻破.

防火牆分為三類:

傳統的分組過濾器

一個機構往往有將其內部網絡 與 ISP相關聯的網關路由器, 所有的流量無論進出都需要通過這個服務器, 因此它也自然承載了 分組過濾的 功能.

過濾規則一般有如下幾種方式:

  • Ip源地址, 目的地址
  • 協議類型字段: TCP UDP
  • TCP UDP 源, 目的端口
  • TCP 的標志bit, SYN, ACK
  • ICMP報文類型
  • 進出網絡采取不同的規則
  • 不同的路由器采取不同的規則

狀態分組過濾器

這是基於 TCP連接的相關知識進行攔截, 防火牆能夠觀測TCP連接的三次握手, 將通過三次握手的連接記錄在一張表 , 如果收到了 TCP FIN 或 超過 60s未活躍, 則認為當前連接已經結束, 從表中刪除.

正是通過這種方式, 阻攔所有的外部惡意請求, 即通過外界主動向內發送數據的. 因為此時必然不在表中.

應用程序網關

如果需要進行內部用戶受限的操作又該如何呢?

在前面所提到的兩種策略中, 並不能夠探測到應用層的數據, 即不能夠對特定應用的 特定用戶 進行區分限流.

應用程序網關, 是特定應用程序的服務器, 所有應用程序相關的數據都必須通過它. 如telnet服務器, 所有用戶在向外界訪問時, 必須輸入自身的用戶名密碼, 如果校驗不通過, 即不能夠進行訪問. 這正是因為 應用程序網關將自身當做服務器, 讀取了來自客戶端的數據, 從而決定是否擁有訪問權限, 當校驗通過后, 又將自身當做客戶端, 向真正的服務器發起請求, 獲取數據.

而缺點也是比較明顯的, 每個應用程序都需要對應的網關服務器, 其次所有的數據都需要代為轉發, 當用戶 和 應用程序數量一旦上來, 對性能是個較大的考驗. 最后 , 不僅是客戶需要知道如何連接到網關服務器, 服務器也需要知道 如何連接到哪一個外部服務器.

在防火牆的描述中, 我們會發現依然有局限性, 並不能夠在執行分組過濾的同時 檢測應用層數據, 否則就需要應用程網關來作為中介.

我們需要一種能夠結合兩者特點的, 且並非只是針對特定的應用程序.

當設備觀測到可疑流量, 可疑分組時, 需要向網絡管理員發出警告. 能夠觀測到潛在惡意流量時產生告警的設備 被稱為 入侵檢測系統(IDS), 濾除可疑流量的設備被稱為 入侵防止系統(IPS).

至於更多的就不多做介紹.

總結

從最簡單的代替密碼. 當我們將密碼本進一步擴展, 且根據文本所處的不同位置采用不同的密碼本 就成了多碼代替, 進一步擴展, 我們將密碼本換成了 初始密碼 與 密碼函數的組合 就變成了 對稱秘鑰的基本雛形. 但對稱密碼不利於在網絡傳輸中直接使用, 因此 公開秘鑰體系應運而生.

相應的, 為了驗證報文的完整性, 就需要 MD5, SHA-1這樣算法 來將報文轉換成 對應的 hash值. 驗證文本與hash值的一致性即可. 由於存在可能性是將整個報文直接替換, 而非修改 生成新的 報文與hash值, 因此需要將 報文與共享秘鑰 合並 生成MAC 加以驗證數據源.

但這依然不夠, 對於服務器需要面對的群體對象實在太多, 很難實現和每個人都共享對應的秘鑰, 倒不如將自身的公鑰公開, 通過私鑰加密報文的hash值, 就變成了數字簽名, 客戶端只需要通過權威機構獲取其證書, 即可解析公鑰, 完成解密驗證過程.

通過同樣的方式, 我們也能夠完成 驗證 你是你(即端點鑒別)的這樣一個過程.

為了防止別人竊取到服務器與客戶端的聊天記錄, 在第二天進行回放操作, 因此又有了不重數做以補充.

然而我們在一段會話中 不可能全部使用 RSA進行加密, 代價太過高昂, 因此通過RSA加密一段 對稱秘鑰, 用於會話中. 這即是 會話秘鑰.

而SSL SSH等 則是對上述種種技術的綜合運用.

防火牆的主要功用是, 通過分組過濾, 分組檢測等功能, 阻止惡意入侵.

網絡安全中心最重要的幾個板塊.

機密性, 完整性, 端點鑒別, 運行時安全 即如是.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM