數字證書

小 樓 一 夜 聽 春 雨發表於2018-01-27

★ 先說一個通俗的例子

  考慮到證書體系的相關知識比較枯燥、晦澀。俺先拿一個通俗的例子來說事兒。

  ◇ 普通的介紹信

  想必大夥兒都聽說過介紹信的例子吧?假設 A 公司的張三先生要到 B 公司去拜訪,但是 B 公司的所有人都不認識他,他咋辦捏?常用的辦法是帶公司開的一張介紹信,在信中說:茲有張三先生前往貴公司辦理業務,請給予接洽......云云。然後在信上敲上A公司的公章。

  張三先生到了 B 公司後,把介紹信遞給 B 公司的前臺李四小姐。李小姐一看介紹信上有 A 公司的公章,而且 A 公司是經常和 B 公司有業務往來的,這位李小姐就相信張先生不是歹人了。

  說到這,愛抬槓的同學會問了:萬一公章是偽造的,咋辦捏?在此,俺要先宣告,在本例子中,先假設公章是難以偽造的,否則俺的故事沒法說下去鳥。

  ◇ 引入中介機構的介紹信

  好,回到剛才的話題。如果和 B 公司有業務往來的公司很多,每個公司的公章都不同,那前臺就要懂得分辨各種公章,非常滴麻煩。所以,有某個中介公司 C,發現了這個商機。C公司專門開設了一項“代理公章”的業務。

  今後,A 公司的業務員去 B 公司,需要帶2個介紹信:

  介紹信1

  含有 C 公司的公章及 A 公司的公章。並且特地註明:C 公司信任 A 公司。

  介紹信2

  僅含有 A 公司的公章,然後寫上:茲有張三先生前往貴公司辦理業務,請給予接洽......云云。

  某些不開竅的同學會問了,這樣不是增加麻煩了嗎?有啥好處捏?

  主要的好處在於,對於接待公司的前臺,就不需要記住各個公司的公章分別是啥樣子的;他/她只要記住中介公司 C 的公章即可。當他/她拿到兩份介紹信之後,先對介紹信1的 C 公章,驗明正身;確認無誤之後,再比對介紹信1和介紹信2的兩個 A 公章是否一致。如果是一樣的,那就可以證明介紹信2是可以信任的了。

  ★ 相關專業術語的解釋

  費了不少口水,終於說完了一個俺自認為比較通俗的例子。如果你聽到到這,還是想不明白這個例子在說啥,那後續的內容,就不必浪費時間聽了 :(

  下面,俺就著上述的例子,把相關的名詞,作一些解釋。

  ◇ 什麼是證書?

  “證書”洋文也叫“digital certificate”或“public key certificate”(專業的解釋看“這裡”)。

  它是用來證明某某東西確實是某某東西的東西(是不是像繞口令?)。通俗地說,證書就好比例子裡面的公章。通過公章,可以證明該介紹信確實是對應的公司發出的。

  理論上,人人都可以找個證書工具,自己做一個證書。那如何防止壞人自己製作證書出來騙人捏?請看後續 CA 的介紹。

  ◇ 什麼是CA?

  CA是Certificate Authority的縮寫,也叫“證書授權中心”。(專業的解釋看“這裡”)

  它是負責管理和簽發證書的第三方機構,就好比例子裡面的中介——C 公司。一般來說,CA必須是所有行業和所有公眾都信任的、認可的。因此它必須具有足夠的權威性。就好比A、B兩公司都必須信任C公司,才會找 C 公司作為公章的中介。

  ◇ 什麼是CA證書?

  CA 證書,顧名思義,就是CA頒發的證書。

  前面已經說了,人人都可以找工具製作證書。但是你一個小破孩製作出來的證書是沒啥用處的。因為你不是權威的CA機關,你自己搞的證書不具有權威性。

  這就好比上述的例子裡,某個壞人自己刻了一個公章,蓋到介紹信上。但是別人一看,不是受信任的中介公司的公章,就不予理睬。壞蛋的陰謀就不能得逞啦。

  文字後續提及的證書,若無特殊說明,均指 CA 證書。

  ◇ 什麼是證書之間的信任關係?

  在俺的例子裡談到,引入中介後,業務員要同時帶兩個介紹信。第一個介紹信包含了兩個公章,並註明,公章C信任公章A。證書間的信任關係,就和這個類似。就是用一個證書來證明另一個證書是真實可信滴。

  ◇ 什麼是證書信任鏈?

  實際上,證書之間的信任關係,是可以巢狀的。比如,C 信任 A1,A1 信任 A2,A2 信任 A3......這個叫做證書的信任鏈。只要你信任鏈上的頭一個證書,那後續的證書,都是可以信任滴。

  ◇ 什麼是根證書?

  “根證書”的洋文叫“root certificate”,專業的解釋看“這裡”。為了說清楚根證書是咋回事,再來看個稍微複雜點的例子。

  假設 C 證書信任 A 和 B;然後 A 信任 A1 和 A2;B 信任 B1 和 B2。則它們之間,構成如下的一個樹形關係(一個倒立的樹)。

  處於最頂上的樹根位置的那個證書,就是“根證書”。除了根證書,其它證書都要依靠上一級的證書,來證明自己。那誰來證明“根證書”可靠捏?實際上,根證書自己證明自己是可靠滴(或者換句話說,根證書是不需要被證明滴)。

  聰明的同學此刻應該意識到了:根證書是整個證書體系安全的根本。所以,如果某個證書體系中,根證書出了問題(不再可信了),那麼所有被根證書所信任的其它證書,也就不再可信了。這個後果是相當相當滴嚴重(簡直可以說是災難性的),具體在下一個帖子裡介紹。

  ★ 證書有啥用?

  CA 證書的作用有很多,俺為了節省口水,只列出常用的幾個。

  ◇ 驗證網站是否可信(針對HTTPS)

  通常,我們如果訪問某些敏感的網頁(比如使用者登入的頁面),其協議都會使用 HTTPS 而不是 HTTP。因為 HTTP 協議是明文的,一旦有壞人在偷窺你的網路通訊,他/她就可以看到網路通訊的內容(比如你的密碼、銀行帳號、等);而 HTTPS 是加密的協議,可以保證你的傳輸過程中,壞蛋無法偷窺。

  但是,千萬不要以為,HTTPS 協議有了加密,就可高枕無憂了。俺再舉一個例子來說明,光有加密是不夠滴。假設有一個壞人,搞了一個假的網銀的站點,然後誘騙你上這個站點。假設你又比較單純,一不留神,就把你的帳號,口令都輸入進去了。那這個壞蛋的陰謀就得逞鳥。

  為了防止壞人這麼幹,HTTPS 協議除了有加密的機制,還有一套證書的機制。通過證書來確保,某個站點確實就是某個站點。

  有了證書之後,當你的瀏覽器在訪問某個 HTTPS 網站時,會驗證該站點上的 CA 證書(類似於驗證介紹信的公章)。如果瀏覽器發現該證書沒有問題(證書被某個根證書信任、證書上繫結的域名和該網站的域名一致、證書沒有過期),那麼頁面就直接開啟;否則的話,瀏覽器會給出一個警告,告訴你該網站的證書存在某某問題,是否繼續訪問該站點?為了形象起見,下面給出 IE 和 Firefox 的抓圖:

  大多數知名的網站,如果用了 HTTPS 協議,其證書都是可信的(也就不會出現上述警告)。所以,今後你如果上某個知名網站,發現瀏覽器跳出上述警告,你就要小心啦!

  ◇ 驗證某檔案是否可信(是否被篡改)

  證書除了可以用來驗證某個網站,還可以用來驗證某個檔案是否被篡改。具體是通過證書來製作檔案的數字簽名。製作數字簽名的過程太專業,我們就不說了。後面專門告訴大家如何驗證檔案的數字簽名。考慮到大多數人用 Windows 系統,俺就拿 Windows 的例子來說事兒。

  比如,俺手頭有一個 Firefox 的安裝檔案(帶有數字簽名)。當俺檢視該檔案的屬性,會看到如下的介面。眼神好的同學,會注意到到上面有個“數字簽名”的標籤頁。如果沒有出現這個標籤頁,就說明該檔案沒有附帶數字簽名。

  選擇該標籤頁,看到如下介面。

  順便說一下,某些數字簽名中沒有包含“郵件地址”,那麼這一項會顯示“不可用”;同樣的,某些數字簽名沒有包含“時間戳”,也會顯示“不可用”。不要緊張,這裡顯示的“不可用”跟數字簽名的有效性沒關係

  一般來說,簽名列表中,有且僅有一個簽名。選中它,點“詳細資訊”按鈕。跳出如下介面:

  通常這個介面會顯示一行字:“該數字簽名正常”(圖中紅圈標出)。如果有這行字,就說明該檔案從出廠到你手裡,中途沒有被篡改過(是原裝滴、是純潔滴)。

  如果該檔案被篡改過了(比如,感染了病毒、被注入木馬),那麼對話方塊會出現一個警告提示“該數字簽名無效”(圖中紅圈標出)。介面如下:

  不論簽名是否正常,你都可以點“檢視證書”按鈕。這時候,會跳出證書的對話方塊。如下:

 

  從後一個介面,可以看到俺剛才說的證書信任鏈。圖中的信任鏈有3層:

  第1層是根證書(Thawte Premium Server CA)。

  第2層是 Thawte 專門用來簽名的證書。

  第3層是 Mozilla 自己的證書。 

  目前大多數知名的公司(或組織機構),其釋出的可執行檔案(比如軟體安裝包、驅動程式、安全補丁),都帶有數字簽名。你可以自己去看一下。

  建議大夥兒在安裝軟體之前,都先看看是否有數字簽名?如果有,就按照上述步驟驗證一把。一旦數字簽名是壞的,那可千萬別裝。

 

 

 

1、基礎知識

這部分內容主要解釋一些概念和術語,最好是先理解這部分內容。

1.1、公鑰密碼體制(public-key cryptography)

公鑰密碼體制分為三個部分,公鑰、私鑰、加密解密演算法,它的加密解密過程如下:

  • 加密:通過加密演算法和公鑰對內容(或者說明文)進行加密,得到密文。加密過程需要用到公鑰。
  • 解密:通過解密演算法和私鑰對密文進行解密,得到明文。解密過程需要用到解密演算法和私鑰。注意,由公鑰加密的內容,只能由私鑰進行解密,也就是說,由公鑰加密的內容,如果不知道私鑰,是無法解密的。

公鑰密碼體制的公鑰和演算法都是公開的(這是為什麼叫公鑰密碼體制的原因),私鑰是保密的。大家都以使用公鑰進行加密,但是隻有私鑰的持有者才能解密。在實際的使用中,有需要的人會生成一對公鑰和私鑰,把公鑰釋出出去給別人使用,自己保留私鑰。

 

1.2、對稱加密演算法(symmetric key algorithms)

在對稱加密演算法中,加密使用的金鑰和解密使用的金鑰是相同的。也就是說,加密和解密都是使用的同一個金鑰。因此對稱加密演算法要保證安全性的話,金鑰要做好保密,只能讓使用的人知道,不能對外公開。這個和上面的公鑰密碼體制有所不同,公鑰密碼體制中加密是用公鑰,解密使用私鑰,而對稱加密演算法中,加密和解密都是使用同一個金鑰,不區分公鑰和私鑰。

 

// 金鑰,一般就是一個字串或數字,在加密或者解密時傳遞給加密/解密演算法。前面在公鑰密碼體制中說到的公鑰、私鑰就是金鑰,公鑰是加密使用的金鑰,私鑰是解密使用的金鑰。

 
1.3、非對稱加密演算法(asymmetric key algorithms)

在非對稱加密演算法中,加密使用的金鑰和解密使用的金鑰是不相同的。前面所說的公鑰密碼體制就是一種非對稱加密演算法,他的公鑰和是私鑰是不能相同的,也就是說加密使用的金鑰和解密使用的金鑰不同,因此它是一個非對稱加密演算法。

 

1.4、RSA簡介

RSA是一種公鑰密碼體制,現在使用得很廣泛。如果對RSA本身有興趣的,後面看我有沒有時間寫個RSA的具體介紹。

RSA密碼體制是一種公鑰密碼體制,公鑰公開,私鑰保密,它的加密解密演算法是公開的。 由公鑰加密的內容可以並且只能由私鑰進行解密,並且由私鑰加密的內容可以並且只能由公鑰進行解密。也就是說,RSA的這一對公鑰、私鑰都可以用來加密和解密,並且一方加密的內容可以由並且只能由對方進行解密

 

1.5、簽名和加密

我們說加密,是指對某個內容加密,加密後的內容還可以通過解密進行還原。 比如我們把一封郵件進行加密,加密後的內容在網路上進行傳輸,接收者在收到後,通過解密可以還原郵件的真實內容。

這裡主要解釋一下簽名,簽名就是在資訊的後面再加上一段內容,可以證明資訊沒有被修改過,怎麼樣可以達到這個效果呢?一般是對資訊做一個hash計算得到一個hash值,注意,這個過程是不可逆的,也就是說無法通過hash值得出原來的資訊內容。在把資訊傳送出去時,把這個hash值加密後做為一個簽名和資訊一起發出去。 接收方在收到資訊後,會重新計算資訊的hash值,並和資訊所附帶的hash值(解密後)進行對比,如果一致,就說明資訊的內容沒有被修改過,因為這裡hash計算可以保證不同的內容一定會得到不同的hash值,所以只要內容一被修改,根據資訊內容計算的hash值就會變化。當然,不懷好意的人也可以修改資訊內容的同時也修改hash值,從而讓它們可以相匹配,為了防止這種情況,hash值一般都會加密後(也就是簽名)再和資訊一起傳送,以保證這個hash值不被修改。至於如何讓別人可以解密這個簽名,這個過程涉及到數字證書等概念,我們後面在說到數字證書時再詳細說明,這裡您先只需先理解簽名的這個概念。

 

2、一個加密通訊過程的演化

我們來看一個例子,現在假設“伺服器”和“客戶”要在網路上通訊,並且他們打算使用RSA(參看前面的RSA簡介)來對通訊進行加密以保證談話內容的安全。由於是使用RSA這種公鑰密碼體制,“伺服器”需要對外發布公鑰(演算法不需要公佈,RSA的演算法大家都知道),自己留著私鑰。“客戶”通過某些途徑拿到了“伺服器”釋出的公鑰,客戶並不知道私鑰。“客戶”具體是通過什麼途徑獲取公鑰的,我們後面再來說明,下面看一下雙方如何進行保密的通訊:

 

2.1 第一回合:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器

“客戶”->“伺服器”:????

因為訊息是在網路上傳輸的,有人可以冒充自己是“伺服器”來向客戶傳送資訊。例如上面的訊息可以被黑客截獲如下:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器

“客戶”->“黑客”:你好        // 黑客在“客戶”和“伺服器”之間的某個路由器上截獲“客戶”發給伺服器的資訊,然後自己冒充“伺服器”

“黑客”->“客戶”:你好,我是伺服器

因此“客戶”在接到訊息後,並不能肯定這個訊息就是由“伺服器”發出的,某些“黑客”也可以冒充“伺服器”發出這個訊息。如何確定資訊是由“伺服器”發過來的呢?有一個解決方法,因為只有伺服器有私鑰,所以如果只要能夠確認對方有私鑰,那麼對方就是“伺服器”。因此通訊過程可以改進為如下:

 

2.2 第二回合:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器

“客戶”->“伺服器”:向我證明你就是伺服器

“伺服器”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[私鑰|RSA]

// 意這裡約定一下,{} 表示RSA加密後的內容,[ | ]表示用什麼金鑰和演算法進行加密,後面的示例中都用這種表示方式,例如上面的 {你好,我是伺服器}[私鑰|RSA]  就表示用私鑰對“你好,我是伺服器”進行加密後的結果。

為了向“客戶”證明自己是“伺服器”, “伺服器”把一個字串用自己的私鑰加密,把明文和加密後的密文一起發給“客戶”。對於這裡的例子來說,就是把字串 “你好,我是伺服器”和這個字串用私鑰加密後的內容 {你好,我是伺服器}[私鑰|RSA] 發給客戶。

“客戶”收到資訊後,她用自己持有的公鑰解密密文,和明文進行對比,如果一致,說明資訊的確是由伺服器發過來的。也就是說“客戶”把 {你好,我是伺服器}[私鑰|RSA] 這個內容用公鑰進行解密,然後和“你好,我是伺服器”對比。因為由“伺服器”用私鑰加密後的內容,由並且只能由公鑰進行解密,私鑰只有“伺服器”持有,所以如果解密出來的內容是能夠對得上的,那說明資訊一定是從“伺服器”發過來的。

假設“黑客”想冒充“伺服器”:

“黑客”->“客戶”:你好,我是伺服器

“客戶”->“黑客”:向我證明你就是伺服器

“黑客”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[???|RSA]    //這裡黑客無法冒充,因為他不知道私鑰,無法用私鑰加密某個字串後傳送給客戶去驗證。

“客戶”->“黑客”:????

由於“黑客”沒有“伺服器”的私鑰,因此它傳送過去的內容,“客戶”是無法通過伺服器的公鑰解密的,因此可以認定對方是個冒牌貨!

到這裡為止,“客戶”就可以確認“伺服器”的身份了,可以放心和“伺服器”進行通訊,但是這裡有一個問題,通訊的內容在網路上還是無法保密。為什麼無法保密呢?通訊過程不是可以用公鑰、私鑰加密嗎?其實用RSA的私鑰和公鑰是不行的,我們來具體分析下過程,看下面的演示:

 

2.3 第三回合:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器

“客戶”->“伺服器”:向我證明你就是伺服器

“伺服器”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[私鑰|RSA]

“客戶”->“伺服器”:{我的帳號是aaa,密碼是123,把我的餘額的資訊發給我看看}[公鑰|RSA]

“伺服器”->“客戶”:{你的餘額是100元}[私鑰|RSA]

注意上面的的資訊 {你的餘額是100元}[私鑰],這個是“伺服器”用私鑰加密後的內容,但是我們之前說了,公鑰是釋出出去的,因此所有的人都知道公鑰,所以除了“客戶”,其它的人也可以用公鑰對{你的餘額是100元}[私鑰]進行解密。所以如果“伺服器”用私鑰加密發給“客戶”,這個資訊是無法保密的,因為只要有公鑰就可以解密這內容。然而“伺服器”也不能用公鑰對傳送的內容進行加密,因為“客戶”沒有私鑰,傳送個“客戶”也解密不了。

這樣問題就又來了,那又如何解決呢?在實際的應用過程,一般是通過引入對稱加密來解決這個問題,看下面的演示:

 

2.4 第四回合:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器

“客戶”->“伺服器”:向我證明你就是伺服器

“伺服器”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[私鑰|RSA]

“客戶”->“伺服器”:{我們後面的通訊過程,用對稱加密來進行,這裡是對稱加密演算法和金鑰}[公鑰|RSA]    //藍色字型的部分是對稱加密的演算法和金鑰的具體內容,客戶把它們傳送給伺服器。

“伺服器”->“客戶”:{OK,收到!}[金鑰|對稱加密演算法]

“客戶”->“伺服器”:{我的帳號是aaa,密碼是123,把我的餘額的資訊發給我看看}[金鑰|對稱加密演算法]

“伺服器”->“客戶”:{你的餘額是100元}[金鑰|對稱加密演算法]

在上面的通訊過程中,“客戶”在確認了“伺服器”的身份後,“客戶”自己選擇一個對稱加密演算法和一個金鑰,把這個對稱加密演算法和金鑰一起用公鑰加密後傳送給“伺服器”。注意,由於對稱加密演算法和金鑰是用公鑰加密的,就算這個加密後的內容被“黑客”截獲了,由於沒有私鑰,“黑客”也無從知道對稱加密演算法和金鑰的內容。

由於是用公鑰加密的,只有私鑰能夠解密,這樣就可以保證只有伺服器可以知道對稱加密演算法和金鑰,而其它人不可能知道(這個對稱加密演算法和金鑰是“客戶”自己選擇的,所以“客戶”自己當然知道如何解密加密)。這樣“伺服器”和“客戶”就可以用對稱加密演算法和金鑰來加密通訊的內容了。

 

總結一下,RSA加密演算法在這個通訊過程中所起到的作用主要有兩個:

  • 因為私鑰只有“伺服器”擁有,因此“客戶”可以通過判斷對方是否有私鑰來判斷對方是否是“伺服器”。
  • 客戶端通過RSA的掩護,安全的和伺服器商量好一個對稱加密演算法和金鑰來保證後面通訊過程內容的安全。

如果這裡您理解了為什麼不用RSA去加密通訊過程,而是要再確定一個對稱加密演算法來保證通訊過程的安全,那麼就說明前面的內容您已經理解了。(如果不清楚,再看下2.3和2.4,如果還是不清楚,那應該是我們說清楚,您可以留言提問。)

到這裡,“客戶”就可以確認“伺服器”的身份,並且雙方的通訊內容可以進行加密,其他人就算截獲了通訊內容,也無法解密。的確,好像通訊的過程是比較安全了。

 

但是這裡還留有一個問題,在最開始我們就說過,“伺服器”要對外發布公鑰,那“伺服器”如何把公鑰傳送給“客戶”呢?我們第一反應可能會想到以下的兩個方法:

a)把公鑰放到網際網路的某個地方的一個下載地址,事先給“客戶”去下載。

b)每次和“客戶”開始通訊時,“伺服器”把公鑰發給“客戶”。

但是這個兩個方法都有一定的問題,

對於a)方法,“客戶”無法確定這個下載地址是不是“伺服器”釋出的,你憑什麼就相信這個地址下載的東西就是“伺服器”釋出的而不是別人偽造的呢,萬一下載到一個假的怎麼辦?另外要所有的“客戶”都在通訊前事先去下載公鑰也很不現實。

對於b)方法,也有問題,因為任何人都可以自己生成一對公鑰和私鑰,他只要向“客戶”傳送他自己的私鑰就可以冒充“伺服器”了。示意如下:

“客戶”->“黑客”:你好           //黑客截獲“客戶”發給“伺服器”的訊息

“黑客”->“客戶”:你好,我是伺服器,這個是我的公鑰    //黑客自己生成一對公鑰和私鑰,把公鑰發給“客戶”,自己保留私鑰

“客戶”->“黑客”:向我證明你就是伺服器

“黑客”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[黑客自己的私鑰|RSA]      //客戶收到“黑客”用私鑰加密的資訊後,是可以用“黑客”發給自己的公鑰解密的,從而會誤認為“黑客”是“伺服器”

因此“黑客”只需要自己生成一對公鑰和私鑰,然後把公鑰傳送給“客戶”,自己保留私鑰,這樣由於“客戶”可以用黑客的公鑰解密黑客的私鑰加密的內容,“客戶”就會相信“黑客”是“伺服器”,從而導致了安全問題。這裡問題的根源就在於,大家都可以生成公鑰、私鑰對,無法確認公鑰對到底是誰的。 如果能夠確定公鑰到底是誰的,就不會有這個問題了。例如,如果收到“黑客”冒充“伺服器”發過來的公鑰,經過某種檢查,如果能夠發現這個公鑰不是“伺服器”的就好了。

為了解決這個問題,數字證書出現了,它可以解決我們上面的問題。先大概看下什麼是數字證書,一個證書包含下面的具體內容:

  • 證書的釋出機構
  • 證書的有效期
  • 公鑰
  • 證書所有者(Subject)
  • 簽名所使用的演算法
  • 指紋以及指紋演算法

證書的內容的詳細解釋會在後面詳細解釋,這裡先只需要搞清楚一點,數字證書可以保證數字證書裡的公鑰確實是這個證書的所有者(Subject)的,或者證書可以用來確認對方的身份。也就是說,我們拿到一個數字證書,我們可以判斷出這個數字證書到底是誰的。至於是如何判斷的,後面會在詳細討論數字證書時詳細解釋。現在把前面的通訊過程使用數字證書修改為如下:

 

2.5 第五回合:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器,這裡是我的數字證書        //這裡用證書代替了公鑰

“客戶”->“伺服器”:向我證明你就是伺服器

“伺服器”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[私鑰|RSA]

注意,上面第二次通訊,“伺服器”把自己的證書發給了“客戶”,而不是傳送公鑰。“客戶”可以根據證書校驗這個證書到底是不是“伺服器”的,也就是能校驗這個證書的所有者是不是“伺服器”,從而確認這個證書中的公鑰的確是“伺服器”的。後面的過程和以前是一樣,“客戶”讓“伺服器”證明自己的身份,“伺服器”用私鑰加密一段內容連同明文一起發給“客戶”,“客戶”把加密內容用數字證書中的公鑰解密後和明文對比,如果一致,那麼對方就確實是“伺服器”,然後雙方協商一個對稱加密來保證通訊過程的安全。到這裡,整個過程就完整了,我們回顧一下:

 

2.6 完整過程:

step1: “客戶”向服務端傳送一個通訊請求

“客戶”->“伺服器”:你好

step2: “伺服器”向客戶傳送自己的數字證書。證書中有一個公鑰用來加密資訊,私鑰由“伺服器”持有

“伺服器”->“客戶”:你好,我是伺服器,這裡是我的數字證書

 

step3: “客戶”收到“伺服器”的證書後,它會去驗證這個數字證書到底是不是“伺服器”的,數字證書有沒有什麼問題,數字證書如果檢查沒有問題,就說明數字證書中的公鑰確實是“伺服器”的。檢查數字證書後,“客戶”會傳送一個隨機的字串給“伺服器”用私鑰去加密,伺服器把加密的結果返回給“客戶”,“客戶”用公鑰解密這個返回結果,如果解密結果與之前生成的隨機字串一致,那說明對方確實是私鑰的持有者,或者說對方確實是“伺服器”。

“客戶”->“伺服器”:向我證明你就是伺服器,這是一個隨機字串     //前面的例子中為了方便解釋,用的是“你好”等內容,實際情況下一般是隨機生成的一個字串。

“伺服器”->“客戶”:{一個隨機字串}[私鑰|RSA]

 

step4: 驗證“伺服器”的身份後,“客戶”生成一個對稱加密演算法和金鑰,用於後面的通訊的加密和解密。這個對稱加密演算法和金鑰,“客戶”會用公鑰加密後傳送給“伺服器”,別人截獲了也沒用,因為只有“伺服器”手中有可以解密的私鑰。這樣,後面“伺服器”和“客戶”就都可以用對稱加密演算法來加密和解密通訊內容了。

“伺服器”->“客戶”:{OK,已經收到你發來的對稱加密演算法和金鑰!有什麼可以幫到你的?}[金鑰|對稱加密演算法]

“客戶”->“伺服器”:{我的帳號是aaa,密碼是123,把我的餘額的資訊發給我看看}[金鑰|對稱加密演算法]

“伺服器”->“客戶”:{你好,你的餘額是100元}[金鑰|對稱加密演算法]

…… //繼續其它的通訊

 

2.7 其它問題:

上面的過程已經十分接近HTTPS的真實通訊過程了,完全可以按照這個過程去理解HTTPS的工作原理。但是我為了方便解釋,上面有些細節沒有說到,有興趣的人可以看下這部分的內容。可以跳過不看,無關緊要。

 

【問題1】

上面的通訊過程中說到,在檢查完證書後,“客戶”傳送一個隨機的字串給“伺服器”去用私鑰加密,以便判斷對方是否真的持有私鑰。但是有一個問題,“黑客”也可以傳送一個字串給“伺服器”去加密並且得到加密後的內容,這樣對於“伺服器”來說是不安全的,因為黑客可以傳送一些簡單的有規律的字串給“伺服器”加密,從而尋找加密的規律,有可能威脅到私鑰的安全。所以說,“伺服器”隨隨便便用私鑰去加密一個來路不明的字串並把結果傳送給對方是不安全的。

〖解決方法〗

每次收到“客戶”發來的要加密的的字串時,“伺服器”並不是真正的加密這個字串本身,而是把這個字串進行一個hash計算,加密這個字串的hash值(不加密原來的字串)後傳送給“客戶”,“客戶”收到後解密這個hash值並自己計算字串的hash值然後進行對比是否一致。也就是說,“伺服器”不直接加密收到的字串,而是加密這個字串的一個hash值,這樣就避免了加密那些有規律的字串,從而降低被破解的機率。“客戶”自己傳送的字串,因此它自己可以計算字串的hash值,然後再把“伺服器”傳送過來的加密的hash值和自己計算的進行對比,同樣也能確定對方是否是“伺服器”。

 

【問題2】

在雙方的通訊過程中,“黑客”可以截獲傳送的加密了的內容,雖然他無法解密這個內容,但是他可以搗亂,例如把資訊原封不動的傳送多次,擾亂通訊過程。

〖解決方法〗

可以給通訊的內容加上一個序號或者一個隨機的值,如果“客戶”或者“伺服器”接收到的資訊中有之前出現過的序號或者隨機值,那麼說明有人在通訊過程中重發資訊內容進行搗亂,雙方會立刻停止通訊。有人可能會問,如果有人一直這麼搗亂怎麼辦?那不是無法通訊了? 答案是的確是這樣的,例如有人控制了你連線網際網路的路由器,他的確可以針對你。但是一些重要的應用,例如軍隊或者政府的內部網路,它們都不使用我們平時使用的公網,因此一般人不會破壞到他們的通訊。

 

【問題3】

在雙方的通訊過程中,“黑客”除了簡單的重複傳送截獲的訊息之外,還可以修改截獲後的密文修改後再傳送,因為修改的是密文,雖然不能完全控制訊息解密後的內容,但是仍然會破壞解密後的密文。因此傳送過程如果黑客對密文進行了修改,“客戶”和“伺服器”是無法判斷密文是否被修改的。雖然不一定能達到目的,但是“黑客”可以一直這樣碰碰運氣。

〖解決方法〗

在每次傳送資訊時,先對資訊的內容進行一個hash計算得出一個hash值,將資訊的內容和這個hash值一起加密後傳送。接收方在收到後進行解密得到明文的內容和hash值,然後接收方再自己對收到資訊內容做一次hash計算,與收到的hash值進行對比看是否匹配,如果匹配就說明資訊在傳輸過程中沒有被修改過。如果不匹配說明中途有人故意對加密資料進行了修改,立刻中斷通話過程後做其它處理。

 

3. 證書的構成和原理
3.1 證書的構成和原理

之前已經大概說了一個證書由什麼構成,但是沒有仔細進行介紹,這裡對證書的內容做一個詳細的介紹。先看下一個證書到底是個什麼東西,在windows下檢視一個證書時,介面是這樣的,我們主要關注一下Details Tab頁,其中的內容比較長,我滾動內容後後抓了三個圖,把完整的資訊顯示出來:

certificateDetails_thumb

 

文中首先解釋了加密解密的一些基礎知識和概念,然後通過一個加密通訊過程的例子說明了加密演算法的作用,以及數字證書的出現所起的作用。接著對數字證書做一個詳細的解釋,並討論一下windows中數字證書的管理,最後演示使用makecert生成數字證書。如果發現文中有錯誤的地方,或者有什麼地方說得不夠清楚,歡迎指出!

 

1、基礎知識

這部分內容主要解釋一些概念和術語,最好是先理解這部分內容。

1.1、公鑰密碼體制(public-key cryptography)

公鑰密碼體制分為三個部分,公鑰、私鑰、加密解密演算法,它的加密解密過程如下:

  • 加密:通過加密演算法和公鑰對內容(或者說明文)進行加密,得到密文。加密過程需要用到公鑰。
  • 解密:通過解密演算法和私鑰對密文進行解密,得到明文。解密過程需要用到解密演算法和私鑰。注意,由公鑰加密的內容,只能由私鑰進行解密,也就是說,由公鑰加密的內容,如果不知道私鑰,是無法解密的。

公鑰密碼體制的公鑰和演算法都是公開的(這是為什麼叫公鑰密碼體制的原因),私鑰是保密的。大家都以使用公鑰進行加密,但是隻有私鑰的持有者才能解密。在實際的使用中,有需要的人會生成一對公鑰和私鑰,把公鑰釋出出去給別人使用,自己保留私鑰。

 

1.2、對稱加密演算法(symmetric key algorithms)

在對稱加密演算法中,加密使用的金鑰和解密使用的金鑰是相同的。也就是說,加密和解密都是使用的同一個金鑰。因此對稱加密演算法要保證安全性的話,金鑰要做好保密,只能讓使用的人知道,不能對外公開。這個和上面的公鑰密碼體制有所不同,公鑰密碼體制中加密是用公鑰,解密使用私鑰,而對稱加密演算法中,加密和解密都是使用同一個金鑰,不區分公鑰和私鑰。

 

// 金鑰,一般就是一個字串或數字,在加密或者解密時傳遞給加密/解密演算法。前面在公鑰密碼體制中說到的公鑰、私鑰就是金鑰,公鑰是加密使用的金鑰,私鑰是解密使用的金鑰。

 
1.3、非對稱加密演算法(asymmetric key algorithms)

在非對稱加密演算法中,加密使用的金鑰和解密使用的金鑰是不相同的。前面所說的公鑰密碼體制就是一種非對稱加密演算法,他的公鑰和是私鑰是不能相同的,也就是說加密使用的金鑰和解密使用的金鑰不同,因此它是一個非對稱加密演算法。

 

1.4、RSA簡介

RSA是一種公鑰密碼體制,現在使用得很廣泛。如果對RSA本身有興趣的,後面看我有沒有時間寫個RSA的具體介紹。

RSA密碼體制是一種公鑰密碼體制,公鑰公開,私鑰保密,它的加密解密演算法是公開的。 由公鑰加密的內容可以並且只能由私鑰進行解密,並且由私鑰加密的內容可以並且只能由公鑰進行解密。也就是說,RSA的這一對公鑰、私鑰都可以用來加密和解密,並且一方加密的內容可以由並且只能由對方進行解密

 

1.5、簽名和加密

我們說加密,是指對某個內容加密,加密後的內容還可以通過解密進行還原。 比如我們把一封郵件進行加密,加密後的內容在網路上進行傳輸,接收者在收到後,通過解密可以還原郵件的真實內容。

這裡主要解釋一下簽名,簽名就是在資訊的後面再加上一段內容,可以證明資訊沒有被修改過,怎麼樣可以達到這個效果呢?一般是對資訊做一個hash計算得到一個hash值,注意,這個過程是不可逆的,也就是說無法通過hash值得出原來的資訊內容。在把資訊傳送出去時,把這個hash值加密後做為一個簽名和資訊一起發出去。 接收方在收到資訊後,會重新計算資訊的hash值,並和資訊所附帶的hash值(解密後)進行對比,如果一致,就說明資訊的內容沒有被修改過,因為這裡hash計算可以保證不同的內容一定會得到不同的hash值,所以只要內容一被修改,根據資訊內容計算的hash值就會變化。當然,不懷好意的人也可以修改資訊內容的同時也修改hash值,從而讓它們可以相匹配,為了防止這種情況,hash值一般都會加密後(也就是簽名)再和資訊一起傳送,以保證這個hash值不被修改。至於如何讓別人可以解密這個簽名,這個過程涉及到數字證書等概念,我們後面在說到數字證書時再詳細說明,這裡您先只需先理解簽名的這個概念。

 

2、一個加密通訊過程的演化

我們來看一個例子,現在假設“伺服器”和“客戶”要在網路上通訊,並且他們打算使用RSA(參看前面的RSA簡介)來對通訊進行加密以保證談話內容的安全。由於是使用RSA這種公鑰密碼體制,“伺服器”需要對外發布公鑰(演算法不需要公佈,RSA的演算法大家都知道),自己留著私鑰。“客戶”通過某些途徑拿到了“伺服器”釋出的公鑰,客戶並不知道私鑰。“客戶”具體是通過什麼途徑獲取公鑰的,我們後面再來說明,下面看一下雙方如何進行保密的通訊:

 

2.1 第一回合:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器

“客戶”->“伺服器”:????

因為訊息是在網路上傳輸的,有人可以冒充自己是“伺服器”來向客戶傳送資訊。例如上面的訊息可以被黑客截獲如下:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器

“客戶”->“黑客”:你好        // 黑客在“客戶”和“伺服器”之間的某個路由器上截獲“客戶”發給伺服器的資訊,然後自己冒充“伺服器”

“黑客”->“客戶”:你好,我是伺服器

因此“客戶”在接到訊息後,並不能肯定這個訊息就是由“伺服器”發出的,某些“黑客”也可以冒充“伺服器”發出這個訊息。如何確定資訊是由“伺服器”發過來的呢?有一個解決方法,因為只有伺服器有私鑰,所以如果只要能夠確認對方有私鑰,那麼對方就是“伺服器”。因此通訊過程可以改進為如下:

 

2.2 第二回合:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器

“客戶”->“伺服器”:向我證明你就是伺服器

“伺服器”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[私鑰|RSA]

// 意這裡約定一下,{} 表示RSA加密後的內容,[ | ]表示用什麼金鑰和演算法進行加密,後面的示例中都用這種表示方式,例如上面的 {你好,我是伺服器}[私鑰|RSA]  就表示用私鑰對“你好,我是伺服器”進行加密後的結果。

為了向“客戶”證明自己是“伺服器”, “伺服器”把一個字串用自己的私鑰加密,把明文和加密後的密文一起發給“客戶”。對於這裡的例子來說,就是把字串 “你好,我是伺服器”和這個字串用私鑰加密後的內容 {你好,我是伺服器}[私鑰|RSA] 發給客戶。

“客戶”收到資訊後,她用自己持有的公鑰解密密文,和明文進行對比,如果一致,說明資訊的確是由伺服器發過來的。也就是說“客戶”把 {你好,我是伺服器}[私鑰|RSA] 這個內容用公鑰進行解密,然後和“你好,我是伺服器”對比。因為由“伺服器”用私鑰加密後的內容,由並且只能由公鑰進行解密,私鑰只有“伺服器”持有,所以如果解密出來的內容是能夠對得上的,那說明資訊一定是從“伺服器”發過來的。

假設“黑客”想冒充“伺服器”:

“黑客”->“客戶”:你好,我是伺服器

“客戶”->“黑客”:向我證明你就是伺服器

“黑客”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[???|RSA]    //這裡黑客無法冒充,因為他不知道私鑰,無法用私鑰加密某個字串後傳送給客戶去驗證。

“客戶”->“黑客”:????

由於“黑客”沒有“伺服器”的私鑰,因此它傳送過去的內容,“客戶”是無法通過伺服器的公鑰解密的,因此可以認定對方是個冒牌貨!

到這裡為止,“客戶”就可以確認“伺服器”的身份了,可以放心和“伺服器”進行通訊,但是這裡有一個問題,通訊的內容在網路上還是無法保密。為什麼無法保密呢?通訊過程不是可以用公鑰、私鑰加密嗎?其實用RSA的私鑰和公鑰是不行的,我們來具體分析下過程,看下面的演示:

 

2.3 第三回合:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器

“客戶”->“伺服器”:向我證明你就是伺服器

“伺服器”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[私鑰|RSA]

“客戶”->“伺服器”:{我的帳號是aaa,密碼是123,把我的餘額的資訊發給我看看}[公鑰|RSA]

“伺服器”->“客戶”:{你的餘額是100元}[私鑰|RSA]

注意上面的的資訊 {你的餘額是100元}[私鑰],這個是“伺服器”用私鑰加密後的內容,但是我們之前說了,公鑰是釋出出去的,因此所有的人都知道公鑰,所以除了“客戶”,其它的人也可以用公鑰對{你的餘額是100元}[私鑰]進行解密。所以如果“伺服器”用私鑰加密發給“客戶”,這個資訊是無法保密的,因為只要有公鑰就可以解密這內容。然而“伺服器”也不能用公鑰對傳送的內容進行加密,因為“客戶”沒有私鑰,傳送個“客戶”也解密不了。

這樣問題就又來了,那又如何解決呢?在實際的應用過程,一般是通過引入對稱加密來解決這個問題,看下面的演示:

 

2.4 第四回合:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器

“客戶”->“伺服器”:向我證明你就是伺服器

“伺服器”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[私鑰|RSA]

“客戶”->“伺服器”:{我們後面的通訊過程,用對稱加密來進行,這裡是對稱加密演算法和金鑰}[公鑰|RSA]    //藍色字型的部分是對稱加密的演算法和金鑰的具體內容,客戶把它們傳送給伺服器。

“伺服器”->“客戶”:{OK,收到!}[金鑰|對稱加密演算法]

“客戶”->“伺服器”:{我的帳號是aaa,密碼是123,把我的餘額的資訊發給我看看}[金鑰|對稱加密演算法]

“伺服器”->“客戶”:{你的餘額是100元}[金鑰|對稱加密演算法]

在上面的通訊過程中,“客戶”在確認了“伺服器”的身份後,“客戶”自己選擇一個對稱加密演算法和一個金鑰,把這個對稱加密演算法和金鑰一起用公鑰加密後傳送給“伺服器”。注意,由於對稱加密演算法和金鑰是用公鑰加密的,就算這個加密後的內容被“黑客”截獲了,由於沒有私鑰,“黑客”也無從知道對稱加密演算法和金鑰的內容。

由於是用公鑰加密的,只有私鑰能夠解密,這樣就可以保證只有伺服器可以知道對稱加密演算法和金鑰,而其它人不可能知道(這個對稱加密演算法和金鑰是“客戶”自己選擇的,所以“客戶”自己當然知道如何解密加密)。這樣“伺服器”和“客戶”就可以用對稱加密演算法和金鑰來加密通訊的內容了。

 

總結一下,RSA加密演算法在這個通訊過程中所起到的作用主要有兩個:

  • 因為私鑰只有“伺服器”擁有,因此“客戶”可以通過判斷對方是否有私鑰來判斷對方是否是“伺服器”。
  • 客戶端通過RSA的掩護,安全的和伺服器商量好一個對稱加密演算法和金鑰來保證後面通訊過程內容的安全。

如果這裡您理解了為什麼不用RSA去加密通訊過程,而是要再確定一個對稱加密演算法來保證通訊過程的安全,那麼就說明前面的內容您已經理解了。(如果不清楚,再看下2.3和2.4,如果還是不清楚,那應該是我們說清楚,您可以留言提問。)

到這裡,“客戶”就可以確認“伺服器”的身份,並且雙方的通訊內容可以進行加密,其他人就算截獲了通訊內容,也無法解密。的確,好像通訊的過程是比較安全了。

 

但是這裡還留有一個問題,在最開始我們就說過,“伺服器”要對外發布公鑰,那“伺服器”如何把公鑰傳送給“客戶”呢?我們第一反應可能會想到以下的兩個方法:

a)把公鑰放到網際網路的某個地方的一個下載地址,事先給“客戶”去下載。

b)每次和“客戶”開始通訊時,“伺服器”把公鑰發給“客戶”。

但是這個兩個方法都有一定的問題,

對於a)方法,“客戶”無法確定這個下載地址是不是“伺服器”釋出的,你憑什麼就相信這個地址下載的東西就是“伺服器”釋出的而不是別人偽造的呢,萬一下載到一個假的怎麼辦?另外要所有的“客戶”都在通訊前事先去下載公鑰也很不現實。

對於b)方法,也有問題,因為任何人都可以自己生成一對公鑰和私鑰,他只要向“客戶”傳送他自己的私鑰就可以冒充“伺服器”了。示意如下:

“客戶”->“黑客”:你好           //黑客截獲“客戶”發給“伺服器”的訊息

“黑客”->“客戶”:你好,我是伺服器,這個是我的公鑰    //黑客自己生成一對公鑰和私鑰,把公鑰發給“客戶”,自己保留私鑰

“客戶”->“黑客”:向我證明你就是伺服器

“黑客”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[黑客自己的私鑰|RSA]      //客戶收到“黑客”用私鑰加密的資訊後,是可以用“黑客”發給自己的公鑰解密的,從而會誤認為“黑客”是“伺服器”

因此“黑客”只需要自己生成一對公鑰和私鑰,然後把公鑰傳送給“客戶”,自己保留私鑰,這樣由於“客戶”可以用黑客的公鑰解密黑客的私鑰加密的內容,“客戶”就會相信“黑客”是“伺服器”,從而導致了安全問題。這裡問題的根源就在於,大家都可以生成公鑰、私鑰對,無法確認公鑰對到底是誰的。 如果能夠確定公鑰到底是誰的,就不會有這個問題了。例如,如果收到“黑客”冒充“伺服器”發過來的公鑰,經過某種檢查,如果能夠發現這個公鑰不是“伺服器”的就好了。

為了解決這個問題,數字證書出現了,它可以解決我們上面的問題。先大概看下什麼是數字證書,一個證書包含下面的具體內容:

  • 證書的釋出機構
  • 證書的有效期
  • 公鑰
  • 證書所有者(Subject)
  • 簽名所使用的演算法
  • 指紋以及指紋演算法

證書的內容的詳細解釋會在後面詳細解釋,這裡先只需要搞清楚一點,數字證書可以保證數字證書裡的公鑰確實是這個證書的所有者(Subject)的,或者證書可以用來確認對方的身份。也就是說,我們拿到一個數字證書,我們可以判斷出這個數字證書到底是誰的。至於是如何判斷的,後面會在詳細討論數字證書時詳細解釋。現在把前面的通訊過程使用數字證書修改為如下:

 

2.5 第五回合:

“客戶”->“伺服器”:你好

“伺服器”->“客戶”:你好,我是伺服器,這裡是我的數字證書        //這裡用證書代替了公鑰

“客戶”->“伺服器”:向我證明你就是伺服器

“伺服器”->“客戶”:你好,我是伺服器 {你好,我是伺服器}[私鑰|RSA]

注意,上面第二次通訊,“伺服器”把自己的證書發給了“客戶”,而不是傳送公鑰。“客戶”可以根據證書校驗這個證書到底是不是“伺服器”的,也就是能校驗這個證書的所有者是不是“伺服器”,從而確認這個證書中的公鑰的確是“伺服器”的。後面的過程和以前是一樣,“客戶”讓“伺服器”證明自己的身份,“伺服器”用私鑰加密一段內容連同明文一起發給“客戶”,“客戶”把加密內容用數字證書中的公鑰解密後和明文對比,如果一致,那麼對方就確實是“伺服器”,然後雙方協商一個對稱加密來保證通訊過程的安全。到這裡,整個過程就完整了,我們回顧一下:

 

2.6 完整過程:

step1: “客戶”向服務端傳送一個通訊請求

“客戶”->“伺服器”:你好

step2: “伺服器”向客戶傳送自己的數字證書。證書中有一個公鑰用來加密資訊,私鑰由“伺服器”持有

“伺服器”->“客戶”:你好,我是伺服器,這裡是我的數字證書

 

step3: “客戶”收到“伺服器”的證書後,它會去驗證這個數字證書到底是不是“伺服器”的,數字證書有沒有什麼問題,數字證書如果檢查沒有問題,就說明數字證書中的公鑰確實是“伺服器”的。檢查數字證書後,“客戶”會傳送一個隨機的字串給“伺服器”用私鑰去加密,伺服器把加密的結果返回給“客戶”,“客戶”用公鑰解密這個返回結果,如果解密結果與之前生成的隨機字串一致,那說明對方確實是私鑰的持有者,或者說對方確實是“伺服器”。

“客戶”->“伺服器”:向我證明你就是伺服器,這是一個隨機字串     //前面的例子中為了方便解釋,用的是“你好”等內容,實際情況下一般是隨機生成的一個字串。

“伺服器”->“客戶”:{一個隨機字串}[私鑰|RSA]

 

step4: 驗證“伺服器”的身份後,“客戶”生成一個對稱加密演算法和金鑰,用於後面的通訊的加密和解密。這個對稱加密演算法和金鑰,“客戶”會用公鑰加密後傳送給“伺服器”,別人截獲了也沒用,因為只有“伺服器”手中有可以解密的私鑰。這樣,後面“伺服器”和“客戶”就都可以用對稱加密演算法來加密和解密通訊內容了。

“伺服器”->“客戶”:{OK,已經收到你發來的對稱加密演算法和金鑰!有什麼可以幫到你的?}[金鑰|對稱加密演算法]

“客戶”->“伺服器”:{我的帳號是aaa,密碼是123,把我的餘額的資訊發給我看看}[金鑰|對稱加密演算法]

“伺服器”->“客戶”:{你好,你的餘額是100元}[金鑰|對稱加密演算法]

…… //繼續其它的通訊

 

2.7 其它問題:

上面的過程已經十分接近HTTPS的真實通訊過程了,完全可以按照這個過程去理解HTTPS的工作原理。但是我為了方便解釋,上面有些細節沒有說到,有興趣的人可以看下這部分的內容。可以跳過不看,無關緊要。

 

【問題1】

上面的通訊過程中說到,在檢查完證書後,“客戶”傳送一個隨機的字串給“伺服器”去用私鑰加密,以便判斷對方是否真的持有私鑰。但是有一個問題,“黑客”也可以傳送一個字串給“伺服器”去加密並且得到加密後的內容,這樣對於“伺服器”來說是不安全的,因為黑客可以傳送一些簡單的有規律的字串給“伺服器”加密,從而尋找加密的規律,有可能威脅到私鑰的安全。所以說,“伺服器”隨隨便便用私鑰去加密一個來路不明的字串並把結果傳送給對方是不安全的。

〖解決方法〗

每次收到“客戶”發來的要加密的的字串時,“伺服器”並不是真正的加密這個字串本身,而是把這個字串進行一個hash計算,加密這個字串的hash值(不加密原來的字串)後傳送給“客戶”,“客戶”收到後解密這個hash值並自己計算字串的hash值然後進行對比是否一致。也就是說,“伺服器”不直接加密收到的字串,而是加密這個字串的一個hash值,這樣就避免了加密那些有規律的字串,從而降低被破解的機率。“客戶”自己傳送的字串,因此它自己可以計算字串的hash值,然後再把“伺服器”傳送過來的加密的hash值和自己計算的進行對比,同樣也能確定對方是否是“伺服器”。

 

【問題2】

在雙方的通訊過程中,“黑客”可以截獲傳送的加密了的內容,雖然他無法解密這個內容,但是他可以搗亂,例如把資訊原封不動的傳送多次,擾亂通訊過程。

〖解決方法〗

可以給通訊的內容加上一個序號或者一個隨機的值,如果“客戶”或者“伺服器”接收到的資訊中有之前出現過的序號或者隨機值,那麼說明有人在通訊過程中重發資訊內容進行搗亂,雙方會立刻停止通訊。有人可能會問,如果有人一直這麼搗亂怎麼辦?那不是無法通訊了? 答案是的確是這樣的,例如有人控制了你連線網際網路的路由器,他的確可以針對你。但是一些重要的應用,例如軍隊或者政府的內部網路,它們都不使用我們平時使用的公網,因此一般人不會破壞到他們的通訊。

 

【問題3】

在雙方的通訊過程中,“黑客”除了簡單的重複傳送截獲的訊息之外,還可以修改截獲後的密文修改後再傳送,因為修改的是密文,雖然不能完全控制訊息解密後的內容,但是仍然會破壞解密後的密文。因此傳送過程如果黑客對密文進行了修改,“客戶”和“伺服器”是無法判斷密文是否被修改的。雖然不一定能達到目的,但是“黑客”可以一直這樣碰碰運氣。

〖解決方法〗

在每次傳送資訊時,先對資訊的內容進行一個hash計算得出一個hash值,將資訊的內容和這個hash值一起加密後傳送。接收方在收到後進行解密得到明文的內容和hash值,然後接收方再自己對收到資訊內容做一次hash計算,與收到的hash值進行對比看是否匹配,如果匹配就說明資訊在傳輸過程中沒有被修改過。如果不匹配說明中途有人故意對加密資料進行了修改,立刻中斷通話過程後做其它處理。

 

3. 證書的構成和原理
3.1 證書的構成和原理

之前已經大概說了一個證書由什麼構成,但是沒有仔細進行介紹,這裡對證書的內容做一個詳細的介紹。先看下一個證書到底是個什麼東西,在windows下檢視一個證書時,介面是這樣的,我們主要關注一下Details Tab頁,其中的內容比較長,我滾動內容後後抓了三個圖,把完整的資訊顯示出來:

2009121816032340

 

上面的步驟結束後,會又彈出一個對話方塊,裡面有三個單選按鈕如下:

  • My user account
  • Service account
  • Computer account

可以選擇第一或者第三個選項,用來檢視當前使用者的證書或整個計算裡面安裝的證書。我們這裡就預設選擇第一個,平時一般安裝證書的時候都會給所有使用者安裝,所以選擇第一個和第三個選項看到的證書會差不多。我們在左邊的導航樹中選中受信任的證書釋出機構(Trusted Root Certificate Authorities),然後點選下面的證書(Certificates),在右邊的區域中就可以看到所有的受信任的證書釋出機構的證書。

trustedcaAuth_thumb

 

注意上面的圖片中,右邊我們選中的這個證書釋出機構”SecureTrust CA”,我們前面在第3章3.2節中舉例子的時候,就是去向這個證書釋出機構申請的證書,由於我們申請的證書是這個機構釋出的,所以應用程式在檢查我們的證書的釋出機構時(會檢查我們證書的簽名,確認是該機構釋出的證書),就會發現是可以信任的證書釋出機構,從而就會相信我們證書的真實性。

刪除數字證書很簡單,直接在右邊的列表中右鍵然後刪除就可以了。

數字證書的安裝也比較簡單,直接雙擊數字證書檔案,會開啟數字證書,對話方塊下面會有一個Install Certificate按鈕,點選後就可以根據嚮導進行安裝,如下圖所示:

installCertificate_thumb_1

這個證書是我自己生成的測試證書,在證書的匯入嚮導裡面,它會讓你選擇匯入到什麼位置,如果是一個我們自己信任的證書釋出機構自己的證書,只要匯入到Certificate Authorities就可以了。Trusted Root Certificate Authorities, Intermediate Certification Authorities, Third-Party Root Certification Authorities 都是可以的,他們只是對證書的釋出機構做了一個分類,還有一些其它的證書型別,例如Personal(個人證書)等等,具體就不介紹了。安裝的時候一般來說可以用預設的選擇項一直”下一步”到底。

4.2 如何自己建立證書

每個證書釋出機構都有自己的用來建立證書的工具,當然,具體他們怎麼去建立一個證書的我也不太清楚,不同型別的證書都有一定的格式和規範,我沒有仔細去研究過這部分內容。 微軟為我們提供了一個用來建立證書的工具makecert.exe,在安裝Visual Studio的時候會安裝上。如果沒有安裝也無所謂,可以上網去下一個,搜尋makecert就可以了。可以直接從我的部落格下載,這是連結

向一些正規的證書釋出機構申請證書一般是要收費的(因為別人要花時間檢查你的身份,確認有沒有同名的證書等等),這裡我們看下如何自己建立一個證書,為後面在IIS中配置Https做準備。

我們用到的是makecert這個工具,微軟有很詳細的使用幫助,我這裡只做一個簡單的解釋,詳細的各種引數和使用方法請檢視MSDN的makecert的幫助。但是裡面有些引數說得不夠清楚,而且還有遺漏的,可以參看我後面的解釋作為一個補充。

 

先看下makecert最簡單的使用方式:

makecert.exe test.cer

上面的命令會在makecert.exe所在的目錄生成一個證書檔案test.cer的數字證書檔案。可以雙擊證書開啟,看看證書的內容如下:

testCertificate1_thumb (1)

證書的釋出機構是”Root Agency”,證書的主題(證書釋出給誰)是”Joe’s-Software-Emporium”,因為我們沒有指定把證書釋出給誰,makecert自己給我們隨便生成了一個公司的名字。另外還指定了公鑰、簽名演算法(用來解密簽名)、指紋和指紋演算法等。

注意,因為這個證書是由微軟的工具生成的,嚴格來說它沒什麼釋出機構,所以微軟虛擬了一個叫做”Root Agency”的釋出機構,預設情況下,windows裡面安裝了這個所謂的證書釋出機構的證書,但是這證書預設情況下不是受信任的,原因很簡單,這樣做大家都可以用makecert來製作合法的數字證書了。如果我們自己硬是要,也可以把它設定為受信任的。

 

下面我們看下其它的引數,比如我們要給網站 www.jefferysun.com 生成一個證書MyCA.cer,假設我們把makecert.exe放在C:盤下,命令列如下:

makecert -r -pe -n “CN=10.30.146.206” -b 01/01/2000 -e 01/01/2036 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange -sp “Microsoft RSA SChannel Cryptographic Provider” -sy 12

C:\> makecert.exe –pe -r  –n  “CN=www.jefferysun.com” -ss my -sr LocalMachine -a sha1 -len 2048  MyCA.cer

解釋一下makecert的常用引數的意思:

  • -n 指定主題的名字,這個是有固定的格式的, CN=主題名字 ,CN應該是Certificate Name的縮寫。我這裡的主題的名字就是我們的IIS所在機器的IP。這裡可以指定一些主題的其它附加資訊,例如 O= *** 表示組織資訊等等。
  • -r 建立自簽署證書,意思就是說在生成證書時,將證書的釋出機構設定為自己。
  • -pe 將所生成的私鑰標記為可匯出。注意,伺服器傳送證書給客戶端的時候,客戶端只能從證書裡面獲取公鑰,私鑰是無法獲取的。如果我們指定了這個引數,證書在安裝在機器上後,我們還可以從證書中匯出私鑰,預設情況下是不能匯出私鑰的。正規的途徑釋出的證書,是不可能讓你匯出私鑰的。
  • -b –e 證書的有效期
  • -ss 證書的儲存名稱,就是windows證書儲存區的目錄名,如果不存在在的話就建立一個。
  • -sr 證書的儲存位置,只有currentuser(預設值)或 localmachine兩個值。
  • -sv 指定儲存私鑰的檔案,檔案裡面除了包含私鑰外,其實也包含了證書。這個檔案是需要保密的,這個檔案在服務端配置時是需要用到的。
  • 這個CN=10.30.146.206要與自己的伺服器相對應,要不然在配置HTTPS的時候會出現錯誤
  • -a 指定簽名演算法,必須是md5或rsa1。(還記得簽名演算法的作用不?可以看一下3章的第1節中關於簽名演算法的介紹)
  • -in 指定證書釋出機構的名稱
  • -len 這個引數在中文的幫助文件中好像沒有提到,但是這個其實很重要,用於指定公鑰的位數,越大越安全,預設值是1024,推薦2048。我試了下,這個不為1024的倍數也是可以的。

 

https://kb.cnblogs.com/page/194742/

http://blog.jobbole.com/74614/?utm_source=blog.jobbole.com&utm_medium=relatedPosts

 

相關文章