原始程式碼概觀 (CNG 範例)
更新: 2008 年 7 月
本概觀提供您 Cryptography Next Generation (CNG) 安全通訊範例中,有關各種程式碼項目之間互動的高階描述。
其中會討論範例的下列各方面:
應用程式
檔案
類別
安全性版本
工作階段概觀
密碼編譯金鑰 (版本 2-5)
透過公用通道交換的數位簽章 (版本 3)
透過私用通道交換的數位簽章 (版本 4)
工作階段的終止 (版本 5)
其他注意事項
CNG 範例的限制
應用程式
本範例包含 3 個獨立的主控台應用程式:Alice、Bob 和 Mallory。每個應用程式是建置為獨立的 Visual Studio 專案,並包含一個主要檔案和 3 個共用檔案。下表顯示這些應用程式和其檔案。
應用程式 (專案) 名稱 |
檔案 |
---|---|
Alice |
|
Bob |
|
Mallory |
|
檔案
下列各節的表格摘要說明每個應用程式所使用的類別和方法,並以出現在原始程式碼中的順序列出。
Alice.cs、Bob.cs 和 Mallory.cs
類別、方法或 全域變數名稱 |
用途 |
---|---|
CNG_SecureCommunicationExample |
整個專案範圍的部分類別。 |
MyColor OtherColor fDisplaySendMessage |
全域變數。 |
Main |
每個應用程式的程式進入點。這個方法會處理下列作業:
|
Run |
方法:用於呼叫 InitializeOptions 方法並建立選取的安全性案例。 |
Utilities.cs
類別、方法或 全域變數名稱 |
用途 |
---|---|
CNG_SecureCommunicationExample |
整個專案範圍的部分類別。 |
Version fVerbose fMallory |
全域變數。 |
Autoloader |
方法:由 Alice 呼叫以用來載入 Bob.exe 和 Mallory.exe 應用程式。 |
InitConsole |
方法:用於處理使用者介面功能表和應用程式層級的訊息。 |
SplashScreen |
方法:用於提供主控台視窗標題。 |
ReadALine |
公用程式方法:用於讀取主控台的使用者輸入行。 |
ReadAChar |
公用程式方法:用於顯示問題並提示使用者輸入是或否的答案。 |
InitializeOptions |
方法:用於顯示選項並提示使用者進行選取。這個方法也會設定 Version、fVerbose 和 fMallory 全域旗標。 |
Display(string s) |
兩個 Display 方法中的第一個。這個方法會傳遞字串和 MyColor 變數給第二個 Display 方法。 |
Display(string DisplayString, int color) |
兩個 Display 方法中的第二個。這個方法會將 Console.WriteLine 陳述式換行並提供輸出行的色彩支援。 |
如需這些類別、方法和變數的詳細資訊,請參閱公用程式類別的程式碼分析 (CNG 範例)。
ChannelManager.cs
類別、方法或 全域變數名稱 |
用途 |
---|---|
CNG_SecureCommunicationExample |
整個專案範圍的部分類別。 |
AppControl |
方法:用於提供內部應用程式控制並同步處理這 3 個主控台應用程式。 Alice 會使用這個方法傳送程式選項 (Version 和 fVerbose 旗標) 給 Bob 和 Mallory。 AppControl 並不是供傳訊用的方法,其內容未經過加密或簽署,也不會呼叫 Communicator 類別。 |
SendChannelName ReceiveChannelName |
方法:用於從 PublicChannel 具名管道切換至 AliceAndBobChannel 和 AliceAndBobChannel1 具名管道。這些方法可讓 CNG 範例概觀中討論的蓄意安全性破壞得以進行。 |
ChannelManager |
類別:用於提供應用程式的處理序間通訊架構。 |
如需這些類別和方法的詳細資訊,請參閱 ChannelManager 類別的程式碼分析 (CNG 範例)。
Communicator.cs
類別、方法或 全域變數名稱 |
用途 |
---|---|
CNG_SecureCommunicationExample |
整個專案範圍的部分類別。 |
Communicator |
類別:用於封裝所有密碼編譯函式。這個類別會處理 Alice、Bob 和 Mallory 間的所有訊息,但不會處理 ChannelManagerAppControl 方法所傳送的訊息。 |
m_DSKey m_ECDH_Cng m_ECDH_local_publicKey_XML m_ECDH_remote_publicKey ChMgr |
類別變數。 |
Communicator |
方法:用於建構 Communicator 物件。 |
Dispose |
方法:用於釋放私下持有的資源。 |
StoreDSKey |
方法:用於儲存數位簽章金鑰。 |
Send_or_Receive_PublicCryptoKey |
方法:用於提供金鑰交換支援。 |
iv ciphertext signature |
私用類別變數:用於加密純文字訊息。這些變數是在 ReceiveMessage() 方法附近宣告的。 |
ReceiveMessage |
方法:用於接收純文字或加密訊息 (視安全性版本而定)。 |
SendMessage |
方法:用於接收純文字訊息,並以純文字或加密格式將訊息傳送出去 (視安全性版本而定)。 |
如需這些類別、方法和變數的詳細資訊,請參閱 Communicator 類別的程式碼分析 (CNG 範例)。
類別
每個專案包含 3 個類別:
public partial class CNG_SecureCommunicationExample
這個類別會提供給全部的 3 個專案檔,包含 Alice、Bob 和 Mallory 應用程式。編譯過後,CNG_SecureCommunicationExample 類別會包含 3 個專案檔的所有類別、變數和方法。如需部分類別的詳細資訊,請參閱部分類別和方法 (C# 程式設計手冊)。
internal sealed class ChannelManager
這個類別提供具名管道的支援。每個專案會在程式執行期間的不同時間建立數個 ChannelManager 執行個體。這個類別的詳細資訊可以在 ChannelManager 類別的程式碼分析 (CNG 範例) 中找到。
internal sealed class Communicator
這個類別提供加密和解密的支援。每個專案會在程式執行期間的不同時間建立數個 Communicator 執行個體。這個類別的詳細資訊可以在 Communicator 類別的程式碼分析 (CNG 範例) 中找到。
安全性版本
原始程式碼支援 CNG 範例概觀中陳述的安全性案例。它所實作的下列 5 個版本,各代表即時訊息 (IM) 工具的 5 個安全性層級:
版本 1:使用純文字訊息和具名管道。
版本 2:使用加密訊息。
版本 3:使用加密訊息和數位簽章。
版本 4:使用加密訊息和私密數位簽章。
版本 5:在發生安全性錯誤時終止應用程式。
注意事項: |
---|
本主題的其餘部分會以編號代表這些版本。除此之外,依據前後文而定,名稱 "Alice"、"Bob" 和 "Mallory" 可能代表範例案例中提及的 3 位人員或是 3 個 Visual Studio 應用程式。 |
工作階段概觀
Alice、Bob 和 Mallory 每個都有各自的 Main 方法和 Run 方法。
Main 方法會同步處理應用程式並執行下列功能:
顯示啟動顯示畫面。
要求使用者選擇工作階段選項 (僅適用於 Alice)。
傳送工作階段選項給 Bob 和 Mallory (僅適用於 Alice)。
接收來自 Alice 的工作階段選項 (僅適用於 Bob 和 Mallory)。
呼叫 Run 方法執行要求的安全性工作階段。
Run 方法會執行安全性案例。
每個工作階段即描述前一節所列的一個版本。
當 Alice、Bob 和 Mallory 進入其 Run 方法時,即會啟動工作階段,當他們返回其 Main 方法時,即會結束工作階段。
Alice、Bob 和 Mallory 在同一個工作階段期間,一定是執行相同版本的。
Alice 會啟始在工作階段期間發生的所有交易。Mallory 會回應 Alice 並啟始與 Bob 的交易。Bob 則只會回應。
Alice 和 Bob 的原始程式碼非常相似。主要的差異在於 Alice 會啟始每個工作階段並做為管道伺服器,而 Bob 會做為管道用戶端。Mallory 的程式碼較為複雜,因為要管理兩個獨立的管道:一個通向 Alice,而一個通向 Bob。
Main 方法
Alice 會在其 Main 方法的開頭呼叫 InitializeOptions 方法,並接收使用者的工作階段選項 (Version、fVerbose 和 fMallory)。她會使用 AppControl 方法傳送選項給 Bob 和 Mallory,而後面兩者會使用 AppControl 方法接收這些選項。如果使用者決定藉由輸入 "x" 關閉應用程式,則 Alice 的 AppControl 方法會傳送字串 "exit" 給 Bob 和 Mallory,而非工作階段選項。
在這 3 個應用程式接收到工作階段後,就會呼叫其 Run 方法。
Run 方法
Alice、Bob 和 Mallory 會藉由執行下列步驟,執行要求的工作階段:
Alice 會呼叫 SendChannelName 方法,該方法使用名為 PublicChannel 的通道。她會傳送新通道名稱 (AliceAndBobChannel) 給 Bob。
如果 fMallory 旗標是設為 true,Mallory 會接聽 PublicChannel 並攔截來自 Alice 的新通道名稱 (AliceAndBobChannel)。接著傳送不同的通道名稱 (AliceAndBobChannel1) 給 Bob。
Alice 和 Bob 會以自己的名稱建立 Communicator 物件。這些物件是在 C# using 陳述式內建立的,並會於 Run 方法的結尾進行處置。
Alice 會初始化為管道伺服器:
using (Communicator Alice = new Communicator("server", NewChannelName))
Bob 會初始化為管道用戶端:
using (Communicator Bob = new Communicator("client", NewChannelName))
Mallory 會建立兩個 Communicator 物件:MalloryAlice 和 MalloryBob。Mallory 會針對 Alice 初始化為管道用戶端:
using (Communicator MalloryAlice = new Communicator("client", AliceChannelName))
Mallory 會針對 Bob 初始化為管道伺服器:
using (Communicator MalloryBob = new Communicator("server", BobChannelName"))
Communicator 類別建構函式會接受通道名稱,並建立稱為 ChMgr 的長期公用 ChannelManager 物件:
ChMgr = new ChannelManager(mode, ChannelName);
ChannelManager 建構函式會接受通道名稱,並建立對應的具名管道。
注意事項: 此時,Alice 和 Mallory 是透過名為 AliceAndBobChannel 的管道通訊,而 Mallory 和 Bob 則是透過名為 AliceAndBobChannel1 的管道通訊。
AliceAndBobChannel 和 AliceAndBobChannel1 是長期通道,在安全性案例結束前 (也就是 Run 方法的結尾),都會持續開啟。
fVersion 旗標 (負責控制安全性版本) 和 fMallory 旗標 (負責控制 Mallory 的介入) 的值會決定接下來發生的事:
在版本 3 中,Alice 會透過 PublicChannel 傳送數位簽章金鑰給 Bob。他們會使用這個數位簽章金鑰來簽署金鑰和訊息。如果 fMallory 是 true,Mallory 會攔截數位簽章金鑰並用來簽署他傳送給 Alice 和 Bob 的金鑰和訊息。
在版本 4 和 5 中,Alice 會傳送兩個數位簽章金鑰給 Bob。數位簽章金鑰 1 跟 Alice 在版本 3 中傳送的金鑰一樣。數位簽章金鑰 2 是 Mallory 不知道的秘密數位簽章金鑰。
Alice 和 Bob 在版本 2 到 5 都會交換公開密碼編譯金鑰。如果 fMallory 是 true,Mallory 會攔截他們的公開金鑰並以自己的金鑰取代。
Alice 和 Bob 會交換訊息。如果 fMallory 是 true,Mallory 會攔截、變更和重新傳送 Alice 和 Bob 的訊息。
在 Alice 和 Bob 完成彼此的交談後,您會收到提示,要求您傳送自己的訊息。這可以讓您看到您訊息的加密方式,以及 Mallory 又是如何變更這些訊息。當您完成時,請按 ENTER 將控制權傳回給 Alice。
Alice 會結束工作階段。Alice、Bob 和 Mallory 的 Run 方法會將控制權傳回給其 Main 方法,而範例會重新啟動。
密碼編譯金鑰 (版本 2-5)
版本 2 到 5 藉由使用先進加密標準 (Advanced Encryption Standard,AES) 演算法來加密訊息。在 Alice、Bob 和 Mallory 的 Run 方法中,密碼編譯金鑰交換是於下列程式碼陳述式後實作的:
if (2 <= Version)
密碼編譯金鑰是由長期公用 ChannelManager 物件 (ChMgr) 傳送的,該物件則是由 Communicator 類別建構函式所建立的。
下列兩個程式碼陳述式顯示 Alice 傳送密碼編譯金鑰的方式和 Bob 的接收方式:
Alice.Send_or_Receive_PublicCryptoKey("send", MyColor);
Bob.Send_or_Receive_PublicCryptoKey("receive", OtherColor);
第二個參數所定義的色彩,是接收應用程式在顯示密碼編譯金鑰內容時應該使用的色彩。
AES 的實作被視為是數學上的不可能任務。但是 AES 卻沒有對攔截式攻擊提供任何保護。在 AES 提供這麼強大的加密功能的同時,看到 Mallory 仍可以解密 Alice 和 Bob 的訊息,似乎有點矛盾。會發生這個情況的原因在於 Mallory 具有 Alice 和 Bob 的共用密碼協議。Mallory 的金鑰攔截和取代作業,讓強大的 AES 加密毫無作用。
使用密碼編譯金鑰而缺乏驗證,帶來了安全性的假象。Alice 和 Bob 認為使用版本 2 就具有安全的訊息傳輸規劃,但實際上,早在他們傳送第一個訊息時安全性就遭到破壞。
Alice 和 Bob 的公司不知道攻擊是來自公司內部或外部,所以設計版本 3 的 IM 工具以探索攻擊來源。
透過公用通道交換的數位簽章 (版本 3)
版本 3 藉由使用數位簽章來簽署金鑰和訊息,以修正版本 2 的安全性缺陷。在 Alice、Bob 和 Mallory 的 Run 方法中,數位簽章金鑰交換是於下列程式碼陳述式後實作的:
if (3 <= Version)
數位簽章金鑰是透過與密碼編譯金鑰相同的長期公用通道而傳送的。下列程式碼負責傳送數位簽章金鑰:
Alice.ChMgr.SendMessage(dsKeyBlob);
注意事項: |
---|
用於傳送數位簽章金鑰的 ChannelManager 執行個體 (ChMgr) 是 Alice Communicator 物件的成員。 |
Alice 和 Bob 會將數位簽章金鑰儲存做為其 Communicator 物件的私用成員:
Alice.StoreDSKey(DSKey);
Bob.StoreDSKey(DSKey);
可惜的是,Mallory 可以從 PublicChannel 輕鬆複製該數位簽章並儲存:
Mallory.StoreDSKey(DSKey);
當 Alice 和 Bob 收到彼此的簽署訊息時,數位簽章可以跟訊息完全相符。這是因為 Mallory 用來進行簽署的數位簽章金鑰,跟 Alice 和 Bob 所使用的一樣。
在版本 3 中,密碼編譯金鑰和數位簽章都是透過公司網路上的公用通道而交換的。Alice 和 Bob 所服務的公司懷疑是公司內部的人員在進行竊取作業,於是建立版本 4 來證實這個想法。
透過私用通道交換的數位簽章 (版本 4)
版本 4 使用兩個數位簽章金鑰:版本 3 所使用的金鑰,而第二個是透過私用通道傳送的秘密金鑰。第一個金鑰現在會視為假的數位金鑰,是針對竊賊設下的陷阱。第二個金鑰則供 Alice 和 Bob 用來數位簽署其密碼編譯金鑰和訊息。
只有 Alice 和 Bob 接獲版本 4 的 IM 軟體,Mallory 會繼續使用版本 3。因此,Mallory 永遠不會發現他使用的數位簽章是無效的。然而,Alice 和 Bob 的 IM 工具會針對他們收到的每個單一金鑰和訊息,顯示安全性警告。
版本 4 也證實密碼編譯金鑰和訊息都已遭到攔截。這表示發生了攔截式攻擊,也說明甚至在傳送密碼編譯金鑰前即已經啟動這個攻擊。因此,某位可以存取公司 PublicChannel 的公司員工一定是在 Bob 前登入的。聰明的使用秘密數位簽章金鑰透露出 Mallory 暗地裡的活動。
在 Alice 和 Bob 的 Run 方法中,秘密數位簽章金鑰傳輸是於下列程式碼陳述式後實作的:
if (4 <= Version)
下列程式碼陳述式負責建立 Alice 和 Bob 的私用 ChannelManager 執行個體:
ChannelManager ChMgr2 = new ChannelManager("server", "PrivateChannel")
ChannelManager ChMgr2 = new ChannelManager("client", "PrivateChannel")
Alice 和 Bob 使用的私用通道 (ChMgr2) 並不是其 Communicator 物件的成員。您可以藉由比較下列兩個程式碼陳述式了解這點:
Alice.ChMgr.SendMessage(dsKeyBlob); // Public channel - fake key
ChMgr2.SendMessage(dsKeyBlob); // Private channel - real key
第一個陳述式所使用的長期 ChannelManager 執行個體 (ChMgr),是在 Run 方法的開頭建立的。這個執行個體是做為 Alice、Bob 和 Mallory 的 Communicator 物件的 Public 成員 (請參閱工作階段概觀一節的步驟 3),一直到工作階段的結尾。第二個陳述式所使用暫存物件的存在時間,則僅足以傳送和接收金鑰,並會在使用後立即處置。
在 Alice 傳送秘密數位簽章金鑰後,Bob 則藉由使用下列陳述式接收金鑰:
DSKey = ChMgr2.ReadMessage();
Alice 和 Bob 會將金鑰儲存做為其 Communicator 物件的私用成員:
Alice.StoreDSKey(DSKey);
Bob.StoreDSKey(DSKey);
這些陳述式也會覆寫假的數位簽章金鑰。
在版本 4 中,Alice 和 Bob 會使用秘密數位簽章金鑰而非假的數位簽章金鑰,簽署金鑰和訊息。版本 4 也會簽署密碼編譯金鑰,並在訊息的數位簽章與訊息不相符時顯示安全性警告。
工作階段的終止 (版本 5)
版本 5 跟版本 4 相同,唯一的不同在於,版本 5 會在發生第一個錯誤時結束工作階段。Alice 在接收到 Bob 的公開密碼編譯金鑰時發生第一個錯誤,並發現到無效的數位簽章。Bob 在接收到 Alice 的公開密碼編譯金鑰時發生第一個錯誤,並且也發現到無效的數位簽章。
其他注意事項
物件處置:C# using 陳述式提供您增強的安全性,是用來封入所有 ChannelManager 和 Communicator 物件的。當這些物件超出範圍時,會立即呼叫其 Dispose 方法,並會釋放所有內部持有的資源。
CNG 範例的限制
CNG 安全通訊範例的目的在於示範 Managed CNG 函式。因此會省略部分功能,包括下列項目:
對所有方法的參數驗證。
廣泛使用 try/catch 區塊。
健全的管道中斷連接探索。
將螢幕輸出記錄到檔案。
加密演算法的動態組態設定性。
數位簽章演算法的動態組態設定性。
傳輸數位信號金鑰給 Bob 的另一種方法。具名管道 PrivateChannel 是簡單的方案,另外還有其他更為複雜的方法。
金鑰的持續性、儲存和擷取。
使用作業系統所產生的數位簽章金鑰。
使用公開金鑰基礎結構 (PKI) 所提供的金鑰。
這些功能牽涉到額外的程式碼複雜度,並且超出這個範例的範圍。
請參閱
概念
Cryptography Next Generation (CNG) 安全通訊範例
變更記錄
日期 |
記錄 |
原因 |
---|---|---|
2008 年 7 月 |
加入主題。 |
資訊加強。 |