密碼學在 .NET 組件上的應用

来源:互联网 发布:win7网络红叉不能上网 编辑:程序博客网 时间:2024/06/06 19:11

密碼學在 .NET 組件上的應用

作者:蔡學鏞

2005 年 5 月

本文章簡單地介紹了密碼學在.NET組件上的應用,內容包括了何謂 strong name、簽署的過程、簽署的查驗、Authenticode、Key pair、以及延遲簽署。

Strong Name

.NET 組件(assembly)可以被簽署(sign),成為 signed assembly。被簽署過的組件就具備 strong name,所以也稱為 strong-name(d) assembly,或者 strongly-named assembly。未被簽署的組件就稱為 weak-name(d) assembly,或者 weakly-named assembly。

strong name 包含了四個部分,分別是

  1. 組件名稱:也就是不含副檔名的檔案名稱。
  2. 版本:由四個整數組成,分別是 ...,例如:1.0.0.1413。
  3. culture:用來標示地區與語言。
  4. public key:作為發行公司的識別。

 

這些資訊記錄在metadata中的『Assembly』表格中,如圖 1 所示。請注意,metadata 中使用『locale』來代表 culture,但未來可能會改成『culture』。

圖 1
圖 1

請注意,『Assembly』表格中還多了兩個欄位,分別為 HashAlgId,以及 Flags。其中,HashAlgId 表示此 Assembly 在計算附屬檔案時所使用的 Hash 演算法為何,ECMA 標準將此訂為 0x8004,表示使用 SHA-1 演算法。Flags 用來註記此組件的 side-by-side 執行方式限制為何(所謂的 Side-by-Side 執行,指的是同時執行新舊版本的同一個組件),可以有下面三種限制方式:

  • 此組件不可以在一個 App Domain 中以 side-by-side 的方式執行。
  • 此組件不可以在一個 Process(行程)中以 side-by-side 的方式執行。
  • 此組件不可以在一個 Machine 中以 side-by-side 的方式執行。

被簽署過的組件,可以被放進 GAC 中,讓所有的程式共用它。被簽署過的組件也可以不放進 GAC 中,僅供某個應用程式使用。但是,未被簽署的程式,一定不能被放進 GAC 中,所以只能供某個應用程式使用,這是簽署和未簽署的一個很大的差異。GAC 是 Global Assembly Cache 的縮寫,你可以將 GAC 看成是 .NET 時代的 System32 目錄(用來放置許多共享的 DLL)。

組件的簽署

簽署 .NET 組件的過程,如圖 2 所示:

圖 2
圖 2

先利用 SHA-1 演算法來取得此組件的訊息摘要(message digest,MD),訊息摘要也稱為 Secure Hash、Crypto Hash、或者數位指紋(digital finger print)。訊息摘要是利用 hash 演算法,計算出一個很小、但是又可以代表此組件的資料,這就好像,每個人的指紋雖然很小,但是可以用來代表一個人。

別人如果寫了一個假冒的組件,他也可以利用 SHA-1 演算法來製造出訊息摘要,所以訊息摘要並不足以防止竄改組件或假冒組件。訊息摘要還需要經過 RSA 演算法的處理,來得到數位簽章(digital signature)。RSA 演算法是一種不對稱的加密解密演算法,利用 RSA 加密時,需要 private key。

將數位簽章連同 public key 嵌入到 weakly-named assembly 中,就得到了 signed assembly。在圖 1 中,你可以在 Metadata 的『assembly』表格中看到一個 public key 的欄位,public key 正是放在此處。至於數位簽章的擺放位置,請看圖 3。

圖 3
圖 3

組件的簽署查核

當使用者拿到此組件,執行此組件時,.NET CLR 會對它進行簽章的核對,來確定此組件沒有被竄改過,如圖 4 所示。

圖 4
圖 4

檢查方式如下:

  1. 先將此組件的 public key 以及數位簽章移除,就得到了 weakly-named assembly,將此 weakly-named assembly 經由 SHA-1 演算法得到訊息摘要。
  2. RSA 演算法搭配 public key,可以將數位簽章還原,得到另一個訊息摘要。
  3. 將上面兩個訊息摘要拿來比對,如果完全一致,就表示「此組件的確是由此 public key 的原始擁有者所製造出來的」。

 

假設我們從某個網站取得一個『號稱』A 公司的組件,那麼即使經過上面的步驟,.NET CLR 可以確定此組件和此 public 的擁有者一致,但仍不能確定這是 A 公司的組件,除非你的電腦已經提前知道 A 公司的 public key,而這個 public key 和組件內的 public key 一致。

Authenticode

想要讓組件和所聲稱的發行公司一致,顯然利用上面的作法是不夠的,我們必須採用 Authenticode 技術,來為 PE 檔附上 certificate(認證),就可以對這個組件的來源提出證明。

什麼是 certificate?簡單來說,certificate 是一個檔案,至少包含了下列兩種資訊:

  • public key
  • 此 public key 屬於哪家公司

 

業界定義了一些常用的 certificate 標準,其中以 X.509 最廣為使用。Windows 作業系統支援 X.509,用 .cer 來作為 X.509 certificate 的副檔名。X.509 內包含了:

  • 演算法
  • Key 擁有者的名稱
  • certificate 有效期限
  • public Key

 

除此之外,certificate 的發行者也可以自由地在 certificate 中加入一些額外的資訊。

你所製作出來的認證,必須由信譽良好且知名的認證主管機構(Certification Authority,CA)背書,才具有實際的效力。VeriSign(http://www.verisign.com/)是目前最知名的 CA。

Keys

public key 和 private key 形成一個 key pair。顧名思義,private key 由某公司持有,不對外公開,而 public 則是可以對外公開。.NET Framework SDK 的 sn.exe 可以用來幫助我們產生 key pair。用法如下:

sn.exe –k MyCompany.snk

這個例子會產生一個 MyCompany.snk 的檔案,檔案內包含了 public key 和 private key。此檔案共 596 bytes,前 32 bytes 是 header,接著 128 bytes 是 public key,最後 436 bytes 是 private key。key pair 檔案內包含 private key,所以要小心存放,公司內只有少數一兩個人可以持有這個檔案。

除了『-k』之外,sn.exe 還有許多其他命令列選項,圖 5 整理了其中常見的四個。『-p』從 key pair 檔案中取得 public key 的部分,可以把 public key 交給公司內的軟體開發者,或者放到網路上散播。『-t』將 public key 拿來經由 SHA-1 演算法處理,得到一個 hash 值,再取出 hash 值前面的 8 個 bytes,就得到 public key token。Public key 太長(128 byte),為了簡潔,許多時候會利用 public key token(8 bytes)來代表 public key。『-T』也可以從組件中取出 public key token。

圖 5
圖 5

延遲簽署

許多時候,軟體的開發過程中,需要將組件放到 GAC 中,來進行測試。如果因此將 key pair 交給軟體開發人員,好讓他們隨時可以為組件進行簽署,這麼做很危險,因為軟體開發人員可能會拿 key pair 來做一些不應該的事(例如:將 private key 外流,或者用公司的 private key 來簽署惡意程式)。如果不把 key pair 交給軟體開發人員,而是由公司的 key 持有者來簽署程式,又會把他累垮(一天可能有數十次的簽署要求)。為了解決這個問題,.NET 支援延遲簽署(delay sign),或稱部分簽署(partial sign)。

前面提到過,將數位簽章連同 public key 嵌入到 weakly-named assembly 中,就得到了 signed assembly。如果只有嵌入 public key,但沒有嵌入數位簽章,就是部分簽署。部分簽署的組件可以被部署到 GAC 中。由於部分簽署不需要數位簽章,所以就不需要用到 private key。軟體工程師可以靠 public key 就完成部分簽署。當組件最後測試完成之後,將組件交給 key pair 持有者,此時再將數位簽章放進組件中即可。

結論

透過在組件中採用這些密碼學的技術,.NET 可以有效地解決組件被竄改與假冒的問題,再搭配 .NET CLR 的 CAS(Code Access Security)機制的安全把關,以及各種 verification 機制,.NET 程式的確是比起以前的程式安全多了。

原创粉丝点击