Share via


原始程式碼概觀 (CNG 範例)

本概觀提供您 Cryptography Next Generation (CNG) 安全通訊範例中,有關各種程式碼項目之間互動的高階描述。

其中會討論範例的下列各方面:

  • 應用程式

  • 檔案

  • 類別

  • 安全性版本

  • 工作階段概觀

  • 密碼編譯金鑰 (版本 2-5)

  • 透過公用通道交換的數位簽章 (版本 3)

  • 透過私用通道交換的數位簽章 (版本 4)

  • 工作階段的終止 (版本 5)

  • 其他注意事項

  • CNG 範例的限制

應用程式

本範例包含 3 個獨立的主控台應用程式:Alice、Bob 和 Mallory。每個應用程式是建置為獨立的 Visual Studio 專案,並包含一個主要檔案和 3 個共用檔案。下表顯示這些應用程式和其檔案。

應用程式 (專案) 名稱

檔案

Alice

  • Alice.cs (主要檔案)

  • Utilities.cs

  • ChannelManager.cs

  • Communicator.cs

Bob

  • Bob.cs (主要檔案)

  • Utilities.cs

  • ChannelManager.cs

  • Communicator.cs

Mallory

  • Mallory.cs (主要檔案)

  • Utilities.cs

  • ChannelManager.cs

  • Communicator.cs

檔案

下列各節的表格摘要說明每個應用程式所使用的類別和方法,並以出現在原始程式碼中的順序列出。

Alice.cs、Bob.cs 和 Mallory.cs

類別、方法或

全域變數名稱

請使用

CNG_SecureCommunicationExample

整個專案範圍的部分類別。

MyColor

OtherColor

fDisplaySendMessage

全域變數。

Main

每個應用程式的程式進入點。這個方法會處理下列作業:

  • 由 Alice 呼叫時,會自動載入 Bob.exe 和 Mallory.exe。

  • 建立處理迴圈。

  • 呼叫 InitConsole 方法,設定主控台大小、位置和標題。

  • 呼叫 Run 方法。

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 會藉由執行下列步驟,執行要求的工作階段:

  1. Alice 會呼叫 SendChannelName 方法,該方法使用名為 PublicChannel 的通道。她會傳送新通道名稱 (AliceAndBobChannel) 給 Bob。

  2. 如果 fMallory 旗標是設為 true,Mallory 會接聽 PublicChannel 並攔截來自 Alice 的新通道名稱 (AliceAndBobChannel)。接著傳送不同的通道名稱 (AliceAndBobChannel1) 給 Bob。

  3. 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"))
    
  4. Communicator 類別建構函式會接受通道名稱,並建立稱為 ChMgr 的長期公用 ChannelManager 物件:

    ChMgr = new ChannelManager(mode, ChannelName);
    
  5. ChannelManager 建構函式會接受通道名稱,並建立對應的具名管道。

    注意事項注意事項

    此時,Alice 和 Mallory 是透過名為 AliceAndBobChannel 的管道通訊,而 Mallory 和 Bob 則是透過名為 AliceAndBobChannel1 的管道通訊。

    AliceAndBobChannel 和 AliceAndBobChannel1 是長期通道,在安全性案例結束前 (也就是 Run 方法的結尾),都會持續開啟。

  6. fVersion 旗標 (負責控制安全性版本) 和 fMallory 旗標 (負責控制 Mallory 的介入) 的值會決定接下來發生的事:

    在版本 3 中,Alice 會透過 PublicChannel 傳送數位簽章金鑰給 Bob。他們會使用這個數位簽章金鑰來簽署金鑰和訊息。如果 fMallory 是 true,Mallory 會攔截數位簽章金鑰並用來簽署他傳送給 Alice 和 Bob 的金鑰和訊息。

    在版本 4 和 5 中,Alice 會傳送兩個數位簽章金鑰給 Bob。數位簽章金鑰 1 與 Alice 在版本 3 中傳送的金鑰一樣。數位簽章金鑰 2 是 Mallory 不知道的秘密數位簽章金鑰。

  7. Alice 和 Bob 在版本 2 到 5 中,會交換公開密碼編譯金鑰。如果 fMallory 是 true,Mallory 會攔截他們的公開金鑰並以自己的金鑰取代。

  8. Alice 和 Bob 會交換訊息。如果 fMallory 是 true,Mallory 會攔截、變更和重新傳送 Alice 和 Bob 的訊息。

  9. 在 Alice 和 Bob 完成彼此的交談後,您會收到提示,要求您傳送自己的訊息。這可以讓您看到您訊息的加密方式,以及 Mallory 又是如何變更這些訊息。當您完成時,請按 ENTER 將控制權傳回給 Alice。

  10. 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 方法,並會釋放所有內部持有的資源。

  • 編碼方法:在任何情況下傳輸加密資料時,應該將資料編碼為 UTF8Unicode,千萬不要使用 ASCII

CNG 範例的限制

CNG 安全通訊範例的目的在於示範 Managed CNG 函式。因此會省略部分功能,包括下列項目:

  • 對所有方法的參數驗證。

  • 廣泛使用 try/catch 區塊。

  • 健全的管道中斷連接探索。

  • 將螢幕輸出記錄到檔案。

  • 加密演算法的動態組態設定性。

  • 數位簽章演算法的動態組態設定性。

  • 傳輸數位信號金鑰給 Bob 的另一種方法。具名管道 PrivateChannel 是簡單的方案,另外還有其他更為複雜的方法。

  • 金鑰的持續性、儲存和擷取。

  • 使用作業系統所產生的數位簽章金鑰。

  • 使用公開金鑰基礎結構 (PKI) 所提供的金鑰。

這些功能牽涉到額外的程式碼複雜度,並且超出這個範例的範圍。

請參閱

概念

Cryptography Next Generation (CNG) 安全通訊範例

金鑰和訊息的逐步交換 (CNG 範例)

預期的輸出 (CNG 範例)